2

我只是尝试使用 fread 读取文件并输出内容。它正在部分工作。它正确输出所有内容,但以一堆随机字符结尾。

#include <iostream>

using namespace std;

void ReadFile(char* filename,char*& buffer)
{
    FILE *file = fopen(filename,"rb");

    fseek(file,0,SEEK_END);
    int size = ftell(file);
    rewind(file);

    buffer = new char[size];
    memset(buffer,0,size);

    int r = fread(buffer,1,size,file);
    cout << buffer;

    fclose(file);
}

int main()
{
    char* buffer;
    ReadFile("test.txt",buffer);
    cin.get();
}

假设在这种情况下“大小”为 50。由于某种原因,调用 fread 后缓冲区的大小最终变为 55 或 56。我在使用它之前清空了缓冲区并尝试输出它,一切正常(它是空的)。在调用 fread 之后,缓冲区不知何故变大并充满了随机字符。我已经在十六进制编辑器中打开了文本文件,以确保没有任何我没有看到但没有的东西。该文件为 50 个字节。fread 返回读取的字节数,在这种情况下返回到 'r','r' 是它应该是什么。那么这些字节来自哪里?

简化: fread 返回读取的正确字节数,但缓冲区在调用 fread 后会以某种方式变大,然后用随机字符填充它。为什么?

我一生都无法弄清楚这是怎么发生的。

此外,在任何人给我一个简单的修复之前,我已经知道我可以只做 buffer[r] = '\0' 并且不再让它输出随机字符,但我更想知道为什么会这样。

4

3 回答 3

6

cout<<运算符char*需要 C 字符串,因此您需要空终止您的buffer:

int size = ftell(file)+1; // Leave space for null terminator
...
int r = fread(buffer,1,size-1,file); 
buffer[r] = '\0';
cout << buffer;

您看到的额外字符是 . 结尾后内存地址中的随机数据bufferoperator <<不知道字符串已经结束,所以它会继续打印,直到找到第一个'\0'字节。

于 2013-07-17T18:55:23.150 回答
0

您可能只是忘记了 null 终止缓冲区。相反,使用 cout.write 并提供缓冲区的长度:

添加一些错误处理(还不够,但开始),缺少包含和使用语句:http ://coliru.stacked-crooked.com/view?id=8bc4f3b7111554c705de96450d806104-f674c1a6d04c632b71a62362c0ccfc51

#include <iostream>
#include <string>
#include <vector>
#include <cstring>

using namespace std;

void ReadFile(const char* filename,char*& buffer)
{
    FILE *file = fopen(filename,"rb");

    if (!file)
         return;

    fseek(file,0,SEEK_END);
    int size = ftell(file);
    rewind(file);

    buffer = new char[size];
    memset(buffer,0,size);

    int r = fread(buffer,1,size,file);
    cout.write(buffer, r);

    fclose(file);
}

int main()
{
    char* buffer;
    ReadFile("test.txt",buffer);
    cin.get();
}
于 2013-07-17T18:55:53.850 回答
0

实际上 cout 将打印字符串,直到它没有得到任何 NULL 字符。这意味着它需要一个 NULL 来终止。

但是分配一个 NULL 并不是一个好的解决方案。那时您的数据可能是二进制文件,cout 只会将输出打印到 NULL 字符。我的意思是二进制数据可以是任何东西,也可以是不可读的字符。cout 会将其视为 NULL 字符。这就是为什么在字符串或数据集的长度内使用 for 循环总是安全的。

len = strlen(buffer)
for (int i = 0; i < len; i++)
     printf("%c", buffer[i])     

//或者你可以使用 FILE *fp; for (int i= 0; i < len; i++) fprintf(fp, "%c", buffer[i]); 另一个好方法是使用 fwrite。

于 2013-07-17T19:22:45.390 回答