2013-04-25 56 views
-3

我想打开并读取4 MB bin文件, 但我不能使用fread读取大于700 KB的数据。 其实我想打开并阅读起始ROM文件 这是二进制格式,读取应该从开始到最后一个字节。 试图读取该数量时,运行时发生错误,程序停止并关闭。fread函数只读取大约700kb

我的代码:

#include <stdio.h> 
int main() 
{ 
    FILE* fp; 
    int buffer[4000000]; 
    fp=fopen ("file.bin","rb"); 
    fread (buffer,sizeof(int),4000000,fp); 
} 

什么是错我的代码?

+4

你知道平均堆栈大小是否在1到4兆字节之间?你有几乎16兆字节的堆栈。我很惊讶你的程序甚至加载。 – 2013-04-25 08:15:31

+0

我在C编程中是全新的,如果它可能向我展示如何完成任务,请.. – 2013-04-25 08:19:23

+2

然后这里有几个其他有用的提示(与你的问题无关,但仍然很好):在C中从来没有一个声明函数时为空参数列表。这意味着该函数需要一个未指定数量的未指定参数。当用于'main'时,它实际上不符合规范。如果你想要一个没有参数的函数使用'void',如'int main(void)...'所示。你还声明'main'返回一个'int'(这是正确的),但你实际上并没有返回任何东西。你要么需要调用'exit'或'return'值(零意味着没有错误)。 – 2013-04-25 08:24:14

回答

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; 

} 
+0

小小的例子可以解决问题,,如何使动态分配的缓冲区 – 2013-04-25 08:34:25

+0

@SaeedBasrah试试这个 – Alex 2013-04-25 08:51:02

+0

谢谢亚历克斯我签署了你的答案 – 2013-04-25 08:57:49

3

请在特定块大小的循环中执行读取操作。

0

使buffer成为一个静态变量,所以它不会驻留在堆栈上。

此外,在循环内部使用fread,因为它不会一次读取所有文件。

+0

使缓冲区成为一个静态变量,所以它不会驻留在堆栈上?这将是伟大的,但我真的是新的C。 – 2013-04-25 08:35:56

+0

只需在'int buffer [4000000];'之前放置关键字'static'即可。 这不是最好的解决方案 - 其他的都给了你更好的解决方案。这是最快的。 – Elazar 2013-04-25 08:39:09

+0

是否有任何证据表明使用'static'存储持续时间声明的对象不能位于堆栈上? – Sebivor 2013-04-25 09:48:43

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; 
} 
+0

'return'语句中不需要括号。 'sizeof(char)'也是不必要的,因为它总是1,尽管可以说可以帮助可读性。无论如何,我们都需要+1,1。 – Elazar 2013-04-25 08:51:57

0

我这个代码最大的问题是在这条线:

fread (buffer,sizeof(int),4000000,fp); 

这条线实际上引入了一个重要的问题列表。首先,不能保证您正在阅读的文件已成功打开。正如其他人所指出的那样,您需要比较fpNULL来作出保证。其次,似乎我经常强调这种方式:你真的应该检查返回值。这适用于所有标准C函数,而不仅仅是fopenfread

返回值fread告诉您有多少项实际上被读取。假设你要求四百万int秒,而该文件只包含两个。返回值会告诉你只有两个int被读取。


现在,到大的东西!让我们首先考虑sizeof(int)在不同的实现上有所不同。您的系统可能会读取四个字节,而另一个可能读取两个字节,但可能读取八个字节。这只是整数表示可能不同的基本方式。

让我们考虑一个更微妙的,但同样的破坏性方式整数表示可能会有所不同:假设你的int s为四个字节,用最左边的位是最低显著位。另一台机器可能使用最左边的位作为至少的重要位。同样,考虑字节顺序排列,这是字节的顺序。

假设您的int s是32位,并且它们表示-(1 << 31)(1 << 31)之间的值,这意味着没有填充位。另一个系统可能会使用具有16位填充的32位整数,这意味着它可能仅表示-(1 << 16)(1 << 16)之间的值。假设这些填充位是奇偶校验位,以确保RAM正常运行(例如Intel Xeon服务器)。现在你有一种情况,你的服务器告诉你你的内存有问题,如果没有。

您的代码应该从您的文件用于存储整数的整数表示形式显式转换为计算机本机使用的任何表示形式。在将整数写入文件时,需要确保您明确地将您的实现表示转换为表示表示的。同样,当从文件中读取整数时,代码应该明确地将该表示转换为您的实现表示。例如,让我们假设您的int值不会超出-3276732767(16位有符号整数,1的补码)。使用两个字节来表示这种情况是可移植的,但您需要明确定义该整数的符号和表示形式。写入时,可以提取符号和绝对值,然后将sign * 128 + absolute_value/256absolute_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); 

无论你需要存储的地方不是在问题中指定的转化价值。如果你不需要,那么我的下一个问题就是使用一个数组,当你只能读一个项目,处理它,然后移动到下一个项目。

+0

多数民众赞成在很好的解释和有益thanx ,,,问题是,我只是真正的初学者在C编程。 – 2013-04-25 09:35:13