以下功能无效,即退出:
fread(buf, 1, 4, stdin);
buf[4] = '\0';
if (strcmp((char*)buf, "data")) exit(EXIT_FAILURE);
我认为如果我可以手动将fread推到更远的流中,它最终会点击“数据”。
换句话说,如何增加fread以便跳过字节。
代码示例总是受到赞赏。
谢谢!
编辑1
基本上我正在解析iPhone上wav文件的标题。它给了我一些麻烦,我相信这与苹果格式化音频文件的方式有关。有人建议我在流中直到获得“数据”,然后从那里继续前进。
我希望这能澄清事情。
编辑2
Here is documentation as to how the wav file header should look like,但我想知道苹果格式化他们的方式是否会导致这种情况不准确。
您会注意到'数据'偏移36,这是4的倍数。
答案 0 :(得分:2)
这可以像时尚一样流动,并按照我的想法做到:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv)
{
long pos = 0;
char buf;
char str[5] = {'\0','\0','\0','\0','\0'};
while ( fread(&buf, sizeof(char), 1, stdin) > 0 )
{
pos++;
str[0] = str[1];
str[1] = str[2];
str[2] = str[3];
str[3] = buf;
str[4] = '\0';
/* uncomment to see what got read ** printf("Read %s\n", str); */
if ( strcmp(str, "data") == 0 )
{
break;
}
}
printf("\"data\" occured after %ld bytes\n", pos);
return 0;
}
这可以通过使用我称为str
的缓冲区并旋转其中的位置来实现。它会一直有效,直到data
出现。
请注意,它会读取二进制数据,而不是文本。所以stdin上的任何内容都会被读取,包括换行符。但是,如果您将其调整为不应该成为问题的文件句柄。
你可以包括这个。使用fread
的问题在于设计:
流的文件位置指示符(如果已定义)应按成功读取的字节数提前。
因此,如果您一次前进4个字节,除非您的数据恰好是数据开头的4的倍数,否则您将错过它。例如:
123DATA
如果一次读取4个字节,则会失败。
现在,鉴于这是一个文档化的文件格式,是否有某些标题规范可以告诉您标题字段的确切宽度?或者至少在它们变化的地方,你可以适当地阅读它们吗?阅读直到data
有效,但实际上并不优雅。
或者,更好的是,我确信必须有一个库可以在某处执行此操作。
编辑响应波形文件的标题,由于它是固定的而不是那么大,所以将整个内容读入缓冲区。
uint8_t* hdr = malloc(36*sizeof(uint8_t));
fread(hdr, sizeof(uint8_t), 36);
别忘了自由。此时,您已提取整个标头。我使用uint8_t
肯定是8
位。在这个阶段,你可以提取一些有趣的技巧,比如将数据转换为结构。请注意字段的字节顺序。
从那时起,我相信这个流可以以大块的形式提供给你。你需要做的第一件事是:
uint8_t chkid;
uint8_t chksz;
fread(&chkid, sizeof(uint8_t), 4, stream);
fread(&chksz, sizeof(uint8_t), 4, stream);
那将抓住你那个特定块的数据。假设您正在使用一个小端系统,此时您应该能够直接使用chksz
作为整数,所以现在可以这样做:
uint8_t dataframe = malloc(chksz * sizeof(uint8_t));
您可以在其中阅读数据:
fread(&dataframe, sizeof(uint8_t), chksz, stream);
这当然是假设Apple波形是描述的那种。现在,从该页面开始:
WAVE文件格式是Microsoft的RIFF规范的一个子集,用于存储多媒体文件。 RIFF文件以文件头开头,后跟一系列数据块。 WAVE文件通常只是一个RIFF文件,其中包含一个“WAVE”块,它由两个子块组成 - 一个指定数据格式的“fmt”块和一个包含实际样本数据的“数据”块。将此表格称为“规范形式”。谁知道它真的如何运作。
我已经给你指示如果在连续循环中使用,直到流上没有其他内容,将允许你读取任意数量的数据块a-la RIFF。然后,您需要处理适当的数据以将其分解;即拆分您正确阅读的数据块。如果这是您希望阅读的唯一格式,则可以忽略其他块。
现在,问题仍然存在,什么是苹果格式,说实话我不知道!
答案 1 :(得分:1)
我认为不能保证ASCII中第一次出现data
是数据头的开头,因为这四个字节也可能作为WAV format格式块的一部分出现。解析WAV的更好方法是(未经测试)
/* Returns the size of the data payload */
off_t skip_to_data_payload(FILE *fp)
{
unsigned char buf[4];
int i;
off_t size;
// the "data" magic should start at byte 36
for (i=0; i<9; i++)
fread(buf, 1, 4, fp);
fread(buf, 1, 4, fp);
if (memcmp(buf, "data", 4) != 0)
return (off_t)(-1);
// read size, assume little-endian
fread(buf, 1, 4, fp);
off_t size = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[4] << 24);
return size;
}
注意:我假设PCM编码和小端文件。由于Apple过去使用过大端处理器,所以你真的应该检查一下。 (或使用库。)
答案 2 :(得分:0)
strcmp将永远不会工作,因为你需要一个额外的字符串终止(\ 0),你已经用完了你的字符串的所有4个字符。请尝试使用strncmp
。如果在使用stdin时添加更多字符,请不要忘记换行符。