通过低级 I/O 导入二进制数据
用于导入数据的低级函数
通过低级文件 I/O 函数,可以最大程度地直接控制对文件数据的读取和写入。但是,相对于更易于使用的高级函数,这些低级函数要求指定更为详细的文件信息。有关高级函数及其支持的文件格式的完整列表,请参阅支持的导入和导出的文件格式。
如果高级函数无法导入数据,请使用下列函数之一:
fscanf
,读取文本或 ASCII 文件(即可以在文本编辑器中查看的文件)中的格式化数据。有关详细信息,请参阅读取格式化模式的数据。fgetl
和fgets
,一次读取文件中的一行,其中每一行通过换行符分隔。有关详细信息,请参阅逐行读取数据。fread
,读取从相应字节或位级开始的数据流。有关详细信息,请参阅 读取文件中的二进制数据。
注意
低级文件 I/O 函数基于 ANSI® 标准 C 库中的函数。但是,MATLAB® 包括向量化版本的函数,通过最少的控制循环在数组中读取和写入数据。
读取文件中的二进制数据
与任何低级 I/O 函数一样,在导入前,使用 fopen
打开文件,并获取文件标识符。处理完文件后,使用 fclose
(
关闭文件。fileID
)
默认情况下,fread
每次读取文件的 1 个字节,并将每个字节解释为一个 8 位无符号整数 (uint8
)。fread
创建一个列向量,文件中每个字节对应一个元素。列向量中的值属于 double
类。
例如,按以下方式创建文件 nine.bin
:
fid = fopen('nine.bin','w'); fwrite(fid, [1:9]); fclose(fid);
要将该文件中的所有数据读取到一个 double
类的 9×1 列向量中:
fid = fopen('nine.bin'); col9 = fread(fid); fclose(fid);
更改数组的维度
默认情况下,fread
将文件中的所有值读取到一个列向量中。但是,您可以指定要读取的值的数量,或者描述一个二维输出矩阵。
例如,要读取前面示例中所述的 nine.bin
:
fid = fopen('nine.bin'); % Read only the first six values col6 = fread(fid, 6); % Return to the beginning of the file frewind(fid); % Read first four values into a 2-by-2 matrix frewind(fid); two_dim4 = fread(fid, [2, 2]); % Read into a matrix with 3 rows and % unspecified number of columns frewind(fid); two_dim9 = fread(fid, [3, inf]); % Close the file fclose(fid);
描述输入值
如果文件中的值不是 8 位无符号整数,则需指定值的大小。
例如,使用以下双精度值创建文件 fpoint.bin
:
myvals = [pi, 42, 1/3]; fid = fopen('fpoint.bin','w'); fwrite(fid, myvals, 'double'); fclose(fid);
读取文件:
fid = fopen('fpoint.bin'); % read, and transpose so samevals = myvals samevals = fread(fid, 'double')'; fclose(fid);
有关精度描述的完整列表,请参阅 fread
函数参考页。
节省内存
默认情况下,fread
创建一个 double
类的数组。在数组中存储双精度值比存储字符、整数或单精度值需要更多的内存。
要减少存储数据所需的内存量,请使用以下方法之一指定数组的类:
用星号 (
'*'
) 匹配输入值的类。例如,要将单精度值读入一个single
类的数组,请使用命令:mydata = fread(fid,'*single')
用
'=>'
符号将输入值映射到一个新类。例如,要将uint8
值读入一个uint16
数组,请使用命令:mydata = fread(fid,'uint8=>uint16')
有关精度描述的完整列表,请参阅 fread
函数参考页。
读取文件的一部分
MATLAB 低级函数包括几个用于读取文件中二进制数据部分的选项:
移动到文件中的特定位置以开始读取。有关详细信息,请参阅在文件中移动。
在每次读取元素后跳过一定数量的字节或位。有关示例,请参阅Write and Read Complex Numbers。
检测文件末尾
打开文件时,MATLAB 创建一个指针,指示文件中的当前位置。
注意
打开一个空文件不会将文件位置指示符移到文件末尾。读取操作以及 fseek
和 frewind
函数可移动文件位置指示符。
使用 feof
函数检查是否已到达文件的末尾。当文件指针在文件的末尾时,feof
返回值 1
。否则,将返回 0
。
例如,分几部分来读取大文件:
filename = 'largedata.dat'; % hypothetical file segsize = 10000; fid = fopen(filename); while ~feof(fid) currData = fread(fid, segsize); if ~isempty(currData) disp('Current Data:'); disp(currData); end end fclose(fid);
在文件中移动
要读取或写入数据的所选部分,请将文件位置指示符移动到文件中的任意位置。例如,使用以下语法调用 fseek
fseek(fid,offset,origin);
其中:
fid
是从fopen
获取的文件标识符。offset
是一个以字节指定的正或负偏移值。origin
指定定位所采用的基本位置:'bof'
文件的开头
'cof'
文件中的当前位置
'eof'
文件的结尾
或者,要轻松移至文件的开头:
frewind(fid);
使用 ftell
查找在给定文件中的当前位置。ftell
返回从文件开头算起的字节数。
例如,创建文件 five.bin
:
A = 1:5; fid = fopen('five.bin','w'); fwrite(fid, A,'short'); fclose(fid);
因为调用 fwrite
会指定 short
格式,所以 A
的每个元素在 five.bin
中使用两个存储字节。
重新打开 five.bin
以便于读取:
fid = fopen('five.bin','r');
将文件位置指示符从文件开头向前移动 6 个字节:
status = fseek(fid,6,'bof');
读取下一个元素:
four = fread(fid,1,'short');
读取操作使文件位置指示符前进。要确定当前文件位置指示符,请调用 ftell:
position = ftell(fid) position = 8
要将文件位置指示符向后移动 4 个字节,请再次调用 fseek
:
status = fseek(fid,-4,'cof');
读取下一个值:
three = fread(fid,1,'short');
读取在其他系统上创建的文件
不同的操作系统在字节级别或位级别以不同的方式存储信息:
Big-endian 系统从内存中的最大地址开始存储字节(即以大端开头)。
Little-endian 系统从最小地址(小端)开始存储字节。
Windows® 系统使用 little-endian 字节顺序,而 UNIX® 系统使用 big-endian 字节顺序。
要读取在相反字节序系统上创建的文件,请指定用于创建该文件的字节顺序。您可以在打开文件的调用中指定顺序,也可以在读取文件的调用中指定顺序。
例如,假设在 little-endian 系统上创建了一个名为 little.bin
的双精度值文件。要在 big-endian 系统上读取此文件,请使用以下命令之一(或两者):
打开文件
fid = fopen('little.bin', 'r', 'l')
读取文件
mydata = fread(fid, 'double', 'l')
其中 'l'
表示 little-endian 顺序。
如果不确定系统使用哪种字节顺序,请调用 computer
函数:
[cinfo, maxsize, ordering] = computer
ordering
为 'L'
表示 little-endian 系统,为 'B'
表示 big-endian 系统。