Main Content

本页的翻译已过时。点击此处可查看最新英文版本。

通过低级 I/O 导入二进制数据

用于导入数据的低级函数

通过低级文件 I/O 函数,可以最大程度地直接控制对文件数据的读取和写入。但是,相对于更易于使用的高级函数,这些低级函数要求指定更为详细的文件信息。有关高级函数及其支持的文件格式的完整列表,请参阅支持的导入和导出文件格式

如果高级函数无法导入数据,请使用下列函数之一:

  • fscanf,读取文本或 ASCII 文件(即可以在文本编辑器中查看的文件)中的格式化数据。有关详细信息,请参阅读取格式化模式的数据

  • fgetlfgets,一次读取文件中的一行,其中每一行通过换行符分隔。有关详细信息,请参阅逐行读取数据

  • 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 低级函数包括几个用于读取文件中二进制数据部分的选项:

检测文件末尾

打开文件时,MATLAB 创建一个指针,指示文件中的当前位置。

注意

打开一个空文件不会将文件位置指示符移到文件末尾。读取操作以及 fseekfrewind 函数可移动文件位置指示符。

使用 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 系统。