简体   繁体   English

fread在缓冲区中存储随机字符

[英]fread storing random characters in buffer

I'm simply trying to read a file using fread and output the contents. 我只是尝试使用fread读取文件并输出内容。 It's partially working. 它部分工作。 It outputs everything correctly but it ends with a bunch of random characters. 它正确地输出所有内容但它以一堆随机字符结束。

#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();
}

Let's say 'size' is 50 in this instance. 假设在这种情况下'size'为50。 for some reason, the size of buffer ends up 55 or 56 after fread is called. 由于某种原因,在调用fread之后,缓冲区的大小最终会达到55或56。 I emptied the buffer before using it and tried outputting it, everything is normal (it's empty). 我在使用它之前清空了缓冲区并尝试输出它,一切正常(它是空的)。 Right after the call to fread the buffer somehow gets bigger and is filled with random characters. 在调用fread之后,缓冲区以某种方式变得更大并且充满了随机字符。 I've opened the text file in a hex editor to ensure there isn't anything I'm not seeing but there isn't. 我已经在十六进制编辑器中打开了文本文件,以确保没有任何我没有看到但没有。 The file is 50 bytes. 该文件是50个字节。 fread returns the amount of bytes read, in this case returned to 'r', 'r' is what it should be. fread返回读取的字节数,在这种情况下返回'r','r'应该是它应该是什么。 so where the mother eff are these bytes coming from? 所以这些字节来自哪个母亲?

simplified: fread returns correct amount of bytes read but the buffer somehow makes itself bigger after fread is called, then fills it with random characters. 简化:fread返回正确读取的字节数,但缓冲区在调用fread后以某种方式使自身变大,然后用随机字符填充它。 why? 为什么?

I can't for the life of me figure out how this is happening. 我不能为我的生活弄清楚这是怎么回事。

Also, before anyone gives me an easy fix, I already know I could just do buffer[r] = '\\0' and not have it output anymore random characters but I'd much rather know WHY this is happening. 此外,在任何人给我一个简单的修复之前,我已经知道我可以做缓冲[r] ='\\ 0'并且不再输出任何随机字符,但我更愿意知道为什么会发生这种情况。

cout 's << operator on char* expects C strings, so you need to null-terminate your buffer : cout<< char* on char*需要C字符串,所以你需要null-terminate你的buffer

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

The extra characters that you see is random data in the memory addresses after the end of your buffer . 您看到的额外字符是buffer结束后内存地址中的随机数据。 operator << does not know that the string has ended, so it continues printing until it finds the first '\\0' byte. operator <<不知道字符串已经结束,所以它继续打印,直到找到第一个'\\0'字节。

You probably just forgot about null terminating the buffer. 你可能只是忘了null终止缓冲区。 Instead, use cout.write and supply the length of the buffer: 相反,使用cout.write并提供缓冲区的长度:

Adding a bit of error handling (not enough, but a start), missing includes and using statements: http://coliru.stacked-crooked.com/view?id=8bc4f3b7111554c705de96450d806104-f674c1a6d04c632b71a62362c0ccfc51 添加一些错误处理(不够,但开始),缺少包含和使用语句: 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();
}

Actually cout will print the string until it does not get any NULL char. 实际上cout会打印字符串,直到它没有得到任何NULL字符。 That mean it needed a NULL for termination. 这意味着终止需要NULL。

But assign a NULL is not a good solution for all the times. 但是分配NULL并不是一直很好的解决方案。 Your data might be a binary at that time cout will print only the output up to the NULL char. 那时你的数据可能是二进制文件,cout只打印输出到NULL char。 I mean binary data could be anything and it could be a not readable char also. 我的意思是二进制数据可以是任何东西,它也可能是一个不可读的字符。 and cout will consider it as a NULL char. 并且cout会将其视为NULL char。 That's why it always safe to use a for loop up to the length of the string or your dataset. 这就是为什么使用for循环直到字符串或数据集的长度总是安全的。

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

//or you could use FILE *fp; //或者你可以使用FILE * fp; for (int i= 0; i < len; i++) fprintf(fp, "%c", buffer[i]); for(int i = 0; i <len; i ++)fprintf(fp,“%c”,buffer [i]); another good approach is to use fwrite. 另一个好方法是使用fwrite。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM