二进制数据的读取
(2010-03-21 16:10:48)
标签:
杂谈 |
2.3 二进制数据
2.3.1 二进制数据的读取
本小节将介绍怎样将一般格式下的二进制数据文件读取到工作空间中。读取二进制数据常用的方法有两种,一是使用导入模板来导入,二是使用二进制数据导入函数来读取。
1. 使用导入模板读取二进制数据
要使用导入模板来读取二进制数据,需按以下步骤进行:
(1) 选择File→Import Data选项,弹出一个文件选择对话框;也可以使用uiimport函数来打开导入数据模板。
(2) 在文件选择对话框中选择想导入数据的二进制数据文件,然后单击Open按钮,导入数据模板就会打开该文件并准备处理其内容。
(3) 选择要导入的变量。在默认情况下,导入模板将要建立的变量取决于文件中的数据类型。
(4) 单击Finish按钮完成数据的导入。
这个过程和使用导入模板读取文本文件是基本一致的,这里就不再举例了。
2. 使用导入函数读取二进制数据
若要从命令行或一个 M 文件中读取二进制数据,就必须使用 MATLAB 导入函数,函数的选择取决于文件中数据的格式,这些函数如表2-4所示。
表2-4
函 数 名 称 |
读取文件的扩展名 |
数 据 格 式 |
load |
.mat |
读取MATLAB下的MAT数据格式的数据 |
aviread |
.avi |
读取AVI格式的音频视频数据 |
cdfread |
.cdf |
读取CDF格式的数据 |
hdf |
.hdf |
读取HDF格式的数据 |
imread |
.bmp .jpg .ppm |
读取各种格式的图形数据 |
wavread |
.wav |
读取 Windows 系统的声音文件 |
xlsread |
.xls |
读取 Excel 电子表格数据 |
2.3.2 二进制数据的存写
要以一种标准二进制格式来存写二进制数据,可以使用 MATLAB 提供的高端函数,函数的选择取决于要存写数据的类型,这些函数如表2-5所示。
表2-5
函 数 名 称 |
读取文件的扩展名 |
数 据 格 式 |
save |
.mat |
存写MATLAB下的MAT数据格式的数据 |
avifile |
.avi |
存写AVI格式的音频视频数据 |
cdfwrite |
.cdf |
存写CDF格式的数据 |
hdf |
.hdf |
存写HDF格式的数据 |
imwrite |
.bmp .jpg .ppm |
存写各种格式的图形数据 |
wavwrite |
.wav |
存写 Windows 系统的声音文件 |
xlswrite |
.xls |
存写 Excel 电子表格数据 |
在MATLAB中可以将一系列的图像保存为电影,这样使用电影播放函数就可以进行回放,保存方法可以同保存其他MATLAB工作空间变量一样,通过采用MAT文件格式保存。但是若要浏览该电影,必须在MATLAB环境下。在以某种格式存写一系列的MATLAB图像时,不需要在MATLBA 环境下进行预览,通常采用的格式为AVI格式。AVI是一种文件格式,在PC 机上的Windows系统或UNIX操作系统下可以进行动画或视频的播放。
若要以AVI格式来存写MATLAB图像,步骤如下:
(1) 用avifile函数建立一个AVI文件。
(2) 用addframe函数来捕捉图像并保存到AVI 文件中。
(3) 使用close函数关闭AVI文件。
注意:
若要将一个已经存在的MATLAB电影文件转换为AVI文件,需使用函数movie2avi。函数原型为:
movie2avi(mov,filename)
movie2avi(mov,filename,param,value,param,value…)
2.4 使用文件I/O函数
前面介绍的都是MATLAB中的一些高级函数,除此之外MATLAB还包含了一组低端的文件I/O函数,如前面介绍的所有文件的打开和关闭函数:fopen函数和fclose函数。这些函数是建立在ANSI标准C库中的I/O函数。若用户对C语言熟悉的话,那么也肯定熟悉这些函数。比如,MATLAB 文件I/O函数使用和C语言同样的编程模式等。要读写这些数据,需进行以下几步:
(1) 使用fopen函数打开文件。fopen函数将会返回一个文件标志,通过它,就可以使用其他所有的低端文件I/O函数。
(2) 对文件进行操作,如:读写二进制数据、格式化读写文本数据等。
(3) 使用fclose函数来关闭文件。
2.4.1 二进制数据的读取
使用fread函数可从文件中读取二进制数据,它将每个字节看成整数,并将结果以矩阵形式返回。对于读取二进制文件,fread必须制定正确的数据精度。
fread的基本调用方法是:
A=fread(fid)
其中fid是一个整数型变量,是通过调用fopen函数获得的,表示要读取的文件标识符,输出变量A为矩阵,用于保存从文件中读取的数据。
例如文件test.txt的内容如下:
test it
用fread函数读取该文件,输入如下命令:
>> f=fopen('test.txt','r');
>> answer=fread(f)
answer =
输出变量的内容是文件数据的ASCII码值,若要验证读入的数据是否正确,通过下面的命令可以验证。
>> disp(char(ans1'))
test it
fread函数的第二个输入参数可以控制返回矩阵的大小,例如:
>> f=fopen('test.txt','r');
>> answer=fread(f,2)
answer =
也可以把返回矩阵定义为指定的矩阵格式,例如
>> f=fopen('test.txt','r');
>> an=fread(f,[2 3])
answer =
使用fread函数的第三个输入变量,可以控制fread将二进制数据转成MATLAB 矩阵用的精度,包括一次读取的位数(Number of Bits)和这些位数所代表的数据类型。
常用的精确度类型有下列几种,如表2-6所示。
表2-6
数 据 类 型 |
说 |
char |
带符号的字符(通常是8h16) |
uchar |
无符号的字符(通常是8bits) |
short |
短整数(通常是16bits) |
long |
长整数(通常是16bits) |
float |
单精度浮点数(通常是32bits) |
double |
双精度浮点数(通常是64bis) |
2.4.2 二进制数据的写入
使用fwrite函数可将矩阵按所指定的二进制格式写入文件,并返回成功写入文件的大小。函数的调用方式如下:
count=fwrite(fid,A,precision)
其中,count用来返回写入文件数据的大小,f参数同样是通过fopen函数获得的整数型变量,表示文件标识符,A表示要写入的数据矩阵,第三个参数precision同二进制读取函数的参数一样,表示数据的写入格式。
在下例中fwrite产生一个大小为100字节的二进制文件,它包含了一个5×5阶魔方矩阵,共25个元素,每个元素占用4个字节。
f=fopen('magic5.bin', 'w');
fwrite(f,magic(5), 'int32');
fclose(f)
二进制文件在不同的计算机架构上可能存储方式不同,所以二进制文件存在兼容性问题,而文本文件则不存在这种兼容性问题。不同的存储方式导致在不同架构上保存的二进制文件在另外的平台上无法读取,这主要是因为多字节数据类型在计算机硬件上的存储顺序不同。在MATLAB中,无论计算机上的数据存储顺序是哪一种,都可以读写二进制文件,但要正确地调用fopen函数打开文件。
2.4.3 格式化读取ASCII码数据
fscanf函数与C语言中的fscanf在结构、含义和使用上都很相似,即能够从一个有格式的文件中读入数据,并将它赋给一个或多个变量。两个函数都采用同一组格式指定符来控制输入数据的格式,fscanf的格式指定符由字符%开头,常用格式如表2-7所示。
表2-7
格式转换符 |
意 |
%c |
读取字符型变量,也可以指定多个字符,'%3c' |
%s |
读取字符串变量 |
%d |
读取整数型变量 |
%f |
读取浮点数 |
%g |
读取双精度浮点数 |
例如,我们仍然读取my_test.dat文件中的数据,其数据内容是:
通过下面这段代码,将该文件中的数据读取到列向量T中。
>> f=fopen('my_test.dat','r');
>> T=fscanf(f,'%g');
>> fclose(f)
也可以通过以下代码段把文件数据读取到一个3×2矩阵A中。
>> f=fopen('my_test.dat','r');
>> A=fscanf(f,'%g',[3 2]);
>> fclose(f)
执行后结果如下,这时候A矩阵恰好是文件中数据矩阵的转置。
>> A
A =
2.4.4 格式化写入文本数据
fprintf将会把数据转换为字符串,并将它们输出到屏幕或文件中。一个格式控制字符串包含转换指定符和可选的文本字符,通过它们来指定输出格式。转换指定符用于控制阵列元素的输出。
当fprint函数做标准输出,也就是运行结果显示在屏幕上的时候,它的功能和disp函数相类似,区别仅在于fprint可以输出特定格式的文本数据。
比如,创建一个2×2的魔方矩阵,然后打开一文件,写入数据。
>> clear all;
>> x=magic(2);
>> fid=fopen('exam4.txt','w');
>>
fprintf(fid,'%4.2f
>> fclose(fid);
执行这段程序段之后,我们可以检验一下执行结果:
>> x
x =
>> type exam4.txt
1.00
3.00
可以看出,fprintf函数在打印显示矩阵数据时,数据转换规则是可以按列方式循环作用于矩阵的各个元素的,这个例子中显示出来的结果就好像原矩阵的转置,而且分别按数据转换规则显示。
2.4.5 控制文件位置指针
每一次打开文件时,MATLAB就会保持一个文件位置指针(File Position Indicator),由它决定下一次进行数据读取或写入的位置。控制此指针的函数如表2-8所示。
表2-8
函 数 名 称 |
功 能 说 明 |
fseek |
设定指针位置 |
ftell |
获得指针位置 |
frewind |
重设指针到文件起始位置 |
feof |
测试指针是否在文件结束位置 |
fseek 函数用于指定文件指针的位置,调用方式如下:
status=fseek(fid,offset,origin)
fid是指定的文件标识符。offset为整数型变量,表示相对于指定位置需要的偏移字节数,正数表示向文件末尾偏移,负数表示向文件开头偏移。Origin可以是特定字符串,也可以是整数,表示文件中的参考位置。参考位置的参数说明如表2-9所示。
表2-9
参考位置(origin) |
说 |
'bof '或者 -1 |
文件开头 |
'cof '或者 0 |
文件中当前位置 |
'eof '或者 1 |
文件末尾 |
ftell 函数用来获得当前文件指针的位置,调用方式如下:
position=ftell(fid)
fid是指定的文件标识符。Position为返回值,表示当前指针的位置。position是以相对于文件开头的字节数来表示的。如果返回值为–1,表示未能成功调用。这是可以通过调用feeeor(fid)的具体的错误信息。
frewind 函数用来把文件指针重新复位到文件开头。调用方式如下:
frewind(fid)
其中fid为指定的文件标识符,其作用和fseek(fid,0,-1)是等效的。
feof 函数用来判断是否到达文件末尾。调用方式如下:
eofstat=feof(fid)
其中fid为指定的文件标识符。eofstat是返回值,当到达文件末尾时,eofstat为1;否则为0。比如我们仍然对文件my_test.dat执行以下命令,然后测试文件指针位置
>> f=fopen('my_test.dat','r');
>> A=fscanf(f,'%g',[3 2])
A =
>>feof(f)
ans=
在本例中,文件指针指向最后一个数据,而不是文件末尾,因此返回值是0,而不是1,但是若执行以下命令:
>> f=fopen('my_test.dat','r');
>> A=fscanf(f,'%g',[4 2])
A =
>>feof(f)
ans=
在my_data.dat文件中只包含6个数字,因此feof函数返回值为1。若要重新设置指针到起始位置,就可以直接使用frewind函数。
2.5 MAT 文件
MAT文件是MATLAB使用的一种特有的二进制数据文件。MAT文件可以包含一个或者多个MATLAB 变量。MATLAB通常采用MAT文件把工作空间的变量存储在磁盘里,在MAT文件中不仅保存各变量数据本身,而且同时保存变量名以及数据类型等。所以在MATLAB中载入某个MAT文件后,可以在当前MATLAB工作空间完全再现当初保存该MAT 文件时的那些变量。这是其他文件格式所不能的。同样,用户也可以使用MAT文件从MATLAB环境中导出数据。MAT文件提供了一种更简便的机制在不同操作平台之间移动MATLAB数据。
2.5.1 在MATLAB中读写MAT文件
在MATLAB环境中,通常使用load和save两个命令进行 MAT 文件的读和写。在默认情况下,这两个命令以 MAT 文件格式处理文件,但是也可以用–ascii参数选项来强制用文件方式处理文件。关于这点已经在本章介绍过了,这里主要介绍如何读写MAT文件。
1. load 函数的使用
load函数可以从MAT文件中读取数据,例如要读取mymat.dat文件,可以直接执行命令load mymat.dat,因为给出要读取的文件的后缀名是MAT,因此命令则以MAT文件格式读取数据,否则将以文本文件读取数据。命令中的文件名可以包含单引号,也可以不包含,也就是说该函数也可以这样调用:load 'mymat.mat' 。
load 函数还可以指定只读取文件中的某几个变量,只需在文件名之后列出想要读取的变量的变量名就可以了,变量名也可以使用通配符。
比如命令load mymat.mat y*,执行结果就是将文件中所有以y开头的变量读取出来。
load还有一种函数形式的调用方式。这种调用方式就要求文件名必须是字符串,比如要导入mymat.mat文件,那么函数形式的调用必须是s = load('mymat.mat')。
2. save函数的使用
save 函数的功能是把当前MATLAB工作空间的一个或多个变量存写到外部文件。在默认情况下,save 函数以MAT格式存写数据。若在命令中直接调用该函数,不带任何参数,执行结果是把MATLAB工作空间的所有变量保存到系统默认的matlab.mat文件中。当然,带上文件名参数,就可以将当前工作空间中的所有变量存写在指定的 MAT文件中。
如果用户需要保存指定的某几个变量,只需在文件名参数后,列出要保存的文件名即可。比如,命令save mymat.mat x,y,z执行后的结果就是将当前工作空间中的变量 x,y,z保存到mymat.mat文件中,要求x,y,z是当前工作空间中已经存在的变量。
2.5.2 在普通的C/C++程序中读写MAT文件
1.使用MATLAB 提供的MAT 文件接口函数
在C/C++程序中有两种方式可以读取MAT文件数据。一种是利用MATLAB提供的有关MAT文件的编程接口函数。MATLAB的库函数中包含了MAT文件接口函数库,其中有各种对MAT文件进行读写的函数,都是以mat开头的函数。如表2-10所示。
表2-10
MAT |
功 |
matOpen |
打开 MAT 文件 |
matClose |
关闭 MAT 文件 |
matGetDir |
从 MAT 文件中获得 MATLAB 阵列的列表 |
matGetFp |
获得一个指向MAT 文件的ANSI C 文件指针 |
matGetVariable |
从MAT文件中读取MATLAB阵列 |
matPutVariable |
写MATLAB阵列到MAT文件 |
matGetNextVariable |
从MAT文件中读取下一个MATLAB阵列 |
matDeleteVariable |
从MAT文件中删去下一个MATLAB阵列 |
matPutVariableAsGlobal |
从MATLAB阵列写入到MAT文件中 |
matGetVariableInfo |
从MAT文件中读取MATLAB阵列头信息 |
matGetNextVariableInfo |
从MAT文件中读取下一个MATLAB阵列头信息 |
2.在C/C++程序中读取MAT文件内容
另外一种在C/C++程序中读写 MAT 文件的方法是根据 MAT 文件结构,以二进制格式在C/C++中读入文件内容,然后解析文件内容,从而获得文件中保存的MATLAB数据。因为MAT文件格式是公开的,用户只要在找到安装路径下的一个名为matfile_format,pdf的文件,就可以详细了解 MAT 文件结构,从而在C/C++程序中以二进制格式读取文件内容,解析以后得到文件中保存的数据。具体方法在后面章节有详细讲解。