C - 读完整个文件最后都是垃圾

时间:2017-09-15 12:59:19

标签: c file

所以我试图使用这个函数读取整个文本文件:

FILE *fp = fopen(path, "r");
fseek(fp, 0, SEEK_END);
int tamanioArchivo = sizeof(char) * ftell(fp);
fseek(fp, 0, SEEK_SET);
char* archivo = malloc(tamanioArchivo + 1);
fread(archivo, tamanioArchivo + 1, 1, fp);
//do something with archivo
fclose(fp);
free(archivo);

我调试了它,问题似乎在fread行。它带回文件并在最后添加一些垃圾。有什么想法我做错了吗?

3 个答案:

答案 0 :(得分:4)

通常C doesn't care文件的内容是什么。无论是文本还是二进制数据,它的读取方式都是一样的。这意味着如果你想读取一个字符串并获得一些很好的空终止的东西,你需要自己处理它。

fread(archivo, tamanioArchivo+1, 1, fp);

这会读取一个额外的字节(同样,空终止是一个C事件,文件系统不强制执行此操作)。摆脱加1.然后你必须确保它以空终止:

archivo[tamanioArchivo] = '\0';

答案 1 :(得分:1)

试试这个例子:

/* Open Fpga config file */
fpconf = fopen(file, "rb");
if (fpconf == NULL) {
     return ERROR;
}

/* set SEEK_END to read the file size using ftell */
fseek(fpconf, 0L, SEEK_END);

bsize = ftell(fpconf);
print_dbg("Size of file: %d bytes\n", (int)bsize);

/* set file offset 0 */
fseek(fpconf, 0L, SEEK_SET);

data = (uint8_t *) malloc(sizeof(uint8_t) * bsize);
if (data == NULL) {
    print_err("Error in malloc\n");
    return ERROR;
}

/* Read data from file and store into buffer */
fread(data, bsize, 1, fpconf);

/* Close file */
fclose(fpconf);

答案 2 :(得分:1)

“垃圾”来自于不正确地检查/打印archivo而代码没有注意到读了多少。

fread()保存到archivo数据中,但该数据肯定不是空字符终止 - 一个C 字符串。如果'\0'指向字符串,则附加archivo

但是在哪里? 在最后一个字符读取后 - 由fread()的返回值确定,不是在请求的字符数之后。

即使没有错误,由于"\r\n"的文本模式行结束转换为"\n",返回值可能会少于请求的字符数。从ftell()返回的值不一定是在文本模式下读取的字符数。

无需尝试阅读tamanioArchivo+1个字符。使用tamanioArchivo

另请参阅@ Andrew Henle关于fread(ptr, element_size, number_of_elements, stream)参数顺序的好评。

// Note that the file is opened in text mode, not binary mode
FILE *fp = fopen (path, "r");

fseek(fp, 0, SEEK_END);
// int tamanioArchivo = sizeof(char) * ftell(fp);
long tamanioArchivo = ftell(fp);
fseek(fp, 0, SEEK_SET); // or `rewind(fp);

// Good to allocate +1 for the null chracter
char* archivo = malloc(tamanioArchivo + 1u);

// Save the return value and drop the +1
// fread(archivo, tamanioArchivo+1, 1, fp);
size_t read_count = fread(archivo, 1, tamanioArchivo, fp);

// bad
// bytes read may be less than the offset due to CR/LF-->LF or input error
archivo[tamanioArchivo] = '\0';

// good
archivo[read_count] = '\0';

//do something with archivo
puts(archivo); 

fclose (fp);
free(archivo);

强大的代码会检查fopen()malloc()fseek()ftell()的返回值是否存在异常返回值。寻求最终,用于确定文件长度的ftell()方法具有额外的限制。替代方案取决于各种未发布的编码目标。