ورود

View Full Version : خواندن داده blob از دیتابیس



JYasProgramer
دوشنبه 28 اردیبهشت 1394, 08:50 صبح
درود بر دوستان
من یه رکوردی دارم و میخوام اونو از دیتابیس واکشی کنم اما حجم یکی از فیلد های اون رکورد 3.7 مگ هستش، از اونجایی که WindowCursor حجم 1 مگ رو برای هر رکورد میتونه ذخیره کنه وقتی که Cursor به اون رکورد 3.7 مگی میرسه برنامه به صورت ناجوانمردانه کرش میکنه
دوستان چگونه میشه این رکورد رو که حجم یکی از فیلداش بالای 1 مگ هست رو بشکنم و اونو قطعه به قطعه بخونم تا برنامه به صورت جوانمردانه اجرا بشه؟؟
در ضمن نمیخوام اون فیلد 3.7 مگی رو در فایلی بریزم و سپس آدرس اون فایل رو در رکرود ذخیره کنم
این سایت هارو هم دیدن کردم اما یا من متوجه نشدم یا من (دوباره) کد رو به درستی به کار نبردم...
این سایت http://stackoverflow.com/questions/12716859/retrieve-large-blob-from-android-sqlite-database
سپاس

pbm_soy
دوشنبه 28 اردیبهشت 1394, 23:19 عصر
همین لینکی که دادید مشکل را حل میکند
درواقع چک میکند فیلد بزرگ باشد آنرا یک مگ یک مگ میخواند
مگه اینکه بیای سه تا فیلد با حجم یک مگ درست کنی و دادها را تیکه تیکه ذخیره کن

JYasProgramer
سه شنبه 29 اردیبهشت 1394, 15:38 عصر
خب دقیقا روش کارش چجوریه من مقداری متوجه نشدم!
من این کد رو زدم اما ارور داد!

String str1 = "Select substr(qObject, 0, 999999) from tblQuestion where id=5";

Field[] dlFieldArr = null;
if (dl2 != null) {
dlFieldArr = dl2.getClass().getDeclaredFields();
}

Cursor c;

if (dl2 != null) {
for (Field fld : dlFieldArr) {
if (fld.get(dl2) != null) {
str1 += " AND " + fld.getName() + "=" + fld.get(dl2);
}
}
}

c = cm.rawQuery(str1, null);

List<dlQuestion> lst = new ArrayList<dlQuestion>();
while (c.moveToNext()) {
dlQuestion dl3 = new dlQuestion();
dl3.qObject = c.getBlob(c.getColumnIndex("qObject"));
lst.add(dl3);
}
c.close();
return lst;

JYasProgramer
سه شنبه 29 اردیبهشت 1394, 15:43 عصر
خطوط بین 3 تا 16 مهم نیستن

pbm_soy
شنبه 02 خرداد 1394, 02:06 صبح
بازم میگم تو اون لینکی که خودتون دادید اصل قضیه گفته شده فقط شما بنا به نیازتون باید استفاده کنید البته به شرطی که درست درک کرده باشید

کد نوشته شده در اون سایت را من سعی میکنم اینجا بازترش کنم (البته من فرصت نکردم چنین کاری آزمایش کنم)

* مورد اول تابع substr است که از یک رشته زیر رشته ای را برای شما برمیگرداند مثلا در حالت زیر
substr(blobcolumn, 1, 1000000)
از متغیر یا فیلد رشته ای blobcolumn از کارکتر یکم به تعداد 1000000 کاراکتر را برای شما برمیگرداند

* مورد دوم دستور زیر است
SELECT id, length(blobcolumn) FROM mytable WHERE length(blobcolumn) > 1000000
رکروردهایی را از جدول به شما میدهد که اطلاعات فیلد موردنظرتون (دراینجا blobcolumn) بیشتر از یک مگابایت است یعنی دستور فوق یک جدول برمیگرداند که دارای دو ستون است (id رکوردی که اطلاعات فیلدش بیشتر از یک مگ و ستون دوم اندازه اطلاعات موجود در فیلد blobcolumn) را میدهد
به این ترتیب شما id تمام رکوردهایی که حجم اطلاعات آن بیشتر از یک مگابایت هستند را پیدا میکنید و همچنین اندازه آن فیلد را هم دارید حالا باید متناسب با اندازه فیلد موردنظر یک یا چند بار دستور select را باید اجرا کنید

* مورد سوم خواندن اطلاعات رکورد مورد نظر بصورت تیکه ، تیکه با دستورات زیر
SELECT substr(blobcolumn, 1, 1000000) FROM mytable WHERE id = 123
SELECT substr(blobcolumn, 1000001, 1000000) FROM mytable WHERE id = 123
دستور اول یک مگابایت اول از فیلد موردنظر از رکورد با id 123 را برای شما برمیگرداند و دستور دوم یک مگابایت دوم فیلد را برمیگرداند تعداد این دستورات باید متناسب با اندازه اطلاعات موجود در فیلد باید باشد (اندازه فیلد برای هر رکورد هم دستور select بخش دوم برای شما میدهد)

pbm_soy
شنبه 02 خرداد 1394, 02:10 صبح
توجه داشته باشید که برای اجرای هر دستور select و یا برای خروجی گرفتن از آن باید شما کرسور مربوط به آن را تعریف کنید و یا حداقل یک برای select اول که دو ستون به شما میدهد یک کرسور جدا و برای select های بعدی یک کرسور تعریف کنید چون ستونهای selectهای بعدی همه شبیه هم هستن و از یک جنس هستند


در کدی که خودتون نوشتید دستور select شما فقط یک مگابایت اول از فیلد مورد نظرتون را برمیگرداند (البته این کار را فقط برای رکورد پانزدهم انجام میدهد id=15 یا رکوردی که id آن برابر 15 باشد) و با بقیه اطلاعات موجود در فیلد موردنظر کاری ندارد باید بررسی میکردید اگر فیلد موردنظرتون داده دیگری هم دارد آنها را هم باید با اجرا کردن دستور Select میخواندید (یعنی شما چندبار دستور select را باید اجرا میکردید) مثلا اگر اطلاعات موجود در فیلد موردنظرتون 3 مگابایت است باید دستور select را 3بار اجرا کنید البته در بخش substr مقادیر صحیح را برای آدرس دهی باید قرار دهید

pbm_soy
شنبه 02 خرداد 1394, 02:20 صبح
قبلا هم گفتم بجای اینکه کل اطلاعات را در یک فیلد ذخیره کنید بیائید چند فیلد (مثلا 3 فیلد) با حجم یک مگابایت در دیتابیستون تعریف کنید و در زمان خواندن آن رکورد دیگر مشکلی نخواهید داشت و مانند یک رکورد معمولی میخوانید و در نهایت مقادیر آن سه فیلد را پس از خواندن در یک متغییر ذخیره میکنید
String myData;
myData = Field1 + Field2 + Field3;
ویا اینکه دستور دوم را کمی منطقی تر مینویسید مثلا اگر field2 مقداری دارد آنرا به myData اضافه کنید و به همین ترتیب برای field3 اینکار را انجام دهید

فکر میکنم این روش کار شما را راحتتر میکند و دردسرهای روش اول را ندارد
بلاخره حجم اطلاعات شما یک محدودیتی دارد! یک مقدار حداکثری برای آن میتوانید پیدا کنید و به همان اندازه و تعداد فیلد (فیلد 1 مگابایتی) تعریف کنید