在低位优先的计算机中使用C++读取高位优先的二进制文件的方法

最近在跟老师做小学期项目,用到了mfcc。他们提供的工具生成了一个二进制频谱序列,并且提供了matlab方法对该文件进行读取,然而matlab用的不熟,想用cpp去解决之后的一系列问题,所以只能靠看matlab源代码分析出这个二进制文件的存储规范。然而这些mfc文件是用“高位优先”的方式去存储文件的,matlab在fopen中提供了以高位优先方式读取数据的参数选项,然而这个参数选项在cpp中没有。在网上查阅了大量的资料始终找不到现成的转换方法,只能自己动手写一个了。(对我来说这是新知识,不能保证我的分析是正确的)

首先来介绍一下什么叫做高位优先。

在计算机的编码中,有一个叫做字节序的东西,用来描述字节是从前段开始进入处理器还是从后端开始进入处理器。

高位优先(Big Endian)代表高地址位在整个地址位的前端

低位优先(Little Endian)代表低地址位在整个地址位的前端

具体的存储方式是这样的:

假设有一个4字节int类型,值为358,它在低位优先机的表示方法是十六进制数:66 01 00 00。而它在高位优先机的表示方法是十六进制数:00 00 01 66。这样的话,文件的存储形式与读取方式就会发生多种匹配。

对于文件来说,文件的存储格式(高位优先或者低位优先)是不会根据cpu不同而变化的,它是用它本身的形式存储在硬盘之中。

但是对于cpu来说,不同方式解读这个文件就会得到不同的结果。

我们最常见的cpu大多都是以低位优先存储数据的,所以当我们调用cpp中的fread函数来读取高位优先的文件之后,就会自动以低位优先的方式去读取这个文件,读取出来的数据将会是千差万别。

下面是我写的在低位优先机上以高位优先模式打开高位优先文件的方法:

void freadByBigEndian(void *buf,size_t size1, size_t size2,FILE *file){  
    char *tmparr = new char[size1*size2];  
    for(long i=(size1*size2)-1;i>=0;i--){  
        char tmp;  
        fread(&tmp,1,1,file);  
        tmparr[i]=tmp;  
    }  
    memcpy(buf, tmparr, size1*size2);  
}  

这段代码的参数(内容与顺序)均与fread函数一样。

  • void *buf:是拷贝目标
  • size_t size1:单次拷贝字节大小(例如4就是int,2就是short)
  • size_t size2:连续拷贝次数
  • FILE *file:拷贝的文件

注:本函数是在MAC OS 10.7 Xcode 4.2环境下编写,在不同的系统上可能需要将"size_t"这样古怪的数据类型做相应的调整。

Friskit

继续阅读此作者的更多文章