افتح الملف وقراءة من File Objective-C
-
25-09-2019 - |
سؤال
أحاول فتح ملف ، وأقرأ منه .. لكنني أواجه بعض المشكلات.
FILE *libFile = fopen("/Users/pineapple/Desktop/finalproj/test242.txt","r");
char wah[200];
fgets(wah, 200, libFile);
printf("%s test\n", wah);
هذا يطبع: 377 376N بدلاً من أي من محتويات ملفي.
أي فكرة لماذا؟
رمز كامل:
#import <Cocoa/Cocoa.h>
#import <stdio.h>
int main(int argc, char *argv[])
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
FILE *libFile = fopen("/Users/pineapple/Desktop/finalproj/test242.txt","r");
if(libFile){
char wah[200];
fgets(wah, 200, libFile);
printf("%s test\n", wah);
}
[pool drain];
return 0;
}
و test242.txt لا يحتوي على أكثر من 200 chars.
المحلول
إذا كان هذا للهدف C ، فلماذا لا تفعل شيئًا مثل:
استخدم nsfilehandle:
NSString * path = @"/Users/pineapple/Desktop/finalproj/test242.txt";
NSFileHandle * fileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
NSData * buffer = nil;
while ((buffer = [fileHandle readDataOfLength:1024])) {
//do something with the buffer
}
أو استخدام NSString:
NSString * fileContents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
أو إذا كنت بحاجة إلى قراءته خطًا على حدة:
كيفية قراءة البيانات من NSFileHandle Line سطر؟
IMO ، ليست هناك حاجة إلى النزول إلى وظائف Fileio على مستوى C إلا إذا كان لديك سبب وجيه للغاية للقيام بذلك (أي افتح ملفًا باستخدام ملف باستخدام O_SHLOCK
أو شيء ما)
نصائح أخرى
يتم تخزين ملفك في UTF-16 (يونيكود). الحرف الأول في ملفك هو "L" ، وهو Code Point 0x4C. أول 4 بايت من ملفك FF FE 4C 00
, ، وهي علامة بايت بايت (BOM) والحرف L المشفر في UTF-16 كبايت.
fgets
ليس يونيكود ، لذلك يبحث عن شخصية الخط الجديد '\n'
, ، وهو بايت 0x0A. على الأرجح سيحدث هذا في أول بايت من خط يونيكود الجديد (البايتان 0A 00
) ، ولكن يمكن أن يحدث أيضًا على الكثير من الأحرف الأخرى غير الجديدة مثل U+010A (رسالة رأس المال اللاتينية A مع نقطة أعلاه) أو أي شيء في البرامج النصية Gurmukhi أو Gujarati (U+0A00 إلى U+0AFF).
على أي حال ، على الرغم من ذلك ، فإن البيانات التي تنتهي في المخزن المؤقت wah
يحتوي على الكثير من الفريدة المدمجة ويبدو شيئًا مثل FF FE 4C 00 47 00 4F 00 4F 00 0A 00
. NUL (0x00) هو TREFINATOR C ، لذلك عندما تحاول طباعة هذا باستخدامه باستخدام printf
, ، يتوقف عند الفرق الأولى ، وكل ما تراه هو \377\376L
. \377\376
هو تمثيل ثماني البايتات FF FE
.
الإصلاح لهذا هو تحويل الملف النصي الخاص بك إلى ترميز بايت واحد مثل ISO 8859-1 أو UTF-8. لاحظ أنه يجب أن لا يمكن ترميز الترميزات أحادية البايت (UTF-8) تشفير النطاق الكامل من أحرف Unicode ، لذلك إذا كنت بحاجة إلى Unicode ، فإنني أوصي بشدة باستخدام UTF-8. بدلاً من ذلك ، يمكنك تحويل البرنامج الخاص بك إلى أن يكون unicode ، ولكن بعد ذلك لم يعد بإمكانك استخدام الكثير من وظائف المكتبة القياسية (مثل fgets
و printf
) ، وتحتاج إلى استخدام wchar_t
في كل مكان بدلاً من char
.
إذا كنت لا تمانع في قراءة كل ملف ، فيمكنك فعل شيء مثل هذا:
NSData* myData = [NSData dataWithContentsOfFile:myFileWithPath];
ثم افعل ما تريد مع البيانات من هناك. سوف تحصل على شيء إذا لم يكن الملف موجودًا.
إذا كنت تفترض بيانات النص (سلسلة) في هذا الملف ، يمكنك بالإضافة إلى ذلك القيام بشيء من هذا القبيل ثم تحليله كـ NSString:
NSString* myString = [[NSString alloc] initWithBytes:[myData bytes] length:[myData length] encoding:NSUTF8StringEncoding];
نظرًا لأنك ذكرت أنك جديد نسبيًا على الهدف-C ، يمكنك البحث عن nsstrings بشكل جيد إلى حد ما. الق نظرة هنا لمزيد من المعلومات حول هذا.
أردت هذا أيضًا وفكرت "افعل هذا بدلاً من ذلك" لم يجيب على السؤال ، إليك مثال عمل أدناه. احذر من أن FGETS يقرأ المحدد n ويؤدي إلى نصك.
NSString * fName = [[NSBundle mainBundle] pathForResource:@"Sample" ofType:@"txt"];
FILE *fileHandle = fopen([fName UTF8String],"r");
char space[1024];
while (fgets(space, 1024, fileHandle) != NULL)
{
NSLog(@"space = %s", space);
}
fclose(fileHandle);
printf("%s test\n");
أنت لا تمرر السلسلة إلى printf. محاولة
printf("%s test\n", wah);
أيضًا ، إذا كان ملفك يحتوي على سطر يزيد طوله عن 200 حرف ، فستقرأ Fgets 200 حرف في WAH - ثم أضف NUL إلى النهاية ، والتي ستكون خارج نهاية WAH (نظرًا لأنك أعلنت أنها 200 حرف) وستقوم تدوس على شيء عشوائي ، وسيكون سلوك برنامجك غير محدد وقد يشعل النار على قطتك.
حصلت سايكلريل. التوسع في هذه الإجابة ، إليك طريقة أخرى (في رأيي ، أبسط) لتحويل تلك البيانات إلى سلسلة:
NSString *myFileString = [[NSString alloc] initWithData:someData encoding:NSUTF8StringEncoding];
هذا يعلن عن NSString جديد مباشرة باستخدام NSDATA المحدد.