文件内容后的胡言乱语

时间:2013-11-18 03:04:23

标签: c fopen

我正在使用以下函数将脚本拉入我的C应用程序:

char *anne_script_load(char fileName[]){
    char path[6400] = "data/scripts/";
    strncat(path, fileName, 6000);
    strncat(path, ".lua", 5);
    struct stat fileInfo;
    char *contents = NULL;
    FILE * pFile;

    stat(path, &fileInfo);
    contents = (char*)malloc(fileInfo.st_size);
    pFile = fopen (path,"r");
    fread (contents,1,fileInfo.st_size,pFile);
    fclose(pFile);

    printf("Script path: %s\n", path);
    printf("Script loaded: %s\n", contents);
    return contents;
}

在运行时,第二个printf生成以下输出:

test script - if you see this load is working :) helicopters����

我的控制台上的乱码文本看起来不一样,但我不确定它是否重要:我的理论是文件流不以空字节结尾(它不作为ac string存储在磁盘上,毕竟 - 所以我自己终止了如下:

contents[fileInfo.st_size] = 0;

这似乎有效,但我担心这个解决方案的稳健性。有没有更好的,普遍接受的做法?

3 个答案:

答案 0 :(得分:3)

您需要在malloc中添加+1才能终止:

if(stat(path, &fileInfo) != 0) {
   perror("stat");
   ...
}
contents = (char*)malloc(fileInfo.st_size + 1); // don't forget this
pFile = fopen (path,"r"); 
if(pFile == 0) {
    perror("fopen");
    ...
}
int n = fread (contents,1,fileInfo.st_size,pFile);
if(n != fileInfo.st_size) {
   perror("read");
   ...
}
contents[n] = 0; // terminate after what you read. Not what you think you read.

**检查fopen,stat和read的返回值。**

答案 1 :(得分:1)

这里有很多东西可以改进......但是为了回答你的问题,fread()将字节读入你没有初始化的数组中。在C中,你不能指望在通过fread读取的最后一个字节之后有一个\ 0字符 - 你必须先将它放在那里,或者使用memset()或calloc()。

此外,如果文件内容被视为文本字符串,请务必在大小上分配一个额外的字节来保存终止\ 0字符!

答案 2 :(得分:1)

你必须以字符串结尾,否则printf()将无法确定何时停止从你刚刚传递的指针中读取。这同样适用于其他函数,例如strcmp(),您可以使用两个具有相同内容的字符串,同时由于非空终止字符串而使strcmp()大喊非零。

所以contents[fileInfo.st_size] = 0;就好了。

您可以在Wikipedia

上阅读更多关于以空字符结尾的字符串的内容