PDA

View Full Version : خواندن/نوشتن از/در فایل در دو حالت متنی و باینری



khafan_bat
یک شنبه 16 آبان 1389, 23:45 عصر
با سلام و خسته نباشید

من هنوز درک نکردم این قضیه رو !! نحوه ی دقیق نوشتن و خواندن تو فایل ! خسته شدم


1 ) چه فایل رو در حالت باینری باز کنیم و چه در حالت متنی وقتی کاراکتر به کاراکتر در فایل می نویسیم بنابراین بایت به بایت در فایل نوشته ( یا خوانده ) می شود . پس بین دو حالت تفاوتی وجود نخواهد داشت . من تست کردم ( پس باینری باز کردن و کاراکتر به کاراکتر نوشتن بی معنی است )







#include <iostream>
#include <conio.h>
#include <fstream>
#include <string>

using namespace std;

int main(int argc,char *argv[])
{
char ch;
system("cls");

// ------------------------------------------------

ofstream out("test.txt",ios::binary);
if(!out) {
cout << "Cannot open file.";
exit(0);
}
cout << "Enter charachters ($ and Enter to end:)\n";
do {
cin.get(ch);
out.put(ch);
} while(ch!='$');
out.close();

// ------------------------------------------------

ifstream in("test.txt");
cout << "\nOutput from file :\n";
in.get(ch);
while(!in.eof())
{
cout<<ch;
in.get(ch);
}
in.close();

// ------------------------------------------------

getch();
return 0;
}





2 ) وقتی رشته رشته در فایل می نویسیم ( یا میخوانیم ) حداکثر طول خواندن ما معلوم است ( طول متغیر استرینگ ) و همچنین با جدا کردن رشته ها با استفاده از space کار راحت تر نیز خواهد شد . اما من در تحلیل کد زیر مانده ام . چون از یک رشته عدد از فایل خوانده میشود اما در یک متغیر صحیح ذخیره میشود . . !! آیا این وسط تبدیلی صورت می گیرد ؟ ( در حالت های مد باینری و متنی تشریح تحلیل شود !! )








include <iostream>
#include <conio.h>
#include <fstream>
#include <string>

using namespace std;

int main(int argc,char *argv[])
{
char name[21];
int number;
float ave;
system("cls");

// -------------------------------------------------------

ofstream Fout("list.txt",ios::binary);
if(!Fout) {
cout << "Cannot open file.";
exit(0);
}
cout << "Enter student name , number and average(Ctr+z to end:)\n";
while( cin >> name >> number >> ave )
{
Fout << name << ' ' << number << ' ' << ave << ' ' ;
}
Fout.close();

// -------------------------------------------------------

cout<<endl<<endl<<endl;
cout << name <<" "<< number <<" "<< ave << endl;
system("cls");

// -------------------------------------------------------
ifstream Fin("list.txt");
if(!Fin) {
cout <<"Cannot open file. ";
getch();
exit(0);
}

while(Fin >> name >> number >> ave)
{
cout << name <<" "<< number <<" "<< ave << endl;
}
Fin.close();
cout << name <<" "<< number <<" "<< ave << endl;
getch();
return 0;
}


3 ) خواندن ( یا نوشتن ) در فایل توسط رکورد به چه صورت است ؟ ( فکر کنم سوالات قبلی پاسخ داده شوند این مسئله نیز حل شود )

با تشکر از تمامی اساتید

hi level hdd
چهارشنبه 19 آبان 1389, 12:16 عصر
دوست عزیز
نوع فایل متنی رو با یک فایل text و یک عکس تست کن تا فرق دو حالت متنی و باینری رو متوجه بشی.
در باره گرفتن یک رشته و برگرداندن نوع صحیح فکر کنم تعداد کاراکتر های خوانده شده را بر میگرداند.مثلا وقتی آخر فایل هستی و میخوای 10 کاراکتر بخوانی برنامه عدد 0 را برمیگرداند تا بگویید آخر فایل هستی.اگه سوال داشتی بپرس

khafan_bat
پنج شنبه 20 آبان 1389, 22:41 عصر
تفاوت بین فایل های متنی و باینری رو میدونم اما اون حالت هایی رو که گفتم نمیتونم برای خودم تحلیل کنم .

sh4mid
شنبه 22 آبان 1389, 02:00 صبح
سلام


1 ) چه فایل رو در حالت باینری باز کنیم و چه در حالت متنی وقتی کاراکتر به کاراکتر در فایل می نویسیم بنابراین بایت به بایت در فایل نوشته ( یا خوانده ) می شود . پس بین دو حالت تفاوتی وجود نخواهد داشت . من تست کردم ( پس باینری باز کردن و کاراکتر به کاراکتر نوشتن بی معنی است )

چطور این موضوع رو امتحان کردید؟ :متفکر::متفکر:
ببینید فرق فایل متنی با باینری به زبان ساده در اینه که فایل باینری کمی خنگ تر از فایل متنی هست ، هر کاراکتری که بهش بدید رو در خودش ذخیره می کنه ، اما فایل متنی باید یکم دستکاری بشه تا توسط انسان قابل خوندن باشه :قهقهه::قهقهه:
بریم سروقت اولی
من عبارت hello رو وارد می کنم دکمه Enter رو فشار میدم بعدش $ رو می زنم
یک بار با حالت باینری و یک بار در حالت متنی فایل رو ذخیره می کنم ، حالا ببینیم فرقش چیه؟
فرض کن اسم اولی رو می گذاریم Bin.txt و دومی رو Text.txt جفتشون رو با Notepad باز کن یک فرق کوچولو دارن :متفکر::متفکر:
چرا اینجوری شد تو یکی علامت $ تو خط بعدی هست تو یکی جلوی hello ؟:متفکر::متفکر:
خب با یک چیزی مثل WinHex تو فایل رو باز کن
برای Text.txt داریم


68 65 6C 6C 6F 0D 0A 24
h e l l o \n $
برای Bin.txt داریم


68 65 6C 6C 6F 0A 24
h e l l o \n $

فرقشون همان کاراکتر 0X0D هست ، تو C کاراکتر خط جدید یا همون 'n\' برابر است با 0x0A ، اما در فایل متنی به صورت 'r\n\' ذخیره شده ، بحث اینجاست که تو Windows کاراکتر خط جدید به صورت 0x0D0A هست تو خانواده Unix به صورت 0X0A و در Mac به صورت 0X0D (تا حالا سعی کردی یک فایل Source Code لینوکس رو با Notepad باز کنی؟:متفکر:)
در حالت متنی OS،Compiler و ... حواسشون هست که این جور چیزا رعایت بشه یعنی وقتی بهش گفتیم می خواهیم New Line داشته باشیم حواسش هست که به جای 0X0A تو فایل بنویسه 0X0D0A (البته تو Windows) ===> کار کردن با فایل های باینری سریع تر است چون این چیزا بررسی نمیشه هر چی ورودی هست همون میره تو خروجی(به نظرت کار کردن با فایل تو Unix سریعتر نیست به خاطر همین موضوع ؟:متفکر::متفکر::متفکر: من خودم هم نمی دونم:لبخند:)

sh4mid
شنبه 22 آبان 1389, 11:03 صبح
بریم سروقت مورد دوم

آیا این وسط تبدیلی صورت می گیرد
بله یه جورایی
بحث اینجاست که ++C برای باز کردن فایل اون رو به یک Stream وصل می کنه و براساس Method هایی که شما فراخونی میکنید تعیین میکنه از چه حالتی استفاده کنه
اگر از عملگرهای >> , << استفاده کنید به صورت فایل متنی با فایل شما رفتار می کند و اگر از read،write،put و get استفاده کنید به صورت باینری
برنامه زیر رو اجرا کن ، بعد فایل ها رو تو WinHex ببین

ofstream Fout3("list3.txt");
ofstream Fout4("list4.txt",ios::binary);

#define WRT(x) Fout3.write(reinterpret_cast<const char *>(&(x)), sizeof((x)))

cin >> name >> number >> ave;
WRT(name);
WRT(number);
WRT(ave);
Fout4 <<name << number << ave ;

Fout3.close();
Fout4.close();

البته استفاده از >>و<< تو فایل های باینری کارایی لازم رو نداره


In binary files, to input and output data with the extraction and insertion operators (<< and >>) and functions like getline is not efficient, since we do not need to format any data, and data may not use the separation codes used by text files to separate elements (like space, newline, etc...).

و اما درباره رکورد:

می تونی عملگرهای >>,<< رو برای رکورد مورد نظر Overload کنی
میتونی از writeو read استفاده کنی


#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>

using namespace std;

typedef struct tagPerson
{
char m_strName[10];
char m_strFamily[10];
int m_iAge;
} Person;

int main()
{

Person SomeBody;
char *szFileName="Person";

char *inp="LIST";
ifstream in(inp);
if(!in)
{
cerr << "Cannot open file.";
exit(EXIT_FAILURE);
}

ofstream Fout(szFileName,ios::binary);
if(!Fout)
{
cerr << "Cannot open file.";
exit(EXIT_FAILURE);
}
while(in>>SomeBody.m_strName>>SomeBody.m_strFamily>>SomeBody.m_iAge)
Fout.write(reinterpret_cast<char *>(&SomeBody), sizeof(SomeBody));

in.close();
Fout.close();

ifstream Fin;

Fin.open(szFileName,ios::binary);
if(Fin.fail())
{
cerr << "Cannot read file.";
exit(EXIT_FAILURE);
}

cout<<"Name\tFamily\tAge\t\n";

Person SomeBodyElse;

while(Fin.read (reinterpret_cast<char *>(&SomeBodyElse), sizeof(SomeBodyElse)))
cout<<SomeBodyElse.m_strName<<'\t'<<SomeBodyElse.m_strFamily<<'\t'<<SomeBodyElse.m_iAge<<endl ;

Fin.close();

system("pause");

return 0;
}