لماذا يعود ftell 0 في هذه الوظيفة؟
سؤال
عندما أقوم بتشغيل برنامجي واختيار رؤية قائمة المنتجات، فإنه لا يطبع أي شيء.وبعد مرور بعض الوقت، اكتشفت أن قيمة fl_size
هو دائما 0.لماذا هذا؟
void view_prdct_code_list() {
FILE *stock = fopen("stock.dat","r+");
assert(stock);
int fl_size=ftell(stock);
int prd_size= sizeof(product);
int quantity= fl_size/prd_size;
printf("fl_size=%d",fl_size);
fseek(stock,0,SEEK_SET);
prdct cprd= (product *)malloc (sizeof(product)*quantity);
assert(cprd);
int i;
fread(cprd,prd_size,quantity,stock);
for (i=0;i<quantity;i++){
printf("PRODUCT CODE: %d\n",cprd->code);
}
free(cprd);
fclose(stock);
}
المحلول
ftell
لا يُرجع الحجم الإجمالي للملف؛يقوم بإرجاع التيار موقف القراءة أو الكتابة داخل الملف.أنت أتصل ftell
مباشرة بعد فتح الملف، بحيث يكون هذا الموضع هو بداية الملف.يمكنك إما استخدام fseek(stock, 0, SEEK_END)
للسعي إلى النهاية قبل الدعوة ftell
, ، أو يمكنك إسقاط طبقة واستخدامها fstat(fileno(stock))
لاسترداد حجم الملف مباشرة من نظام التشغيل.
ملاحظات أخرى:
- لن يعمل أي من هذه الخيارات إذا كنت تقرأ من الأنبوب.(بشكل عام، تحتاج إلى التحقق من نجاح كل عملية من عمليات الوصول إلى الملفات الخاصة بك.)
fread
لا يمكن ضمان قراءة الملف بأكمله دفعة واحدة حتى لو طلبت ذلك.- كما يشير "ألك"،
ftell
يعود أlong
, ، ليسint
. - يجب أن تفتح هذا الملف الثنائي على ما يبدو باستخدام الوضع
"r+b"
. - الملفات الثنائية التي لا تحتوي على رأس ملف (وعلى وجه الخصوص التي لا تحتوي على أي رأس). الرقم السحري, ، من أربعة بايت على الأقل، عند الإزاحة صفر) يعد أمرًا سيئًا.
- لا يلقي القيمة المرتجعة ل
malloc
.(من الضروري القيام بذلك في لغة C++، ولكن في لغة C ليس فقط غير ضروري، يمكنه إخفاء الأخطاء.)
نصائح أخرى
تحقق من صفحة الرجل ل ftell
, ، على سبيل المثال هذا: http://linux.die.net/man/3/ftell
هنا هو الجزء ذو الصلة: "تحصل الدالة ftell() على القيمة الحالية لمؤشر موضع الملف للدفق المشار إليه بواسطة الدفق."
عند فتح الملف، سيكون موضع المؤشر في البداية.إذن المسافة من البداية ستكون صفرًا.لذلك ftell
يعود صفر.
لمعرفة حجم الملف راجع هذا الرابط: كيف يمكنني الحصول على حجم الملف في C؟.إليك مقتطف باختصار:
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
تأكد من الاتصال fseek(fp, 0L, SEEK_SET);
بعد أعلاه.
لأن ftell
إرجاع الحجم من البداية إلى الموضع الحالي للملف.
fseek(stock,0,SEEK_SET);
يعني أنك قمت بتعيين الموضع على الجزء الأول من الملف.
أيضا عليك أن تحدد fl_size=ftell(stock);
بعد ال fseek
.