PDA

View Full Version : ذخیره سازی در فایل



emad_67
پنج شنبه 25 مرداد 1386, 18:29 عصر
سلام
من میخوام یه متغیری از struct یا یه object رو تو یه فایل ذخیره کنم .می خواستم ببینم از چه دستوری باید استفاده کنم ؟

hdv212
پنج شنبه 25 مرداد 1386, 20:25 عصر
باید اونو serialize کنی و در فایل ذخیره کنی، باید NameSpaceهای زیر رو به پروژه ات اضافه کنی :

using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
این یه نمونه کد هست برای ذخیره ی آبجکت lstStoreItems در فایلی به نام StoreItems.sti :

string strFileName = "StoreItems.sti";
FileStream fStream = new FileStream(strFileName,FileMode.Create);
BinaryFormatter binFormat = new BinaryFormatter();

try
{
binFormat.Serialize(fStream,this.lstStoreItems);
}
catch(ArgumentNullException)
{
MessageBox.Show("دسترسی به ذخایر امکان پذیر نیست","خطا ");
}
catch(SerializationException)
{
MessageBox.Show("امکان ذخیره اطلاعات وجود ندارد","خطا ");
}
finally
{
fStream.Close();
}

و اینم کدی هست که میتونی آبجکت ذخیره شده در فایل رو مجددا بازیابی کنی (این قسمت درست برعکس مرحله ی قبله، یعنی تو مرحله ی قبل serialize کردی، اینجا باید deserialize کنی) :

string strFileName = "StoreItems.sti";
FileStream fstream = null;
if(File.Exists(strFileName))
{
try
{
fstream = new FileStream(strFileName,FileMode.Open);

BinaryFormatter binFormat = new BinaryFormatter();
lstStoreItems = (ArrayList)binFormat.Deserialize(fstream);

}
catch(ArgumentNullException)
{
MessageBox.Show("دسترسی به ذخایر امکان پذیر نیست","خطا ");
}
catch(SerializationException)
{
MessageBox.Show("امکان باز یابی اطلاعات وجود ندارد","خطا ");
}
finally
{
fstream.Close();
}
}
else
return;

موفق باشید.

emad_67
پنج شنبه 25 مرداد 1386, 20:49 عصر
خیلی خیلی ممنون دوست عزیز
نمیدونم درست متوجه شدم یا نه ولی آیا این serialize کردن اطلاعات رو به صورت باینری در میاره و بعد تو فایل ذخیره میکنه یا نه؟
یه سوال دیگه هم اینکه lstStoreItems یه شیء از کلاس ArrayList هست؟

hdv212
پنج شنبه 25 مرداد 1386, 23:06 عصر
آیا این serialize کردن اطلاعات رو به صورت باینری در میاره و بعد تو فایل ذخیره میکنه یا نه؟
بله عزیزم، به صورت باینری در فایل ذخیره میشه.

یه شیء از کلاس ArrayList هست؟
نه عزیزم، این کلاسی هست که خودم نوشتم، راستی خوب شد یادم انداختی، قبل از تعریف کلاست، باید خصیصه ی [Serializable] رو در ابتدای تعریف کلاست ذکر کنی، مثل این کد که من در ابتدای تعریف کلاس CStoreItem خودم ذکر کردم :


namespace StoreItem
{
/// <summary>
/// Summary description for Class1.
/// </summary>
[Serializable]
public class CStoreItem
{
private string nm;
private string cd;
private int nmi;
//some code ...
موفق باشید.

emad_67
جمعه 26 مرداد 1386, 01:40 صبح
بازم خیلی ممنون از لطفتون


نه عزیزم، این کلاسی هست که خودم نوشتم،

پس چرا موقع باز گردانی اطلاعات از فایل اونو به شیء کلاس ArrayList تبدیل کردین؟


lstStoreItems = (ArrayList)binFormat.Deserialize(fstream);

مگه نباید به شی ایی از همون کلاسی که بوده تبدیل بشه؟

hdv212
جمعه 26 مرداد 1386, 12:34 عصر
[Serializable] باعث میشه که کلاس شما قابلیت ذخیره شدن در فایل به صورت جریانی از داده ها رو که به صورت سریالی و پشت سرهم در اومدن رو داشته باشه، بدیهی است که زمان نمایش و بازیابی، باید اون رو به صورت جریانی از داده ها (آرایه نمونه ی خوبی میتونه باشه) بارگذاری کنیم، میتونی به جای ArrayList، آرایه ای از بایتها رو در نظر بگیری (byte[])، ولی بهترین گزینه arrayList هست چون هر داده ای رو میتونی در اون نگهداری کنی، در ضمن فکر میکنم بتونی تو همون ArrayList نگهداری کنی و مشکلی پیش نیاد.

emad_67
جمعه 26 مرداد 1386, 13:00 عصر
منظورتون اینه که مثلا اگه چند تا object توی فایل به صورت پشت سر هم ذخره شدن میشه اون ها به شی کلاس Arraylist تبدیل کرد؟ یعنی به فرض بشه به هر شی که تو فایل بوده به صورتی اندیسی در شی کلاس Arraylist دست پیدا کرد؟
من یه کلاسی به اسم person نوشتم و بعد برای باز گردوندن اطلاعات از فایل اونو این جوری نوشتم و مشکل پیدا کرد . منطقی هم هست چون نمیشه یه شیئ از کلاس Arraylist رو ریخت تو شیئ کلاس person


person objperson=(ArrayList)binformat.Deserialize(objfile );

PC2st
جمعه 26 مرداد 1386, 13:56 عصر
اون کدتون رو به شکل زیر تغییر بدید:


ArrayList list=(ArrayList)bin.Deserialize(objfile);

یا به شکل زیر:


person list=(person)bin.Deserialize(objfile);

emad_67
جمعه 26 مرداد 1386, 14:18 عصر
با تشکر
ولی آیا این درسته که وقتی شیئ کلاس person رو ریختیم تو فایل بعد موقع باز خوانی اون رو به Arraylist تبدیل کنیم ؟ اگه درسته حالا که به شی کلاس ArrayList تبدیل شده چه جوری باید به متغیر هایی که تو object تعریف کرده بودم دست پیدا کنم؟
یه سوال دیگه هم دارم:
برای ذخیره چند تا object از یه کلاس باید چیکار کرد البته خودم فکر کنم باید از seek استفاده کنم تا جای رو که تو فایل یه شی باید ذخیره بشه عوض کنم درسته؟ اگه میشه در مورد این seek , منظورم پارامتر هایی که میگیره هست یه توضیحی بدیدن

hdv212
جمعه 26 مرداد 1386, 15:15 عصر
آیا این درسته که وقتی شیئ کلاس person رو ریختیم تو فایل بعد موقع باز خوانی اون رو به Arraylist تبدیل کنیم ؟
اصولا شما هر چیزی رو میتونید در ArrayList ذخیره کنید.

حالا که به شی کلاس ArrayList تبدیل شده چه جوری باید به متغیر هایی که تو object تعریف کرده بودم دست پیدا کنم؟
اینطوری میتونی به کلاس مورد نظرت برگردونی، از طریق حلقه :

ArrayList lst = new ArrayList();
CStoreItem Item = new CStoreItem();
public int Locates(string ItemName)
{
int j=0;
int k=0;
for(int i=0;i<lst.Count;i++)
{
Item = (StoreItem.CStoreItem)lst[i];
if(Item.ItemName == ItemName)
{
j=Item.NumberInput;
k+=j;
}
}

return k;
}

emad_67
جمعه 26 مرداد 1386, 15:38 عصر
با تشکر مجدد
یعنی اگه مثلا 10 شی از کلاسی رو تو فایل ذخیره کرده باشیم با نوشتن این خط


lstStoreItems = (ArrayList)binFormat.Deserialize(fstream);

تمام شی ها داخل شی کلاس ArrayList قرار میگیرن یا باید تک تک اونا را قرار داد؟
در مورد سوال دومی هم که پرسیده بودم میشه بفرمایید که برای ریختن چندتا شی تو فایل باید چیکار منم؟ آیا با نوشتن همون دستوراتی که در بالا گفته بودین میشه چندتا شی رو به صورت پشت سر هم تو فایل ریخت و مجددا باز خوانی کرد یا باید کار دیگه ای بکنم؟

hdv212
جمعه 26 مرداد 1386, 15:47 عصر
تمام شی ها داخل شی کلاس ArrayList قرار میگیرن یا باید تک تک اونا را قرار داد؟
با این کار کل فایلت که شامل هرتعداد آبجکت هست در arrayList قرار میگیره.


برای ریختن چندتا شی تو فایل باید چیکار منم؟
منظورتو درست متوجه نشدم، خب میتونی مثل خود من یه ابجت از ArrayList بسازی و با متد Add اون آبجکت های مورد نظرت رو بهش اضافه کنی و بعد اون رو serialize کنی و در فایل ذخیره کنی.

emad_67
جمعه 26 مرداد 1386, 15:59 عصر
منظورتو درست متوجه نشدم، خب میتونی مثل خود من یه ابجت از ArrayList بسازی و با متد Add اون آبجکت های مورد نظرت رو بهش اضافه کنی و بعد اون رو serialize کنی و در فایل ذخیره کنی.

درسته منطقی هم همینه که شما میگین هست. ولی به طور مثال این کد رو ببینید
الان می خوام این کد 10 تا عدد رو بریزه تو فایل. ولی به جای اعداد فرض کنید 10 شی داریم
این برای ذخیره کردن


privatevoid button1_Click(object sender, EventArgs e)
{
FileStream objfile = newFileStream("c:\\intiger.dat", FileMode.Create);
BinaryFormatter binformat = newBinaryFormatter();
for (int i = 0; i < 10; i++)
{
objfile.Seek(i * sizeof(int), SeekOrigin.Begin);
binformat.Serialize(objfile, i);
}
objfile.Close();
}

و اینم برای باز خوانی از فایل


privatevoid button2_Click(object sender, EventArgs e)
{
int a;
FileStream objfile = newFileStream("c:\\intiger.dat", FileMode.Open);
BinaryFormatter binformat = newBinaryFormatter();
for (int i = 0; i < 10; i++)
{
objfile.Seek( i*sizeof(int), SeekOrigin.Begin);
a=(int)binformat.Deserialize(objfile);
MessageBox.Show(a.ToString());
}
}

البته کد دوم مشکل داره که نفهمیدم درست مشکلش کجاست اگه لطف کنید ببینید مشکلش چیه ممنون میشم .
البته نمیدونم serialize کردن برای شی هاست یا در مورد اعداد هم میشه استفاده کرد .

PC2st
جمعه 26 مرداد 1386, 16:21 عصر
اصولا شما هر چیزی رو میتونید در ArrayList ذخیره کنید.

با این کار کل فایلت که شامل هرتعداد آبجکت هست در arrayList قرار میگیره.
جناب hdv212 فکر کنم سوء تفاهمی پیش اومده :) با این جوابها و سوالها، ایشون فکر میکنند که شما یک شیئ از نوع person رو Serialize کردید و موقع خواندن آن از فایل، آنرا بصورت یک شیئ از نوع ArrayList میخونید :)





ولی آیا این درسته که وقتی شیئ کلاس person رو ریختیم تو فایل بعد موقع باز خوانی اون رو به Arraylist تبدیل کنیم ؟
خیر. همچنین چیزی نمیشه انجام داد.


تمام شی ها داخل شی کلاس ArrayList قرار میگیرن یا باید تک تک اونا را قرار داد؟

اصلا نمیشه! باید تک تک اونها رو با متد Deserialize بگیرید.


در مورد سوال دومی هم که پرسیده بودم میشه بفرمایید که برای ریختن چندتا شی تو فایل باید چیکار منم؟
به مثال زیر توجه کنید، در مثال زیر سه شیئ از نوع person رو Serialize میکنیم:


formatter.Serialize(fstream, obj1);
formatter.Serialize(fstream, obj2);
formatter.Serialize(fstream, obj3);

و در کد زیر، اون اشیاء رو از فایل، دریافت میکنید:


obj1 = (person)formatter.Deserialize(fstream);
obj2 = (person)formatter.Deserialize(fstream);
obj3 = (person)formatter.Deserialize(fstream);

PC2st
جمعه 26 مرداد 1386, 16:37 عصر
البته نمیدونم serialize کردن برای شی هاست یا در مورد اعداد هم میشه استفاده کرد .
برای اعداد هم میشه.

منظورتون رو از این خط کد نفهمیدم، میخواید چیکار کنید؟


objfile.Seek( i*sizeof(int), SeekOrigin.Begin);

emad_67
جمعه 26 مرداد 1386, 16:56 عصر
نمیدونم درست فهمیدم یا نه ولی فکز کنم باید این seek جای جریان رو تغییر بده( یعنی اون بایتی که متغییر باید از اون جا write بشه رو تغییر میده) توی این خط


objfile.Seek( i*sizeof(int), SeekOrigin.Begin);

مثلا وقتی i=0 باشه مقدار داخل seek 0 میشه و باید عدد در ابتدای فایل write بشه و حالا وقتی که i=1 میشه در واقع مقدار داخل seek میشه 4 ( 4*1) و باید عدد روی 4 امین بایت فایل نوشته بشه درسته؟ و به همین ترتیب تا آخر یعنی اعداد 1 تا 10 به ترتیب توی فایل ذخیره میشن
در مورد کدی هم که داده بودین
من تو کلاس person یه متغیر رشته ای به عنوان name تعریف کردم و سه تا شی ساختم البته با name های مختلف ولی وقتی این کد:


obj1 = (person)formatter.Deserialize(fstream);
obj2 = (person)formatter.Deserialize(fstream);
obj3 = (person)formatter.Deserialize(fstream);

رو نوشتم فقط 3 بار name اولین شی ایی رو که ذخیره کرده بودم چاپ میکنه یعنی فکر میکنم که هر بار از ابتدای فایل اطلاعات رو می خونه

hdv212
جمعه 26 مرداد 1386, 17:46 عصر
privatevoid button1_Click(object sender, EventArgs e)
{
FileStream objfile = newFileStream("c:\\intiger.dat", FileMode.Create);
BinaryFormatter binformat = newBinaryFormatter();
for (int i = 0; i < 10; i++)
{
objfile.Seek(i * sizeof(int), SeekOrigin.Begin);
binformat.Serialize(objfile, i);
}
objfile.Close();
}

عزیزم، Serialize رو چرا توی حلقه گذاشتی ؟
با objfile.Seek چکار داری ؟
به جای objfile یه آبجکت از arraylist بساز، و در حلقه، فقط متد Add آبجت arrayList رو فراخوانی کن و در خط اخر و خارج از حلقه، متد Serialize رو فراخوانی کن و آبجکت ArrayList رو بهش پاس کن، اینطوری :


privatevoid button1_Click(object sender, EventArgs e)
{
FileStream objfile = newFileStream("c:\\intiger.dat", FileMode.Create);
BinaryFormatter binformat = newBinaryFormatter();
ArrayList lst = new ArrayList();
for (int i = 0; i < 10; i++)
{
lst.Add(i * sizeof(int));
}
binformat.Serialize(objfile, lst);
objfile.Close();
}

برای بازیابی هم، اینطوری :

privatevoid button2_Click(object sender, EventArgs e)
{
ArrayList lst = new ArrayList();
FileStream objfile = newFileStream("c:\\intiger.dat", FileMode.Open);
BinaryFormatter binformat = newBinaryFormatter();
lst = (ArrayList)binformat.Deserialize(objfile);
}
واسه چی از حلقه استفاده کردی ؟ تمام این کارها با ArrayList انجام شد، در صورت نیاز باید به صورت دستی اونو به آبجکت مورد نظرت تبدیل کنی(اینجا بایستی از حلقه استفاده کنی)

emad_67
جمعه 26 مرداد 1386, 17:57 عصر
درسته روش منطقی ، همین روشی هست که شما میگید ولی من می خواستم جوری برنامه رو بنویسم که که شی ایی از نوع Arraylist رو که حاوی همه اشیا یا اعداد هست رو ذخیره نکنم . یعنی تک تک ، اعداد رو بریزم تو فایل ( فقط جهت یاد گیری ولی روش اصلی همین روشی هست که شما میگید)
باز هم خیلی ممنون:چشمک:

PC2st
جمعه 26 مرداد 1386, 22:44 عصر
رو نوشتم فقط 3 بار name اولین شی ایی رو که ذخیره کرده بودم چاپ میکنه یعنی فکر میکنم که هر بار از ابتدای فایل اطلاعات رو می خونه
هر بار از ادامه میخونه...

نیازی به تکه کد زیر نیست:


objfile.Seek( i*sizeof(int), SeekOrigin.Begin);

چون خودش، ادامه داده ها رو در ادامه فایل میریزه.