我正在尝试打开并读取4 MB bin文件,
但我无法使用fread
读取超过700 KB的内容。
其实我想打开并阅读创世纪ROM文件
这是二进制格式,读取应该从开始到最后一个字节。
当试图读取该数量时,错误发生在运行时,程序停止并关闭。
我的代码:
#include <stdio.h>
int main ()
{
FILE* fp;
int buffer[4000000];
fp=fopen ("file.bin","rb");
fread (buffer,sizeof(int),4000000,fp);
}
我的代码出了什么问题?
答案 0 :(得分:3)
请针对特定的块大小循环执行读取操作。
答案 1 :(得分:1)
[1]缺少返回(返回否定表示发生错误)
[2]使用malloc(动态分配堆)而不是堆栈
[3]检查文件读取,内存分配和指针的指针值。读取的字节数
#include <stdio.h>
#include <stdlib.h>
int main ()
{
FILE * pFile;
char * buffer;
size_t size = 4194304;
size_t result;
pFile = fopen ( "file.bin" , "rb" );
if (pFile==NULL) {
fputs ("Unable to open file",stderr);
return (-1);
}
buffer = (char*) malloc (sizeof(char)*size);
if (buffer == NULL) {
fputs ("Unable to allocate memory",stderr);
return (-2);
}
result = fread (buffer,1,size,pFile);
if (result != size) {
fputs ("Unable to read 4 MB",stderr);
return (-3);
}
fclose (pFile);
free (buffer);
return 0;
}
答案 2 :(得分:0)
更好的选择是加载文件我的块。
另外,为了不用完堆栈,你应该使用动态分配的缓冲区,因为heap
大于stack
。
#define BLOCK_SIZE 4096
#include <stdio.h>
#include <stdlib.h>
int read_file(FILE* file, unsigned char* buffer);
int main ()
{
FILE* fp;
unsigned char* buffer = NULL;
int bytes_read = 0;
fp=fopen ("file.bin","rb");
bytes_read = read_file(fp, buffer);
return 0;
}
int read_file(FILE* file, unsigned char* buffer)
{
int bytes_read = 0;
int block_bytes_read = 0;
unsigned char block[BLOCK_SIZE];
do
{
block_bytes_read = fread (block,sizeof(char),BLOCK,file);
buffer = realloc(buffer, block_bytes_read*sizeof(char));
memcpy((buffer + bytes_read), block, block_bytes_read*sizeof(char));
bytes_read += block_bytes_read;
} while (block_bytes_read != 0);
return bytes_read;
}
答案 3 :(得分:0)
使buffer
成为静态变量,因此它不会驻留在堆栈上。
此外,在循环中使用fread
,因为它不能保证一次读取所有文件。
答案 4 :(得分:0)
我对此代码的最大问题是:
fread (buffer,sizeof(int),4000000,fp);
这一行实际上引入了一系列重要问题。首先,无法保证您正在读取的文件已成功打开。您需要将fp
与NULL
进行比较以作出保证,正如其他人所指出的那样。其次,我似乎经常这样强调:你真的应该检查返回值。这适用于所有标准C函数,而不仅仅是 fopen 和 fread 。
fread 的返回值告诉您实际读取了多少项。假设您要求四百万int
个,并且该文件只包含两个。{返回值将告诉您只读取了两个int
。
现在,重要的事情!我们首先考虑sizeof(int)
在不同的实现上有所不同。您的系统可能会读取四个字节,而另一个可能读取两个字节,另一个可能读取八个字节这只是整数表示可能不同的基本但基本的方式。
让我们考虑一个更微妙但同样具有破坏性的方式整数表示可能不同:假设您的int
是四个字节,最左边的位是最低有效位。另一台机器可能使用最左边的位作为最小有效位。同样,请考虑 endianness ,这是字节的顺序。
假设您的int
是32位,它们代表-(1 << 31)
和(1 << 31)
之间的值,这意味着没有填充位。另一个系统可能使用具有16位填充的32位整数,这意味着它可能仅表示-(1 << 16)
和(1 << 16)
之间的值。假设这些填充位是奇偶校验位,以确保RAM正常运行(例如,Intel Xeon服务器)。现在你的情况是你的服务器告诉你你的RAM有问题,而不是。
您的代码应明确地从您的文件用于存储整数的整数表示转换为您的计算机本机使用的任何表示形式。将整数写入文件时,需要确保将实现表示显式转换为 表示。同样,当从文件中读回整数时,您的代码应该明确地将该表示转换为您的实现表示。
例如,我们假设您的int
值不会超出-32767
或32767
(16位有符号整数,1'补码)。使用两个字节来表示它是可移植的,但是你需要明确地定义该整数的符号和表示。写作时,您可以提取符号和绝对值,然后将sign * 128 + absolute_value / 256
和absolute_value % 256
写入您的文件。在阅读时,您将提取符号位,乘以并添加以重建您的值。
我们假设您的文件大小为4MB,但您正在阅读sizeof (int) * 4000000
个值。 4MB是0x400000
,而不是sizeof (int) * 4000000
。我想你真正想要的是:
unsigned char *foo = malloc(0x400000); /* 4MB */
/* XXX: Handle malloc errors here */
assert(foo != NULL);
FILE *fp = fopen("file.bin", "rb");
/* XXX: Handle fopen errors here */
assert(fp != NULL);
size_t num_bytes_read = fread(foo, 1, 0x400000, fp);
/* XXX: Transform the bytes into integers */
free(foo);
我的问题在于它依赖于4MB缓冲区来读取字节并将其转换为整数。此任务根本不需要缓冲区!
FILE *fp = fopen("file.bin", "rb");
/* XXX: Handle fopen errors here */
assert(fp != NULL);
for (;;) {
int x = fgetc(fp);
/* XXX: Handle fgetc errors here */
assert(x >= 0);
int y = fgetc(fp);
/* XXX: Handle fgetc errors here */
assert(y >= 0);
/* XXX: Transform the characters in x and y into the int values */
};
free(foo);
问题中是否未指定是否需要在某处存储转换后的值。如果您不需要,那么我的下一个问题是使用数组,当您只是阅读单个项目,处理它然后移动到下一个项目时。