这是我现在尝试的与cs50“恢复”中以前的问题有关的代码的摘录。
我已经用fread
进行了所有尝试,但是由于某种原因,它根本无法按照我想要的方式工作。
在此循环中,我试图弄清楚fread
的实际工作方式。
我对fread
的问题是-每次调用时,它是否一次从指向(rawdata
)的文件中读取512字节的数据1?在那种情况下,我的代码应该工作,因为循环是无限期地运行,一次又一次地调用该函数,因此一次将流位置/文件游标(我不知道其叫什么)移动512字节。我在feof(rawdata)
的圈里休息了。
我正在使用这个小程序来帮助我从cs50 pset4中恢复。
// In a loop, until the end of file has been reached,
while (true) {
// Zeroing counter
jpg_counter = 0;
// Reading 512 bytes into the array of bytes
fread(bytes, 512, 1, rawdata);
// Searching the 512 bytes for JPEG signatures - bytes[3] with bitwise AND
if (bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff && (bytes[3] & 0xf0) == 0xe0) {
jpg_counter++;
}
// If found JPG, add total and keep going till end of file
if (jpg_counter != 0) {
total++;
}
//feof returns a non zero value only at the end of a file
if (feof(rawdata) != 0) {
break;
}
}
printf("%i\n", total);
答案 0 :(得分:1)
您的方法存在两个主要问题:
您没有在读取循环中正确测试文件结尾。您应该使用返回值fread
来确定是否已从流中读取至少一个字节,并且应该以相反的顺序传递参数:您正在读取多达512个字节:
size_t n;
while ((n = fread(bytes, 1, 512, rawdata)) > 0) {
// n bytes were read from the file.
,您仅测试JPEG签名的前4个字节。除非已知文件具有非常特定的结构,否则您可能要在块中搜索签名。
必须小心处理签名重叠的块,即:从512字节的块的末尾开始,在下一个块的末尾结束。
这是修改后的版本:
int count_jpeg(FILE *rawdata) {
unsigned char bytes[3 + 512];
int pos = 0, end, i;
int total = 0;
size_t nread;
// In a loop, until the end of file has been reached,
while ((nread = fread(bytes + pos, 1, 512, rawdata)) > 0) {
end = pos + nread - 3;
for (i = 0; i < end; i++) {
// Searching the block for JPEG signatures - bytes[3] with bitwise AND
if (bytes[i] == 0xff && bytes[i + 1] == 0xd8
&& bytes[i + 2] == 0xff && (bytes[i + 3] & 0xf0) == 0xe0) {
total++;
i += 3;
}
}
// copy the last 3 bytes to the beginning of the block
for (i = pos = 0; i < 3; i++)
if (end + i >= 0) {
bytes[pos++] = bytes[end + i];
}
}
printf("%i\n", total);
return total;
}
编辑::如果已知JPEG签名在512字节边界上对齐,则可以删除扫描循环,但是仍然可以读取文件末尾的部分块:
int count_jpeg(FILE *rawdata) {
unsigned char bytes[512];
int total = 0;
// In a loop, until the end of file has been reached,
while (fread(bytes + pos, 1, 512, rawdata) > 4) {
/* check for a signature at the beginning of the block */
if (bytes[0] == 0xff && bytes[1] == 0xd8
&& bytes[2] == 0xff && (bytes[3] & 0xf0) == 0xe0) {
total++;
}
}
printf("%i\n", total);
return total;
}
答案 1 :(得分:0)
恐惧状态手册页
函数fread()读取nmemb数据项,每个数据项的长度为字节, 从流指向的流中,将它们存储在该位置 由ptr提供
因此您可以将读取的元素数量存储在变量中,并检查是否读取了512个字节。
int nmenb = fread(bytes, 512, 1, rawdata);
if( nmemb != 1 )
{
//exit
}
else{
// 512 bytes read successfully
}