通过低级 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 系统。