C 当到达文件末尾时,fread如何处理尾随垃圾?
我最近又开始涉足C语言,这是一种我不是特别精通的语言,事实上,我一直在忘记(我主要用Python编写代码)。我的想法是从一个假设的大文件中读取数据作为块,然后相应地处理数据。现在,我通过将整个文件加载到带有fread的short类型的缓冲区来模拟这个过程。这种方法将会改变,因为我认为,对于一个1GB的文件来说,这是一个非常糟糕的主意。最终目标是将一个块作为一个块读取、处理、移动光标、读取另一个块,等等 这个文件有43个字节,上面有短语“敏捷的棕色狐狸跳过了懒狗”。这个大小很方便,因为它是一个素数,所以无论我把它分成多少字节,都会有尾随垃圾(因为缓冲区有剩余空间?)。在这种情况下,数据处理只是在字节操作后将短字符打印为两个字符(参见下面的代码)C 当到达文件末尾时,fread如何处理尾随垃圾?,c,fread,C,Fread,我最近又开始涉足C语言,这是一种我不是特别精通的语言,事实上,我一直在忘记(我主要用Python编写代码)。我的想法是从一个假设的大文件中读取数据作为块,然后相应地处理数据。现在,我通过将整个文件加载到带有fread的short类型的缓冲区来模拟这个过程。这种方法将会改变,因为我认为,对于一个1GB的文件来说,这是一个非常糟糕的主意。最终目标是将一个块作为一个块读取、处理、移动光标、读取另一个块,等等 这个文件有43个字节,上面有短语“敏捷的棕色狐狸跳过了懒狗”。这个大小很方便,因为它是一个素数
#包括
#包括
#定义最大BUFF大小1024
长文件大小(文件*f)
{
如果(fseek(f,0,SEEK_END)!=0)退出(exit_FAILURE);//将光标移到末尾
long file_size=ftell(f);//确定获取文件大小的位置
倒带(f);
返回文件大小;
}
int main(int argc,char*argv[])
{
short buff[MAX\u buff\u SIZE]={0};//初始化为0删除尾部垃圾
char*filename=argv[1];
FILE*fp=fopen(文件名,“r”);
if(fp)
{
size_t size=sizeof(buff[0]);//每个块的大小(以字节为单位)。固定为2字节
int nmemb=(文件大小(fp)+size-1)/size;//要从文件中读取的块数
//(天花板f_尺寸/尺寸)
printf(“最多应读取%d个块”,nmemb);
short mask=0xFF;//获取第一个或第二个字节的掩码
size\u t num\u read=fread(buff,size,nmemb,fp);
printf(“读取%lu块\n\n”,num_Read);//似乎读了更多?查看。
对于(int i=0;i>8)&mask;//标识2个字节。保留掩码以保持一致性
printf(“块%02d:0x%04x |%c%c\n”,//记住小尾端(字节颠倒)
i、 buff[i],第一个字节,第二个字节);
}
fclose(fp);
}否则
{
printf(“未找到文件%s\n”,文件名);
返回1;
}
返回0;
}
昨天,在打印最后一块数据时,我得到了“chunk 21:0xffff9567 | g”。最后一个(第一个?)字节(0x67)是g,我确实希望有一些尾随垃圾,但我不明白为什么当变量buff中有短路时,它会打印出这么多字节。当时我只是将十六进制打印为%x,而不是%04x,buff没有初始化为0。今天,我决定将其初始化为0,不仅垃圾消失了,而且即使在再次取消初始化buff后,我也无法重新创建问题
下面是我希望不要太抽象的问题:
为了澄清这一点,由于我在注释中读错了位置,我希望保留剩余的字节(或数据),而丢弃其余的未定义的字节(或数据)。我不知道这是否是通常的方法,因为如果我在循环中使用num\u read,那么不管最后剩下的是什么,不管是不是数据,都会被丢弃。我更感兴趣的是知道通常的方法是什么:丢弃剩余数据或删除我们知道的未定义的任何内容,在本例中是一个字节。您希望如何处理最后剩余的字节?在我看来,您的循环应该基于
num_read
,因为%x取一个无符号int,所以它将通过符号扩展将你的签名短转换为int,这意味着符号位(最有效位)将被用来填充空白空间。因为您的short是0x9567,所以设置了符号位,这意味着空空间将被1s填充,从而导致0xffff9567。如果使用无符号的短字符,您将看不到0xffff。@MikeCAT只能放弃,因为它们不是来自文件本身的数据。只要我将数组初始化为零,C似乎可以帮我做到这一点,这就是为什么我假设垃圾来自统一化的缓冲区而不是fread,但我不确定,因为我不知道fread本身是如何工作的fread()
的行为如文档所述。否则,许多人会抱怨过去40年。您想如何处理最后的剩余字节?在我看来,您的循环应该基于num_read
,而不是nmemb
。由于%x接受一个无符号int,它将通过符号扩展将您的有符号short转换为int,这意味着符号位(最高有效位)
#include <stdio.h>
#include <stdlib.h>
#define MAX_BUFF_SIZE 1024
long file_size(FILE *f)
{
if (fseek(f, 0, SEEK_END) != 0) exit(EXIT_FAILURE); // Move cursor to the end
long file_size = ftell(f); // Determine position to get file size
rewind(f);
return file_size;
}
int main(int argc, char* argv[])
{
short buff[MAX_BUFF_SIZE] = {0}; // Initialize to 0 remove trailing garbage
char* filename = argv[1];
FILE* fp = fopen(filename, "r");
if (fp)
{
size_t size = sizeof(buff[0]); // Size in bytes of each chunk. Fixed to 2 bytes
int nmemb = (file_size(fp) + size - 1) / size; // Number of chunks to read from file
// (ceil f_size/size)
printf("Should read at most %d chunks\n", nmemb);
short mask = 0xFF; // Mask to take first or second byte
size_t num_read = fread(buff, size, nmemb, fp);
printf("Read %lu chunks\n\n", num_read); // Seems to have read more? Look into.
for (int i=0; i<nmemb; i++) {
char first_byte = buff[i] & mask;
char second_byte = (buff[i] >> 8) & mask; // Identity for 2 bytes. Keep mask for consistency
printf("Chunk %02d: 0x%04x | %c %c\n", // Remember little endian (bytes reversed)
i, buff[i], first_byte, second_byte);
}
fclose(fp);
} else
{
printf("File %s not found\n", filename);
return 1;
}
return 0;
}