קבצים בינאריים ב-C - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

קבצים בינאריים ב-C


slimshady21

Recommended Posts

שלום, התחלתי ללמוד על קבצים בינאריים ב-C, ויש כמה דברים שלא הבנתי:

- נכון שכשכתובים לקובץ מספר INT למשל, אז כפותחים את הקובץ לקריאה רואים את הערך אסקיי שלו. למשל רשמתי 65 אני אראה A. אז לא הבנתי מה קורה כשרושמים מספר שהוא גדול מ-255, רשמתי למשל 300 לקובץ, וכשפתחתי אותו ראיתי את הסימן "," (פסיק), לא הבנתי איך הגיעו לזה....

-לקחתי קובץ שרשום בו slimshady. אז כאשר אני קורא ממנו (בתור קובץ בינארי) נגיד למערך של 100 תווים, אז עורך המחרוזת אמורה להיות 9, כי זה האורך של המילה נכון? (או 10 כולל התו n\ , לא יודע בדיוק איך זה הולך) אבל כשהדפסתי את המחרוזת אז התוצאה הייתה משהו כזה- slimshady$%-* f

מה זה כל הסימנים האלה?

או שלפעמים אני קולט כמה תווים למחרוזת, ובתוצאה אני רואה שאורך המחרוזת , קטן יותר ממספר התווים שנקלטו (אני בודק על ידי הערך המוחזר מהפונקציה FREAD) איך זה הגיוני?

- עוד משהו, נגיד אני פותח סתם קובץ ורשום בו 5F772D. ואני רוצה לקלוט ממנו נתונים. אז איך אני יכול לדעת עם מה שכתוב בו נכתב כתווים- שכל תו תופס בית אחד, ולכן עליי לקרוא ממנו 6 תווים. או שהקובץ נכתב כ-INTים, ואז כל הקובץ תופס בעצם פי שניים בתים.

תודה לעוזרים.

קישור לתוכן
שתף באתרים אחרים

לשאלה האחרונה והכי פשוטה - אתה יכול לצור תו "דמה" בכל קובץ שאתה יוצר כדי לסמן האם הוא טקסטואלי או בינארי.

הסבר קצר -

כשאתה שומר משהו כקובץ טקסט, אתה שומר בכל מקום בקובץ את ערך האסקי של התו אותו הכנסת. אם אתה שומר בבינארי, אז אתה שומר את הערך עצמו, כפי שהוא מופיע בזיכרון של המחשב.

לדוגמא, אם אתה שומר את המספר 9 לתוך קובץ טקסט, רק בייט אחד ישמר. אם אתה שומר את המספר 9 לתוך קובץ בינארי, הוא ישמר לך ב- 4 בייטים(כגודלו של INT, תלוי במערכת ההפעלה).

כשאתה פועל עם קבצי טקסט, אתה אמור להשתמש בfprintf, ולהשתמש בפםונ בידיו כפי שאתה משתמש בprintf רגיל. אם אתה רוצה לשמור int, תשתמש ב- %d. אם אתה רוצה לשמור תו, תשתמש ב- %c. הפונ כבר תדאג "להמיר" אותם לטקסט ולשמור בקובץ.

כדאי שתרשום את הקוד שהקלדת כדי לקבל הסברים, קשה להסביר ככה באוויר.

קישור לתוכן
שתף באתרים אחרים

כשכתבת מחרוזת לקובץ, לא כתבת את ה- NULL שבסופה, ולכן קיבלת תוצאה לא ממש צפויה כשקראת ממנו.

זו בדיוק הסיבה שלקבצי מידע משתמשים בפורמט כלשהו.

בדר"כ, כדי להקל על העניינים, את המידע שאומר לך מה אורך המידע ומה הסוג שלו שומרים לפני המידע הזה.

ספציפית, אם אורך המחרוזת לא קבוע, אתה יכול לשמור את אורך המחרוזת ואחריו את המחרוזת עצמה, ואז כשאתה קורא אותה, אתה יודע בדיוק כמה בתים לקרוא לתוך המחרוזת.

קישור לתוכן
שתף באתרים אחרים

כשכתבת מחרוזת לקובץ, לא כתבת את ה- NULL שבסופה, ולכן קיבלת תוצאה לא ממש צפויה כשקראת ממנו.

זו בדיוק הסיבה שלקבצי מידע משתמשים בפורמט כלשהו.

בדר"כ, כדי להקל על העניינים, את המידע שאומר לך מה אורך המידע ומה הסוג שלו שומרים לפני המידע הזה.

ספציפית, אם אורך המחרוזת לא קבוע, אתה יכול לשמור את אורך המחרוזת ואחריו את המחרוזת עצמה, ואז כשאתה קורא אותה, אתה יודע בדיוק כמה בתים לקרוא לתוך המחרוזת.

איך אני כותב את הNULL שבסוף?

ולא הבנתי, אז נגיד אני רוצה לקחת סתם קובץ רנדומלי, שאני לא יודע מה אורכו, ולהעתיק אותו לקובץ אחר. אז אי אפשר לעשות זאת?

ואיך אני שומר קודם את אורך המחרוזת אם אני לא יודע מה הוא בכלל? וגם איך זה הגיוני שאורך המחרוזת קטן ממספר התווים שנקלטו לתוכה??

ממש מעצבן כל הקטע הזה, אני כותב כל מיני קודים דומים וכל פעם יוצאת לי תוצאה ממש אחרת, לפעמים המחרוזת יוצאת יותר קצרה ממה שרשום בקובץ, ולפעמים יותר ארוכה, לא מבין פה כלום

אם אני זוכר משהו, ברגע שיש לך מידע על סוג הקובץ מספיק לשלוח פלאגים לפונקציות מיוחדות לעבודה עם קבצים - נו,משהו כזה... :smile1::screwy:

אני אברר :cool2:

איזה פלאגים ומה זה פונקציות מיוחדות לעבודה עם קבצים? ואיזה מידע בדיוק צריך שיהיה על הקובץ?

קישור לתוכן
שתף באתרים אחרים

אם אתה רוצה להעתיק קובץ - תשתמש בקובץ בינארי(אתה יכול גם בטקסטואלי, אבל לפי ההיגיון כדאי בינארי).

אתה צריך לשים '\0' בסף המחרוזת כדי לציין את סופה. scanf עושה את זה.

scanf גם לא מכירה את אורך המחרוזת, ולכן אתה יכול להכניס כמה תווים שאתה רוצה. הבעיה היא שאתה יכול לדרוס של תוכנית אחרת, ואז התוכנית שלך תיסגר.

שוב, תרשום את הקוד שלך.

קישור לתוכן
שתף באתרים אחרים

ולא הבנתי, אז נגיד אני רוצה לקחת סתם קובץ רנדומלי, שאני לא יודע מה אורכו, ולהעתיק אותו לקובץ אחר. אז אי אפשר לעשות זאת?

במקרה זה אתה לא משתמש ב-scanf ו-printf, אלא ב-getc ו-putc.

הנה דוגמה:

http://www.cppreference.com/stdio/putc.html

קישור לתוכן
שתף באתרים אחרים

הבעיה היא שאתה יכול לדרוס של תוכנית אחרת, ואז התוכנית שלך תיסגר

זה מאוד נאיבי לחשוב ככה.

מקרה כזה (buffer overflow) הוא בדיוק המקרה שהאקרים (קראקרים, אם רוצים להיות מדוייקים) מחפשים כדי לפרוץ תוכניות ורשתות.

במקרה הזה, קל לייצר קובץ שאם תנסה לקרוא ממנו בצורה הזו, הוא ישתלט לך על המחשב.

במקרה של תוכנית שרצה על שרת - יש סיכוי (בהתאם להרשאות התוכנית על השרת) להשתלט גם על השרת.

מה היתרון של זה על פתיחה כבינארי?

כשפותחים קובץ כקובץ טקסט, מערכת ההפעלה עושה המרות newline. כשפותחים אותו כ- binary, היא לא.

בנוסף - עד כמה שזכור לי, כשמערכת ההפעלה קוראת קובץ טקסט, היא מפסיקה לקרוא כשהיא מגיעה ל- NULL.

קישור לתוכן
שתף באתרים אחרים

באילו מקרים צריך לבצע המרות NEWLINE? קובץ המקור גם ככה ממערכת ההפעלה, והיא יוצרת אותו עם תווים של NEWLINE טובים, לא?

כש"מעתיקים" קובץ בצורה בינארית, הוא לא מועתק ביט ביט ויוצר עותק "מושלם" של המקור ללא שינויים?

לא הבנתי למה צריך לשנות את קובץ הטקסט.

קישור לתוכן
שתף באתרים אחרים

בקבצי טקסט של דוס/windows, שורות מסתיימות ב- newline,carriage return.

כשאתה משתמש בפונקציות שמטפלות בקבצי טקסט, אתה עובד רק עם newlines. מערכת ההפעלה עושה את התרגום.

(יש גם תרגום שנעשה עבור UNICODE, אבל לא נראה לי שזה רלוונטי כרגע)

כשאתה עובד על קובץ בינארי, אתה קורא בתים בלי תרגום, ולכן יכול לשמור אותם כמו שהם, ולקבל עותק זהה.

קישור לתוכן
שתף באתרים אחרים

זה עוד לא הוזכר, אבל כדי לעבוד עם קבצים בינאריים ב-ANSI-C נא להשתמש ב-fread, fwrite וחבריהם.

לקבצי טקסט מומלץ fprintf, fgets וכולי.

ואם אתם עובדים ב-C++ הדרך הקלה ביותר לעבוד עם קבצי טקסט היא fstream וכל היררכית ה-streams.

קישור לתוכן
שתף באתרים אחרים

רגע רגע, התקדמתם יותר מדי, ובקושי הבנתי משהו

אם אתה רוצה להעתיק קובץ - תשתמש בקובץ בינארי(אתה יכול גם בטקסטואלי, אבל לפי ההיגיון כדאי בינארי).

אתה צריך לשים '\0' בסף המחרוזת כדי לציין את סופה. scanf עושה את זה.

scanf גם לא מכירה את אורך המחרוזת, ולכן אתה יכול להכניס כמה תווים שאתה רוצה. הבעיה היא שאתה יכול לדרוס של תוכנית אחרת, ואז התוכנית שלך תיסגר.

שוב, תרשום את הקוד שלך.

לא ראיתי קודם את ההודעה הראשונה שלך, בגלל זה לא הגבתי עליה. מה הכוונה התו "דמה"?

אמרתם שכדאי להשתמש בfscanf אבל מצד שני אמרתם שזה יכול לגרום לקריסה אז איך לעשות לא הבנתי. והנה עשיתי למשל תוכנית שקוראת בעזרת fscanf מחרוזת ומדפיסה אותה:

void main(){

FILE *file;

char c,string[30];

int counter=-1;

file=fopen("log.log","rb");

do

{

counter++;

fscanf(file,"%c", &string[counter]);

}while(string[counter]!=0);

puts(string);

fclose(file);

}

בקובץ log.log רשום Eminem . והתוצאה הייתה מלא חרבושים.

ניסיתי לבנות עוד תוכנית, שתיקח קובץ אחד ותכווץ אותו בשיטת RLE. ותשמור את זה בקובץ אחר. הנה:

void main(){

FILE *file, *file2;

char ch[80],c;

int num=1,counter,check;

file=fopen("log.log","rb");

if(file==NULL)

{

printf("cant open file");

exit(1);

}

file2=fopen("Slimshady.dat","wb");

if(file2==NULL)

{

printf("cant open file");

exit(1);

}

fread(&ch[0],sizeof(char),1,file);

counter=1;

do

{

check=fread(&ch[counter],sizeof(char),1,file);

if(ch[counter]==ch[counter-1])

{

num++;

}

else

{

fwrite(&num,sizeof(int),1,file2);

fwrite(&ch[counter-1],sizeof(char),1,file2);

num=1;

}

counter++;

}while(check>0);

fclose(file2);

file2=fopen("Slimshady.dat","rb");

do

{

check=fread(&c,sizeof(char),1,file2);

printf(" %02X" , c);

}while(check>0);

fclose(file2);

fclose(file);

}

בקובץ log.log היה רשום abbcccd. והתוצאה הייתה :

64 64 00 01 63 00 03 62 00 02 61 00 01

כאילו אחרי כל תו יש את התו NULL TERMINATOR. ושמתי לב שזה קורא לפעמים גם כשאני מנסה לקרוא תו תו מקובץ בינארי בעזרת FREAD. אז מה זה אמור להיות בדיוק לא הבנתי.

גם חוץ מזה ממה שקראתי בספר אפשר להשתמש רק בפונקציות fread & fwrite בשביל קובץ בינארי. רק עכשיו הבנתי מכם שאפשר גם fscanf . אז מהן בדיוק כל הפונקציות קריאה/כתיבה שאפשר להשתמש על קובץ בינארי?

קישור לתוכן
שתף באתרים אחרים

התכוונתי לתו שאתה שומר בתחילת הקובץ שלך ורק מסמן לך אם זה קובץ בינארי או טקסטואלי. דגל כזה.

תחזור על לולאות ומחרוזות, שם הבעיה שלך בהעתקת הקובץ.

BOOMERANG: אם אני מעתיק קובץ, למה שאני ארצה לפתוח קבצי טקסט בתור טקסט ולא בינארי? לפי מה שהבנתי, פונ הקריאה וכתיבה של קבצי טקסט יעשו פעולות מיותרות(ההמרות למיניהן). הרי קובץ המקור נוצר ע"H אותה , ולא צריך להמיר כלום.

קישור לתוכן
שתף באתרים אחרים

כשיש לך קובץ טקסט (נגיד שאתה שומר את הקונפיגורציה שלך בקובץ טקסט) אז יותר נוח לקרוא אותו שורה אחרי שורה, במקום לרוץ בית אחרי בית ולחפש סימנים של newline ו- carriage return.

רק שהיום אתה לא יכול סתם ככה לקרוא שורה לתוך buffer (לא ב- C על כל פנים) אלא חייב להגביל אותו בגודל ה- buffer.

קישור לתוכן
שתף באתרים אחרים

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

×
  • צור חדש...