Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 通过fget/缓冲字符串解码二进制文件(尝试获取mp3头)_C_Binary_Header_Mp3_Decoding - Fatal编程技术网

C 通过fget/缓冲字符串解码二进制文件(尝试获取mp3头)

C 通过fget/缓冲字符串解码二进制文件(尝试获取mp3头),c,binary,header,mp3,decoding,C,Binary,Header,Mp3,Decoding,我正在写一些快速代码,尝试从mp3文件头提取数据 目标是从头中提取信息,如比特率和其他重要信息,以便我可以使用必要的参数将文件适当地流式传输到mp3decoder 以下是显示mp3header信息的wikipedia图像: 我的问题是,我的攻击是否正确?打印接收到的数据毫无价值——我只得到一堆随机字符。我需要找到二进制文件,这样我才能解码它并确定重要信息 以下是我的基线代码: // mp3 Header File IO.cpp : Defines the entry point for the

我正在写一些快速代码,尝试从mp3文件头提取数据

目标是从头中提取信息,如比特率和其他重要信息,以便我可以使用必要的参数将文件适当地流式传输到mp3decoder

以下是显示mp3header信息的wikipedia图像:

我的问题是,我的攻击是否正确?打印接收到的数据毫无价值——我只得到一堆随机字符。我需要找到二进制文件,这样我才能解码它并确定重要信息

以下是我的基线代码:

// mp3 Header File IO.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"

// Main function
int main (void)
{
    // Declare variables
    FILE *mp3file;
    char *mp3syncword; // we will need to allocate memory to this!!
    char requestedFile[255] = "";
    unsigned long fileLength;

    // Counters
    int i;

    // Memory allocation with malloc
    mp3syncword=(char *)malloc(2000);

    // Let's get the name of the requested file (hard-coded for now)
    strcpy(requestedFile,"testmp3.mp3");

    // Open the file with mode read, binary
    mp3file = fopen(requestedFile, "rb"); 
    if (!mp3file){
         // If we can't find the file, notify the user of the problem
         printf("Not found!");
    }

    // Let's get some header data from the file
    fseek(mp3file,1,SEEK_SET);
    fread(mp3syncword,32,1,mp3file);

    // For debug purposes, lets print the received data
     for(i = 0; i < 32; ++i)
        printf("%c", ((char *)mp3syncword)[i]);
    enter code here
    return 0;
}
//mp3头文件IO.cpp:定义控制台应用程序的入口点。
//
#包括“stdafx.h”
#包括“stdio.h”
#包括“string.h”
#包括“stdlib.h”
//主要功能
内部主(空)
{
//声明变量
文件*mp3file;
char*mp3syncword;//我们需要为此分配内存!!
char requestedFile[255]=“”;
无符号长文件长度;
//计数器
int i;
//用malloc进行内存分配
mp3syncword=(char*)malloc(2000);
//让我们获取所请求文件的名称(目前为硬编码)
strcpy(requestedFile,“testmp3.mp3”);
//以二进制读取模式打开文件
mp3file=fopen(requestedFile,“rb”);
如果(!mp3file){
//如果找不到该文件,请通知用户该问题
printf(“未找到!”);
}
//让我们从文件中获取一些头数据
fseek(mp3文件,1,SEEK\u集);
fread(mp3syncword,32,1,mp3file);
//出于调试目的,让我们打印接收到的数据
对于(i=0;i<32;++i)
printf(“%c”,((char*)mp3syncword)[i]);
在这里输入代码
返回0;
}

感谢您的帮助。

您正在使用
%c
作为格式说明符打印字节。您需要使用无符号数字格式说明符(例如,
%u
表示十进制数或
%x
%x
表示十六进制)来打印字节值

您还应该将字节数组声明为
无符号字符
,因为它们在Windows上默认是有符号的

您可能还希望在每个字节值后打印一个空格(或其他分隔符),以使输出更清晰

标准
printf
不提供二进制表示类型说明符。某些实现确实有此功能,但随Visual Studio提供的版本没有。为了输出该值,您需要对数字执行位操作,以提取各个位,并为每个字节依次打印每个位。例如:

unsigned char byte = // Read from file
unsigned char mask = 1; // Bit mask
unsigned char bits[8];

// Extract the bits
for (int i = 0; i < 8; i++) {
    // Mask each bit in the byte and store it
    bits[i] = (byte & (mask << i)) >> i;
}

// The bits array now contains eight 1 or 0 values
// bits[0] contains the least significant bit
// bits[7] contains the most significant bit
unsigned char byte=//从文件读取
无符号字符掩码=1;//位掩码
无符号字符位[8];
//提取比特
对于(int i=0;i<8;i++){
//屏蔽字节中的每一位并存储它
位[i]=(字节和(掩码>i;
}
//位数组现在包含八个1或0值
//位[0]包含最低有效位
//位[7]包含最高有效位

C没有用于二进制打印的
printf()
说明符。大多数人使用十六进制打印,一次只能打印八位:

printf("the first eight bits are %02x\n", (unsigned char) mp3syncword[0]);
您需要手动对此进行解释,以计算出各个位的值。参数上转换为
unsigned char
是为了避免出现负值时的意外情况


要测试位,可以将
&
运算符与按位左移运算符一起使用,
警告:这种方法可能会导致内存布局和/或endianess错误。不能保证结构成员在计算机之间匹配相同的位。
简言之:不要依赖于此(我会留下答案,它可能对其他事情有用)

可以使用位字段定义结构:

struct MP3Header {
    unsigned SyncWord : 12;
    unsigned Version : 1;
    unsigned Layer : 2;
    unsigned ErrorProtection : 1;
    unsigned BitRate : 4;
    unsigned Frequency : 2;
    unsigned PadBit : 1;
    unsigned PrivBit : 1;
    unsigned Mode : 2;
    unsigned ModeExtension : 2;
    unsigned Copy : 1;
    unsigned Original : 1;
    unsigned Emphasis : 2;
};
然后将每个成员用作独立值:

struct MP3Header h;
/* ... */
fread(&h, sizeof h, 1, mp3file); /* error check!! */
printf("Frequency: %u\n", h.Frequency);

作为旁注,我不能使用现有的大多数库来完成这类工作,因为这段代码需要在资源有限的微控制器上运行。在printf语句中更改为%d确实会给我带来一大堆数值——但是,我怀疑它们是否是二进制6851300147118658073670083-3300030-1-40-1-32016747073结果中的破折号。这看起来不正确。我考虑过将数据保存到字符以外的其他位置,但我不认为这会起作用,因为这是二进制的。哦--当然,它不能是二进制的!值不是1和0。抱歉,您应该将它们视为无符号的
数字(这就是为什么你会看到破折号-减号).哦…我想我明白了。你想打印出字节的二进制表示,对吗?嗯,我需要以某种方式解析文件的前32位,然后能够分析位17-20,以确定比特率。维基百科的图片有帮助。你正确地说,将其更改为无符号数字helps——但我没有得到二进制值。老实说,我将采用二进制、十六进制或任何格式的前32位。这是非常危险的;您不知道位字段将在内存中排列以匹配文件格式。您还依赖于endianness,并且可能会受到填充的影响。@unwind:关于内存布局和endiannes,您是对的s、 但不是填充(我回答时唯一考虑的事情)——请参见标准中的6.7.2.1/10。谢谢您的警告。
struct MP3Header h;
/* ... */
fread(&h, sizeof h, 1, mp3file); /* error check!! */
printf("Frequency: %u\n", h.Frequency);