【问题标题】:Open file and read from file Objective-c打开文件并从文件中读取 Objective-c
【发布时间】:2011-05-11 15:33:43
【问题描述】:

我正在尝试打开一个文件并从中读取.. 但我遇到了一些问题。

FILE *libFile = fopen("/Users/pineapple/Desktop/finalproj/test242.txt","r");
char wah[200];
fgets(wah, 200, libFile);
printf("%s test\n", wah);

这将打印:\377\376N test 而不是我文件的任何内容。

知道为什么吗?

完整代码:

#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 个字符。

【问题讨论】:

    标签: objective-c fgets


    【解决方案1】:
     printf("%s test\n");
    

    您没有将字符串传递给 printf。试试

     printf("%s test\n", wah);
    

    另外,如果您的文件包含超过 200 个字符的行,fgets 会将 200 个字符读入 wah - 然后在末尾添加 NUL,这将超出 wah 的末尾(因为您声明它是 200 个字符) 并且会随意践踏某些东西,并且您的程序的行为将是未定义的,并且可能会着火您的猫。

    【讨论】:

    • 我一定是在尝试修复它时犯了这个错误。我编辑为 printf("%s yeh\n", wah);它有同样的问题
    • 您的文件存在吗?你没有检查 fopen 的成功
    【解决方案2】:

    如果您不介意阅读所有文件,您可以执行以下操作:

    NSData* myData = [NSData dataWithContentsOfFile:myFileWithPath];
    

    然后对那里的数据做任何你想做的事情。如果文件不存在,你将得到 nil。

    如果您在此文件中假设文本(字符串)数据,您还可以执行类似的操作,然后将其解析为 NSString:

    NSString* myString = [[NSString alloc] initWithBytes:[myData bytes] length:[myData length] encoding:NSUTF8StringEncoding];
    

    由于您提到您对objective-c 比较陌生,因此您可以很好地搜索NSStrings。查看here 了解更多信息。

    【讨论】:

    • 我一定是在尝试修复它时犯了这个错误。我编辑为 printf("%s yeh\n", wah);它有同样的问题
    • paul 是正确的,如果没有更多信息,我们无能为力。您确定您的文件存在并且 fgets 正在读取数据吗?尝试先将 wah 设置为某个值,以确保垃圾不仅仅是未初始化的数据,例如:char wah[200] = "hello";
    • 我尝试将 wah 初始化为某些东西,它在程序运行时打印 \377\376H test。另外,我现在正在检查,该文件确实存在。
    • 听起来这是一个编码问题。您可能正在读取数据,但 sprintf 正在尝试将其打印为 ascii c 字符串,而不是 unicode 字符串。我将更新我的帖子以包含来自 NSData 的 NSString 转换。
    【解决方案3】:

    如果这是针对 Objective-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];
    

    或者如果您需要逐行阅读:

    How to read data from NSFileHandle line by line?

    IMO,除非您有非常非常非常好的理由(例如,使用 O_SHLOCK 或其他方式打开文件),否则无需下拉到 C 级 fileIO 函数

    【讨论】:

    • 目标是逐字读取文件中的文本。我是 Objective-C 的新手,而且(至少)我知道如何使用 c 函数管理文本文件。
    • 这是正确的。如果文件不一定包含字符串数据(即原始字节),请使用 NSData 对象及其 dataWithContentsOfFile 构造函数,您不必担心 NSString 对字符串编码的自动解释。
    【解决方案4】:

    您的文件存储在UTF-16 (Unicode) 中。文件中的第一个字符是“L”,即代码点 0x4C。文件的前 4 个字节是 FF FE 4C 00,这是一个字节顺序标记 (BOM) 和以 UTF-16 编码为两个字节的字母 L。

    fgets 不支持 Unicode,因此它正在寻找换行符 '\n',即字节 0x0A。这很可能会发生在 Unicode 换行符的第一个字节(两个字节 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) 是 C 字符串终止符,因此当您尝试使用 printf 将其打印出来时,它会在第一个 null 处停止,您看到的只是 \377\376L\377\376 是字节 FF FE 的八进制表示。

    解决此问题的方法是将文本文件转换为单字节编码,例如 ISO 8859-1 或 UTF-8。请注意,必须单字节编码(UTF-8 除外)不能编码全范围的 Unicode 字符,所以如果您需要 Unicode,我强烈建议使用 UTF-8。或者,您可以将您的程序转换为支持 Unicode,但是您不能再使用很多标准库函数(例如 fgetsprintf),您需要在任何地方使用 wchar_t 来代替char.

    【讨论】:

    • ... 或者只是使用原生理解 UTF16 的东西,例如 NSString
    • 啊,戴夫,你们这些孩子,今天有了花哨的编码、高级框架,甚至还有音乐,你们会毁了我们美好的世界……
    【解决方案5】:

    Slycrel 明白了。扩展该答案,这是将数据转换为字符串的另一种(在我看来,更简单)的方法:

    NSString *myFileString = [[NSString alloc] initWithData:someData encoding:NSUTF8StringEncoding];
    

    这直接使用指定的 NSData 声明一个新的 NSString。

    【讨论】:

      【解决方案6】:

      我也想要这个,并认为“改为这样做”没有回答问题,下面是一个工作示例。请注意 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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-09
        • 1970-01-01
        • 1970-01-01
        • 2016-09-21
        • 2019-07-11
        • 2019-02-17
        • 1970-01-01
        • 2012-08-31
        相关资源
        最近更新 更多