PDA

View Full Version : فایل باینری یا فایل متنی ؟



بیتافرهی
شنبه 18 اسفند 1386, 12:13 عصر
سلام دوستان
1-ا ول من یه سوال اساسی دارم؛چه موقع از فایل باینری و چه موقع از فایل متنی استفاده کنم؟؟؟
2- دوم اینکه من یه برنامه نوشتم که البته ارور نداره ولی جواب عددی درست هم نمیده:
شرح برنامه:برنامه ای که تعدادی عدد راخوانده در یک فایل باینری یا متنی قرار دهد(البته من خودم با هدوش را نوشتم ولی باز هم نتیجه نگرفتم.!!)سپس اعداد را از فایل خوانده و آنها را مرتب کند(من خودم اعداد مرتب شده را در آرایه ی پویا قرار دادم)سپس اعداد مرتب شده را نمایش دهد.
من کد برنامه را براتون میذارم.خواهش می کنم،بگید اشکالم کجاست .:عصبانی++::گریه:

3-اگه فایلم متنی بود چه فرقی در دستوراتم می کرد؟

BitMap
شنبه 18 اسفند 1386, 13:47 عصر
فرق فایل باینری و متنی در این است که در فایل باینری هرچیز آنطور که هست ذخیره میشه.مثلا وقتی مقدار صحیص (int( 5 رو توی یک فایل باینری مینویسی همان مقدار 5 در فایل ذخیره میشه ولی در فایل متنی همه چیز بصورت رشته ذخیره میشه ، یعنی همون عدد 5 بصورت '5' یعنی مقدار اسکی معادل کاراکتر 5 ذخیره میشه.
شما توی این برنامه فایل رو بصورت باینری باز کردید ولی با آن مثل یک فایل متنی رقتار می کنید.
در واقع شما همه چیز را با هم مخلوط کردید.
فایل را برای نوشتن بصورت باینری باز کردید اعداد را بصورت رشته در آن نوشتید ، ار تابع fputs استفاده کردید سپس فایل را بصورت متنی باز کردید تا از آن بخوانید !!!!

برای رفع اشکالات باید خیلی بیشتر در مورد ورودی و خروجی فایل اطلاعات کسب کنید

ICEMAN
یک شنبه 19 اسفند 1386, 08:47 صبح
شما توی یه فایل متنی وقتی 4 تا record داری مثلا:
1 ali 2000
2 majid 3000
3 elyas 5000
وقتی بخوای مثلا ali و به اسمی تغییر بدی که از 3 کاراکتر بیشتر کل فایل به هم میریزه !
ولی توی یه فایل Binary برای هر Field طول در نظر بگیری
شاید یکی از مهم ترین دلایلش این باشه

emad_67
یک شنبه 19 اسفند 1386, 11:41 صبح
منم یه مقدار تو کاربرد فایل های باینری مشکل دارم. مثلا فرق بین 2 تعریف زیر از فایل چیه؟


fstream inout("test.dat", ios::in | ios::out |ios::binary);


fstream inout("test.dat", ios::in | ios::out);

نحوه خوندن و نوشتن که هیچ فرقی نمیکنه پس چه موقع از باینری استفاده میشه؟ مگه کلا اطلاعات در فایل به صورت باینری ذخیره نمیشه پس کلمه binary که در تعریف فایل می نویسن چیه؟

Nima_NF
یک شنبه 19 اسفند 1386, 22:39 عصر
مگه کلا اطلاعات در فایل به صورت باینری ذخیره نمیشه پس کلمه binary که در تعریف فایل می نویسن چیه؟
در فایل های متنی اسکی همه چیز به صورت کارکتر (در یک بایت) ذخیره می شود ، یعنی عدد 666 در 3 بایت و در هر بایت یک عدد 6 ذخیره می شود.
اما در فایل های باینری عدد 666 به صورت یک عدد word یعنی در 2 بایت ذخیره می شود.

فایل های متنی شامل کارکتر انتهای فایل هستند و در مواقعی که یونیکد هستند نیز در ابتدا یا انتها باید شامل کارکتر مخصوص آن باشد تا توسط نرم افزار های مربوط به خواندن آن ها و یا حتی برای نمایش در Textbox ها و غیره به صورت یک استاندارد متنی به راحتی نمایش داده شوند. (چرا که هر بایت یک کارکتر هست و نیاز به قانون خاصی ندارد)
از طریق توابع ساخت فایل خود سیستم عامل های 32 بیتی ، اگر قوانین فوق رعایت شود ، فایل شما متنی است در غیر این صورت باینری.

اما در فایل باینری (تمامی فایل ها غیر از نوع فوق) فرد یا نرم افزاری که می خواهد دیتاها را از فایل بخواند باید بداند که اطلاعات در کدام بایت و یا بیت از فایل قرار دارد ، یعنی قانون خواندن را نیز بداند:
مثلا فرض کنید که فایل فقط شامل یک بایت اطلاعات هست ، در حالی که شامل سه عدد 2 و 1 و 2 باشد که برای کار خاصی استفاده شده و برای بدست آوردن هر عدد باید 2 بیت از فایل را بخواند ، نه مثل فایل متنی یک بایت را.

بیتافرهی
دوشنبه 20 اسفند 1386, 06:25 صبح
ممنون از توجهتون.ولی کسی نگفت اشکال برنامه ی من کجاست؟من این برنامه را با VC++
کامپایل کردم.ارور نداشت،ولی جوابشم مد نظر من نبود.کسی می تونه بگه اشکالم کجاست؟فایل اجراییشو گذاشتم.درقسمت چاپ اعدادSORT شده اعداد را به صورت کد نشان می دهد.چرا؟؟

emad_67
دوشنبه 20 اسفند 1386, 06:51 صبح
اما در فایل باینری (تمامی فایل ها غیر از نوع فوق) فرد یا نرم افزاری که می خواهد دیتاها را از فایل بخواند باید بداند که اطلاعات در کدام بایت و یا بیت از فایل قرار دارد ، یعنی قانون خواندن را نیز بدان
بنابراین در 2 تعریفی که در بالا برای ساختن یک فایل نوشتم با فرض اینکه قرار باشه یه شی از کلاس در فایل ذخیره بشه، نباید با هم فرقی داشته باشند درسته؟

اما در فایل های باینری عدد 666 به صورت یک عدد word یعنی در 2 بایت ذخیره می شود.
میشه در مورد یک کلمه یا همون word در حافظه هم توضیح بدی که به چه معنی هست.
با تشکر

ICEMAN
دوشنبه 20 اسفند 1386, 08:25 صبح
بنابراین در 2 تعریفی که در بالا برای ساختن یک فایل نوشتم با فرض اینکه قرار باشه یه شی از کلاس در فایل ذخیره بشه، نباید با هم فرقی داشته باشند درسته؟

میشه در مورد یک کلمه یا همون word در حافظه هم توضیح بدی که به چه معنی هست.
با تشکر
اون word فکر نکنم کلمه باشه یه data type از


typedef unsigned int WORD;

اگه اشتباه میکنم بهم بگید
http://www.cplusplus.com/doc/tutorial/other_data_types.html

ممنون

Nima_NF
دوشنبه 20 اسفند 1386, 13:25 عصر
بنابراین در 2 تعریفی که در بالا برای ساختن یک فایل نوشتم با فرض اینکه قرار باشه یه شی از کلاس در فایل ذخیره بشه، نباید با هم فرقی داشته باشند درسته؟

میشه در مورد یک کلمه یا همون word در حافظه هم توضیح بدی که به چه معنی هست.
با تشکر
منظورتان را در مورد ذخیره یک شئی از کلاس متوجه نشدم.
همان طور که توضیح دادم در یک فایل متنی ممکن است سایر کارکتر های مورد نیاز هم علاوه بر دیتای شما به آن اضافه شود ، مثلا کارکتر انتهای هر خط و غیره ...

در مورد word منظور یک عدد 16 بیتی یا در ++C همان بدون علامت short است که تا عدد 65536 را در 2 بایت می تواند ذخیره کند (اما در متنی در 5 کارکتر/بایت) ، یا در ویندوز :



typedef unsigned short WORD;

با توجه به مشغله بسیار ، لطفا در صورت امکان پاسخ مشکل برنامه سوال کننده را هم بدهید ،
تشکر

emad_67
دوشنبه 20 اسفند 1386, 18:02 عصر
ممنون از توجهتون.ولی کسی نگفت اشکال برنامه ی من کجاست؟من این برنامه را با VC++
کامپایل کردم.ارور نداشت،ولی جوابشم مد نظر من نبود.کسی می تونه بگه اشکالم کجاست؟فایل اجراییشو گذاشتم.درقسمت چاپ اعدادSORT شده اعداد را به صورت کد نشان می دهد.چرا؟؟
در این قسمت ها مشکل داره:
در حلقه while اول، خط i++ رو به آخر حلقه منتقل کنید یعنی به این شکل:


while(1)
{
printf("enter number %d :",i+1);
gets(num);
if(!num[0] ) //enter baraye tavaghof vorud info be file
break;
strcat(num,"\n"); //enter ra ham be info file ezafe konad.
fputs (num,in);
i++; //counter
}

علتش هم اینه که مثلا وقتی کاربری بدون وارد کردن عدد enter رو میزنه نباید به i یک واحد اضافه بشه که در کد شما این کار انجام میشد که بعدا در تخصیص حافظه آرایه مشکل ایجاد میکرد.
مشکل دیگه هم که باعث اشتباه نمایش داده شدن مقادیر بعد از bubble sort میشه به خاطر اینه که j++ رو در حلقه while دوم ننوشتین. به این شکل اصلاح کنید:


while(!feof(in))
{
printf("%s",num); //zemn namayesh info baraye karbar,anha ra dar arraye mirizad.
arr[j]=atoi(num);
fgets(num,9,in);
j++;

}

emad_67
دوشنبه 20 اسفند 1386, 18:18 عصر
منظورتان را در مورد ذخیره یک شئی از کلاس متوجه نشدم.برای ساده تر شدن یه مثال با struct میگم.
مثلا فرض کنید همچین ساختاری داریم:


struct person
{
char name[10];
int num;
};
برای ذخیره اون در فایل من اینجوری نوشتم:


fstream inout("test.txt", ios::in | ios::out | ios::binary);
person p;
cin>>p.name>>p.num;
inout.seekp((p.num-1)*sizeof(person));
inout.write((char *)(&p),sizeof(person));
حالا سوالم اینه که اگه از تعریف فایل قسمت binary رو حذف کنم آیا در نحوه ذخیره شدن فرقی داره یا نه؟ یعنی به این شکل بنویسم:


fstream inout("test.txt", ios::in | ios::out);
عملا در خوندن این نوع فایل ها چه binary قرار داده بشه و چه نشه مشکلی پیش نمیاد.
در مورد صحبت دوتا دوستی هم که در ابتدا جواب دادن من اومدم و یه فایل رو به صورت باینری باز کردم و در اون متن ذخیره کردم و مشکلی هم تو خوندنش پیش نیومد.

Nima_NF
دوشنبه 20 اسفند 1386, 22:16 عصر
عملا در خوندن این نوع فایل ها چه binary قرار داده بشه و چه نشه مشکلی پیش نمیاد.
در مورد صحبت دوتا دوستی هم که در ابتدا جواب دادن من اومدم و یه فایل رو به صورت باینری باز کردم و در اون متن ذخیره کردم و مشکلی هم تو خوندنش پیش نیومد.وقتی خواندن / نوشتن فقط به همین مسائل ساده محدود باشد ، بله فرق چندانی نمی کند ، اما در بحث های پیشرفته تر (از جمله همان ذخیره بیتی دیتا ها) کاملا متفاوت هست و یا مثلا برای یک نمونه بسیار ساده یعنی برای دو فایل متنی که یکی به صورت اسکی هست و دیگری به صورت یونیکد می باشد. برای فایل اسکی هر دو روش قابل استفاده هست ولی در مورد یونیکد در هر حال اطلاعات متفاوت است.

سه فایل text زیر را دریافت کنید (هر سه شامل حروف انگلیسی هستند) و ببینید که هر سه یک چیز هستند ولی نحوه خواندن آن ها متفاوت هست. حجم فایل اسکی 14 بایت هست ، حجم فایل unicode1 دو برابر فایل اسکی به علاوه 3 بایت اضافی برای تشخیص یونیکد بودن می باشد (30 بایت) و حجم فایل unicode2 نیز برابر فایل اسکی به علاوه 3 بایت ابتدایی اضافی هست (17 بایت).

حتی شاید کسی بخواهد کارکتر بی معنایی را در انتهای فایل متنی برای هدف خاصی اضافه کند ؛ اگر شما آن را به صورت متنی بخوانید شاید حرف A معادل اسکی آن به شما نشان داده شود ، در حالی که مفهوم آن چیز دیگری باشد.

ICEMAN
سه شنبه 21 اسفند 1386, 09:12 صبح
fstream inout("test.txt", ios::in | ios::out | ios::binary);
person p;
cin>>p.name>>p.num;
inout.seekp((p.num-1)*sizeof(person));
inout.write((char *)(&p),sizeof(person));



سلام ...
میتونی از Cast ها هم استفاده کنی interpret_cast هم برای خوندن هم برای نوشتن


outCredit.seekp( ( client.getAccountNumber() - 1 ) *
sizeof( ClientData ) );
outCredit.write( reinterpret_cast< const char * >( &client ),
sizeof( ClientData ) );

inCredit.read( reinterpret_cast< char * >( &client ),
sizeof( ClientData ) );

client یه کلاس هست که برای خوندن و نوشتن و ... استفاده شده
این توضیحات رو هم به نقل از کتاب C++ How to program اینجا نقل میکنم چون هم زیاد و منم زیاد قدرت بیانم
خوب نیست ( فقط چون فکر کردن ممکن مفید باشه اینجا میزارم )


Converting Between Pointer Types with the reinterpret_cast Operator
Unfortunately, most pointers that we pass to function write as the first argument
are not of type const char *. To output objects of other types, we must convert the
pointers to those objects to type const char *; otherwise, the compiler will not compile calls
to function write. C++ provides the reinterpret_cast operator for cases like this in which a pointer
of one type must be cast to an unrelated pointer type. You can also use this cast operator to convert
between pointer and integer types, and vice versa. Without a reinterpret_cast, the write statement that
outputs the integer number will not compile because the compiler does not allow a pointer of type
int * (the type returned by the expression &number) to be passed to a function that expects an
argument of type const char *as far as the compiler is concerned, these types are incompatible.

A reinterpret_cast is performed at compile time and does not change the value of the object to which
its operand points. Instead, it requests that the compiler reinterpret the operand as the target type
(specified in the angle brackets following the keyword reinterpret_cast). In Fig. 17.12, we use
reinterpret_cast to convert a ClientData pointer to a const char *, which reinterprets a ClientData
object as bytes to be output to a file. Random-access file-processing programs rarely write a single
field to a file. Normally, they write one object of a class at a time, as we show in the following
examples.

emad_67
سه شنبه 21 اسفند 1386, 11:57 صبح
ممنون دوست عزیز منم بحث فایل ها رو از روی همین کتاب خوندم ولی برای کوتاه تر شدن از reinterpret استفاده نکردم
به هر حال ممنون