נושאים פעיליםנושאים פעילים  הצגת רשימה של חברי הפורוםרשימת משתמשים  חיפוש בפורוםחיפוש  עזרהעזרה
  הרשמההרשמה  התחברותהתחברות RSS עדכונים
תיכנות
RSS UnderWarrior Forums : RSS תיכנות
נושא

נושא: נעילת קובץ

שליחת תגובהשליחת נושא חדש
כותב
הודעה << נושא קודם | נושא הבא >>
יוסי
אורח
אורח


הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין
הודעות: 12647
נשלח בתאריך: 16 October 2007 בשעה 15:08 | IP רשוּם
ציטוט יוסי

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


הצטרף / הצטרפה: 02 January 2007
מדינה: Israel
משתמש: מנותק/ת
הודעות: 209
נשלח בתאריך: 16 October 2007 בשעה 15:55 | IP רשוּם
ציטוט צחי@

בשביל ש-2 פונקציות שמופעלות מאותה התוכנית ידרסו זאת על המידע של השניה צריך להתקיים אחד מהתנאים הבאים (או שניהם יחדיו)

1. הפונקציות רצות כל אחת ב-thread נפרד ללא סינכרוניזציה - הפתרון - הוספת סינכרוניזציה (mutex) על פעולת הכתיבה לקובץ.

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

חזרה לתחילת העמוד הצג את כרטיס החבר של צחי@ חפש הודעות אחרות של צחי@ בקר בדף הבית של צחי@
 
יוסי
אורח
אורח


הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין
הודעות: 12647
נשלח בתאריך: 16 October 2007 בשעה 16:29 | IP רשוּם
ציטוט יוסי

תודה צחי!

1)כדי ליצור סינכרוניזציה השתמשתי בפונקציה:

 lock_r = lockf(fp, F_TLOCK, sizeof(fp));

2)בפונקצית הקריאה השתצשתי ב- fseek(fp, 0, SEEK_SET);

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

חזרה לתחילת העמוד הצג את כרטיס החבר של יוסי חפש הודעות אחרות של יוסי בקר בדף הבית של יוסי
 
צחי@
משתמש חבר
משתמש חבר


הצטרף / הצטרפה: 02 January 2007
מדינה: Israel
משתמש: מנותק/ת
הודעות: 209
נשלח בתאריך: 16 October 2007 בשעה 17:37 | IP רשוּם
ציטוט צחי@

1) אם אתה לא משתמש ב-threads נפרדים, כנראה אין לך סיבה לנעול את הקובץ, מה גם שאני לא מכיר את lockf (זה חלק מ-ANSI C ?).

2) אם כל פעם שאתה כותב לקובץ אתה עושה

קוד:

fseek(fp, 0, SEEK_SET);

אז אין פלא שכאשר אתה כותב - הכתיבה דורסת את מה שיש בתחילת הקובץ !

אם תסביר יותר מה המטרה שלך ומה אתה מנסה לעשות אולי אפשר יהיה לעזור יותר.

לצרף קוד זה גם עוזר.

חזרה לתחילת העמוד הצג את כרטיס החבר של צחי@ חפש הודעות אחרות של צחי@ בקר בדף הבית של צחי@
 
יוסי
אורח
אורח


הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין
הודעות: 12647
נשלח בתאריך: 16 October 2007 בשעה 17:54 | IP רשוּם
ציטוט יוסי

1)יש לי שני תהליכים שרצים במקביל ושניהם צריכים את אותו קובץ.

1א)lockf נמצא בספריה #include <unistd.h>

2)ה- fseek נועד לאתחל את הקובץ כדי שאני אחפש את המשתנה שאני צריך מההתחלה(אני כותב ini file)

3)

int WriteCfg(FILE *fp, FILE *tmp_fp, char *section, char *varname, char *var)
{
    char line[CONFIG_LINE_LENGTH], *p;
    int linenum = 0;
    int done = 0;
   
    fseek(fp, 0, SEEK_SET);
 
    for(;;)
 {
     fgets(line, sizeof(line), fp);
     line[strlen(line)-1] = 0; /* remove ending \n */
     linenum++;
    
     if (feof(fp))
   return 1;
    
     if (!line[0])    /* empty line */
  {
      fprintf(tmp_fp,"%s\n", line);
      continue;
  }
    
     if (line[0] == ';')   /* comment line */
  {
      fprintf(tmp_fp,"%s\n", line);
      continue;
  }
     if(!section)
  {
   if ((line[0] == '[') && (line[strlen(line)-1] == ']'))
   {
    fprintf(tmp_fp,"%s\n", line);
    line[strlen(line)-1] = 0;
    if (strcasecmp(&line[1], section))
     continue;  /* not right section */  
   }
      /* found section, now look for variable */
      for (;;)
   {
       fgets(line, sizeof(line), fp);
       line[strlen(line)-1] = 0; /* remove ending \n */
       linenum++;
   
       if (feof(fp))
    {
        if (!done)
      fprintf(tmp_fp,"%s=%s\n", varname,var);
        return 2;
    }
      
       if (!line[0])  /* empty line */
    {
        fprintf(tmp_fp,"%s\n", line);
        continue;
    }
      
       if (line[0] == ';') /* comment line */
    {
        fprintf(tmp_fp,"%s\n", line);
        continue;  
    }
      
       if (line[0] == '[')
    {
        if (!done)
     {
         fprintf(tmp_fp,"%s=%s\n", varname,var);
         done = 1;
     }
        fprintf(tmp_fp,"%s\n", line);
        continue;
    }
      
       p = (char *)strchr(line, '=');
       if (!p)
     return -linenum;/* bad line format */
      
       *p = 0;   /* make variable name a string */
      
       if (strcasecmp(line, varname)) 
    {
        *p = '=';
        fprintf(tmp_fp,"%s\n", line);
        continue; /* no varname match */
    }
      
       p++;
       fprintf(tmp_fp,"%s=%s\n", varname,var);
   if(DEBUG) printf("cfg.c:199:varname= %s, var= %s\n", varname, var);
       done = 1;
   }
  }
     fprintf(tmp_fp,"%s\n", line);
 }
}

חזרה לתחילת העמוד הצג את כרטיס החבר של יוסי חפש הודעות אחרות של יוסי בקר בדף הבית של יוסי
 
צחי@
משתמש חבר
משתמש חבר


הצטרף / הצטרפה: 02 January 2007
מדינה: Israel
משתמש: מנותק/ת
הודעות: 209
נשלח בתאריך: 16 October 2007 בשעה 17:55 | IP רשוּם
ציטוט צחי@

בנוסף, ה-msdn כותב על מס' מגבלות של fseek עבור text mode:

קוד:

For streams opened in text mode, fseek has limited use, because carriage return—linefeed translations can cause fseek to produce unexpected results. The only fseek operations guaranteed to work on streams opened in text mode are:

  • Seeking with an offset of 0 relative to any of the origin values.
  • Seeking from the beginning of the file with an offset value returned from a call to ftell.

Also in text mode, CTRL+Z is interpreted as an end-of-file character on input. In files opened for reading/writing, fopen and all related routines check for a CTRL+Z at the end of the file and remove it if possible. This is done because using fseek and ftell to move within a file that ends with a CTRL+Z may cause fseek to behave improperly near the end of the file.

חזרה לתחילת העמוד הצג את כרטיס החבר של צחי@ חפש הודעות אחרות של צחי@ בקר בדף הבית של צחי@
 
צחי@
משתמש חבר
משתמש חבר


הצטרף / הצטרפה: 02 January 2007
מדינה: Israel
משתמש: מנותק/ת
הודעות: 209
נשלח בתאריך: 16 October 2007 בשעה 18:12 | IP רשוּם
ציטוט צחי@

סתם רעיון - כאשר אתה כותב נתונים לתוך הקובץ, אך לא בסופו, אם אתה כותב נתון שמסתיים לאחר סוף השורה לפני השינוי, אתה דורס את ה-n\ שבסוף השורה, ואולי גם חלק מתחילת השורה הבאה.

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

מבנה כזה צריך להכיל למשל struct שמייצג קבוצה שיכיל את שמה וכן רשימה של מפתחות השייכים לקבוצה.

struct שמייצג מפתח יכיל את שם המפתח ואת הערך של המפתח.

זאת סתם דוגמא, אלה יכולים להיות גם מחלקות ולא struct.

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

חזרה לתחילת העמוד הצג את כרטיס החבר של צחי@ חפש הודעות אחרות של צחי@ בקר בדף הבית של צחי@
 
יוסי
אורח
אורח


הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין
הודעות: 12647
נשלח בתאריך: 16 October 2007 בשעה 18:31 | IP רשוּם
ציטוט יוסי

כדי להמנע מהבעיה של דריסת ה-n\ אני פותח בפונקציה שקראה לפונקצית הכתיבה קובץ זמני ע"י הפונקציה:

sprintf(tmp_fname, "%s/tmp_fname.XXXXXX", chConfigPath);
 tmp_file = mktemp(tmp_fname);

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

mv = rename(tmp_file, fname );

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

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

חזרה לתחילת העמוד הצג את כרטיס החבר של יוסי חפש הודעות אחרות של יוסי בקר בדף הבית של יוסי
 
צחי@
משתמש חבר
משתמש חבר


הצטרף / הצטרפה: 02 January 2007
מדינה: Israel
משתמש: מנותק/ת
הודעות: 209
נשלח בתאריך: 16 October 2007 בשעה 19:00 | IP רשוּם
ציטוט צחי@

לפתוח קובץ זמני זה מקובל, אבל לפי התהליך שאתה תיארת, עבור כל שורה, עליך לכתוב ל-buffer את התוכן החדש של השורה שעליך לשנות, להעתיק את כל השורות מהקובץ המקורי לקובץ הזמני, עד לשורה הנ"ל , לכתוב את התוכן המעודכן של השורה, ולהעתיק את יתרת השורות בקובץ.

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

חזרה לתחילת העמוד הצג את כרטיס החבר של צחי@ חפש הודעות אחרות של צחי@ בקר בדף הבית של צחי@
 

אם ברצונך להגיב לנושא זה עליך קודם להתחבר
אם אינך רשום/ה כבר עליך להרשם

  שליחת תגובהשליחת נושא חדש
גרסת הדפסה גרסת הדפסה

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