чтение и запись изображений в базу данных sqlite для iphone

<p>я установил базу данных sqlite, которая в настоящее время отлично читает и пишет <code>nsstring</code>s. я также хочу сохранить изображение в базе данных и вспомнить его позже. я немного прочитал об использовании <code>nsdata</code> и кодировании изображения, но я не совсем уверен, каков синтаксис того, что я хочу сделать. любые фрагменты кода или примеры будут с благодарностью. </p><p>мой текущий процесс выглядит следующим образом: <code>uiimagepickercontroller</code> -> user выбирает изображение из фотографий -> selectedimage устанавливается на экземпляр <code>uiimageview</code> -><strong> теперь я хочу взять это изображение и сохранить его в бд </strong></p><p>я должен упомянуть, что этот звонок в конечном итоге будет заменен звонком на удаленный сервер. не уверен, что это влияет на производительность.</p>

<p>один из вариантов (и обычно предпочитаемый при работе в sql) - записать изображение в файл в системе и сохранить путь (или какой-либо другой вид идентификатора) в базе данных.</p>

<p>вам нужно будет преобразовать uiimage, размещенный в вашем uiimageview, в двоичный blob для хранения в sqlite. для этого вы можете использовать следующее:</p><pre><code>nsdata *dataforimage = uiimagepngrepresentation(cachedimage); sqlite3\_bind\_blob(yoursavingsqlstatement, 2, [dataforimage bytes], [dataforimage length], sqlite\_transient); </code></pre><p>это сгенерирует png-представление вашего изображения, сохранит его в экземпляре nsdata, а затем свяжет байты из nsdata как blob для второго аргумента в вашем запросе sql. используйте uiimagejpegrepresentation в приведенном выше, чтобы сохранить в этом формате, если хотите. вам нужно будет добавить столбец blob в соответствующую таблицу в вашей базе данных sqlite.</p><p>чтобы получить это изображение, вы можете использовать следующее:</p><pre><code>nsdata *dataforcachedimage = [[nsdata alloc] initwithbytes:sqlite3\_column\_blob(yourloadingsqlstatement, 2) length: sqlite3\_column\_bytes(yourloadingsqlstatement, 2)]; self.cachedimage = [uiimage imagewithdata:dataforcachedimage]; [dataforcachedimage release]; </code></pre>

<p>apple не рекомендует хранить blob в базах данных sqlite, размер которых превышает ~ 2 килобайта.</p><p>sqlite организует базы данных в страницы. каждая страница имеет размер 4 килобайта. когда вы читаете данные из файла базы данных sqlite, он загружает эти страницы во внутренний кеш страниц. на iphone я думаю, что этот кэш по умолчанию имеет размер 1 мегабайт. это делает чтение соседних записей очень быстрым, потому что они, вероятно, уже будут в кеше страницы.</p><p>когда sqlite считывает вашу запись базы данных в память, она читает всю запись и все страницы, которые она занимает. поэтому, если ваша запись содержит blob, она может занимать много страниц, и вы будете извлекать существующие страницы из кэша и заменять их страницами своей записи blob.</p><p>это не так уж плохо, если вы просто просматриваете и загружаете все свои blob-объекты, чтобы что-то с ними сделать (например, отобразите их). но если, скажем, вы сделали запрос, в котором вы просто хотели получить некоторые данные, которые находятся в той же строке, что и blob, этот запрос был бы намного медленнее, чем если бы запись не содержала большой blob.</p><p>поэтому, как минимум, вы должны хранить данные blob в отдельной таблице. например:</p><pre><code>create table blobs ( id integer primary key, data blob ); create table photos ( id integer primary key, name text, blob\_id integer, foreign key(blob\_id) references blobs(id) ); </code></pre><p>или, что еще лучше, храните данные blob в виде файлов вне базы данных sqlite.</p><p>обратите внимание, что можно изменить размер кэша страницы с помощью <a href="http://www.sqlite.org/pragma.html">операторов sql pragma</a> (если вы не используете coredata).</p>

<p>запись изображения в бд sqlite</p><pre><code>if(myimage != nil){ nsdata *imgdata = uiimagepngrepresentation(myimage); sqlite3\_bind\_blob(update\_stmtement, 6, [imgdata bytes], [imgdata length], null); } else { sqlite3\_bind\_blob(update\_stmtement, 6, nil, -1, null); } </code></pre><p>чтение из бд sqlite:</p><pre><code>nsdata *data = [[nsdata alloc] initwithbytes:sqlite3\_column\_blob(init\_statement, 6) length:sqlite3\_column\_bytes(init\_statement, 6)]; if(data == nil) nslog(@"no image found."); else self.pictureimage = [uiimage imagewithdata:data]; </code></pre>

<p>лучше всего сжимать изображение и сохранять его в базе данных или файловой системе. если вам не важно разрешение изображения, вы можете изменить размер изображения, используя:</p><pre><code> uigraphicsbeginimagecontext(newsize); [image drawinrect:cgrectmake(0,0,newsize.width,newsize.height)]; uiimage* newimage = uigraphicsgetimagefromcurrentimagecontext(); uigraphicsendimagecontext(); </code></pre><p>после этого вы можете использовать <code>uiimagejpegrepresentation</code> для изображений jpeg со значением «0» для максимального сжатия. или вы можете использовать <code>uiimagepngrepresentation</code> для изображений png</p>

<p>вы должны сначала написать изображение в файловой системе. а затем возьмите путь к изображению и сохраните этот путь к изображению (url) как text в sqlite. </p>