第9章 文件I/O

    MATLAB系统具有直接对磁盘文件进行访问的功能,用户不仅可进行高层的程序设计,必要时还可进行低层次磁盘文件的读写操作,增强了MATLAB程序设计的灵活性。

    MATLAB内建有很多有关文件输入和输出的函数,使用者可以很方便地对二进制文件或ASCII文件进行打开、关闭和存储等操作。这些函数是基于C语言的文件I/O函数的,简单易学。

    9.1 打开和关闭文件

    9.1.1 打开文件

    根据操作系统的要求,在程序要使用或者创建一个磁盘文件时,必须向操作系统发出打开文件的命令,使用完毕后,还必须通知操作系统关闭这些文件。

    在MATLAB中,使用C语言中的同名函数fopen来完成这一功能,其语法为:

    alt

    其中filename是要打开的文件名称,permission则表示要对文件进行处理的方式。可以是下列任一字符串:

    · 'r':只读文件(reading);

    · 'w':只写文件,覆盖文件原有内容(如果文件名不存在,则生成新文件,writing);

    · 'a':增补文件,在文件尾增加数据(如果文件名不存在,则生成新文件,appending);

    · 'r+':读写文件(不生成文件,reading and writing);

    · 'w+':创建一个新文件或者删除已有文件内容,并可进行读写操作;

    · 'a+':读取和增补文件(如果文件名不存在,则生成新文件)。

    文件可以以二进制的形式或者文本形式打开(默认情况下是前者),在二进制形式下,字符串不会被特殊对待。如果要求以文本形式打开,则在permission字符串后面加't',例如'rt+','wt+'等。需要说明的是在UNIX下,文本形式和二进制形式没有什么区别。

    fid是一个非负整数,称为文件标识,对于文件的任何操作,都是通过这个标识值来传递的,MATLAB通过这个值来标识已打开的文件,实现对文件的读、写和关闭等操作。正常情况下应该返回一个非负的整数,这个值是由操作系统设定的。如果返回的文件标识为'-i',则表示fopen无法打开该文件,原因可能是该文件不存在,而以'r'或'r+'方式打开,也可能是用户无权限打开此文件。程序设计中,每次打开文件,都要进行打开操作是否正确的测定。如果要知道fopen操作失败的原因,可以使用下列方式调用:

    alt

    输出变量message中包含了文件打开操作结果的信息,示例代码设置如下:

    alt

    运行后在命令行显示为:

    alt

    如果是打开一个存在的文件,示例代码设置如下:

    alt

    运行后分别查看message和fid的值如下:

    alt

    文件标识fid=1和fid=2是自动获取的,不必打开。如果要获取所有已打开的文件标识值,可用以下命令:

    alt

    注意,查看错误信息时,也可用MATLAB的函数ferror,其函数格式如下:

    alt

    9.1.2 关闭文件

    在进行完读写操作后,必须关闭文件,以免打开文件过多,造成系统资源浪费,命令为:

    alt

    如果关闭成功,则返回status值为0;否则返回-1。

    上述命令是关闭了文件标识为fid的文件,如果要一次关闭所有打开的文件,则需执行下面的代码:

    alt

    用户可以通过检查status的值来确认文件是否关闭。

    在某些情况下,可能需要用到暂存目录及临时文件,要取用系统的暂存目录,可用tempdir命令:

    alt

    要打开一个临时文件,可用tempname命令:

    alt


    注意:打开和关闭文件的操作都比较费时,尽量不要将它们置于循环中,以提高程序执行的效率。


    9.2 读取二进制文件

    MATLAB中函数fread可以从文件中读取二进制数据,将每一个字节看成一个整数,将结果写入一个矩阵返回。最基本的调用形式为:

    alt

    其中,fid是从fopen中得来的文件标识。MATLAB读取整个文件并将文件指针放在文件末尾处(在后面的feof命令介绍中有详细解释)。

    例如,文件t b.m内容如下:

    alt

    用fread函数读取此文件,操作如下:

    alt

    如要验证,可输入如下代码:

    alt

    如果不用char将data转换为ASCII字符,则输出的是一组整数,取data的转置是为了方便阅读。

    函数fread返回矩阵的大小和形式是可控的,通过fread的第2个输入变量来实现:

    alt

    size的有效输入大体可分为3种:

    · n:读取前n个整数,并写入一个列向量中;

    · inf:读至文件末尾;

    · [m,n]:读取数据到m×n的矩阵中,按列排序,n可以是inf,m不可以。

    例如,对t b.m文件进行操作,示例代码设置如下:

    alt

    其中,后一个fread命令读取的数据是紧接第一个fread的。

    fread命令还有第3个输入变量,用来控制二进制数据转换成MATLAB矩阵时所用的精度,命令格式为:

    alt

    precision包括两部分:一是数据类型定义,比如int、float等;二是一次读取的位数。默认情况下是uchar(8位字符型),常用的精度在表9-1中有简单的介绍,并且与C和Fortran中相当的形式做了对比。

    表9-1    精度类型

    alt

    还有一些类型是与平台有关的,平台不同可能位数不同,如表9-2所示。

    表9-2    与平台有关的精度类型

    alt

    如果fid表示的是已打开的浮点类型的数据文件,则得到下面的代码:

    alt

    将读入前10个浮点型数据到列向量a中。


    注意:fread还有两个输入参数,即skip和machineformat,均不常用,其用法可参考MATLAB中fread的help文件。


    9.3 写入二进制文件

    函数fwrite的作用是将一个矩阵的元素按所定的二进制格式写入某个打开的文件,并返回成功写入的数据个数。格式为:

    alt

    其中,fid是从fopen得到的文件标识,a是待写入的矩阵,precision设定了结果的精度,可用的精度类型见fread中的叙述。示例代码设置如下:

    alt

    上面的程序段的执行结果是生成一个文件名为tob.bin的二进制文件,长度为100字节,包含5×5个数据,即5阶方阵的数据,每个数据占用4个字节的存储单位,数据类型为整型,输出变量count值为25。由于是二进制文件,所以无法用type命令来显示文件内容,如果要查看,可用以下命令:

    alt

    9.4 读取文本文件

    如果需要将文本文件中的某一行读出,并将该行的内容以字符串形式返回,可采用以下两个命令:

    alt

    两个函数的功能很相似,均可从文件中读取一行数据,区别在于fgetl会舍弃换行符,而fgets则保留换行符。示例代码设置如下:

    alt

    命令执行结果为:

    alt

    alt

    alt

    若已知ASCII文件的格式,要进行更精确的读取,可用fscanf函数从文件中读取格式化的数据,其使用语法如下:

    alt

    此命令从文件标识为fid的文件中读取数据,并转换成指定的format格式字符串,返回到矩阵a中。count是可选输出项,表示成功读取的数据个数。size是可选输入项,它对可以从文件读取的数据数目做了限制,如果没有指定,则默认为整个文件,否则可以指定为3种类型:n,inf,[m,n]。各项的意义同9.2节中的描述。

    format用于指定读入数据的类型,常用的格式有:

    · %s:按字符串进行输入转换;

    · %d:按十进制数据进行转换;

    · %f:按浮点数进行转换。

    另外还有其他的格式,它们与C语言中的fprintf中参数的用法是相同的,可以参阅C手册。

    在格式说明中,除了单个的空格字符可以匹配任意个数的空格字符外,通常的字符在输入转换时将与输入的字符一一匹配,函数fscanf将输入的文件看作是一个输入流,MATLAB根据格式来匹配输入流,并将在流中匹配的数据读入到MATLAB系统中。下面是一个文件输入的例子:

    alt

    读取的数据解释为字符串,结果为:

    alt

    用type命令读取table.txt文件内容为:

    alt

    如果以双精度格式来读取的话,则程序和结果为:

    alt

    上例显示了MATLAB的fscanf函数和C中fscanf函数的不同之处。MATLAB的fscanf函数是向量化的,只要读入数据的类型正确,MATLAB的fscanf函数会一再执行,并把所得结果以向量形式返回。

    如果要对返回向量的形式和大小进行限制,可以加入size输入变量。示例代码设置如下:

    alt


    注意:(1)fscanf在读取文件时,是逐行进行的,在返回矩阵时,是将数据逐列写入的。(2)本节所介绍的命令不能对二进制文件进行操作。(3)sscanf函数和fscanf函数的功能类似,不同的是sscanf是从字符串中读取数据,而不是对文件的操作。


    9.5 写入文本文件

    MATLAB的函数fprintf的作用是将数据转换成指定格式字符串,写入到文本文件中。其语法格式为:

    alt

    其中fid是要写入的文件标识,由fopen产生,format是格式指定字符串,用以指定数据写至文件的格式,y是MATLAB的数据变量。count是返回的成功写入的字节数。

    fid值也可以是代表标准输出的1和代表标准出错的2,如果fid字段省略,则默认值为1,输出到屏幕上。常用的格式类型说明符如下:

    · %e:科学计数形式,即数值表示成a×10b形式;

    · %f:固定小数点位置的数据形式;

    · %g:在上述两种格式中自动选取较短的格式。

    可以用一些特殊格式比如\n、\r、\t、\b、\f等来产生换行、回车、tab、退格、走纸等字符,用\来产生反斜线符号\,用%%来产生百分号。此外还可以包括数据占用的最小宽度和数据精度的说明。举例说明此命令的用法:

    alt

    运行后将s_table.dat打印出来,可得如下代码:

    alt

    在本例中,第一条fprintf语句输出一行标题,随后换行,第二条fprintf语句输出函数值表,每组自变量和函数占一行,都是固定小数点位置的形式。自变量值占2个字符位,不带小数;函数值占6个字符位,小数点后的精度是4个字符位,自变量和函数值之间空两格。

    矩阵y的元素按列的顺序转换成格式化的输出,函数反复使用格式说明,直至将矩阵的数据转换完毕。


    注意:sprintf函数与fprintf函数功能类似,但是sprintf将数据以字符串形式返回,而不是直接写入文件。


    9.6 文件内的位置控制

    根据操作系统的规定,在读写数据时,缺省的方式总是从磁盘文件的开始顺序向后的在磁盘空间上读写数据。操作系统通过一个文件指针,来指示当前的文件位置。C或Fortran语言都有专门的函数来控制和移动文件指针,达到随机访问磁盘文件的目的。MATLAB中也有类似的函数,如表9-3所示。

    表9-3    控制文件内位置指针的函数

    alt

    · feof

    feof用于测试指针是否在文件结束位置,其语法格式为:

    alt

    如果文件标识为fid的文件的末尾指示值被置位,则此命令返回1,说明指针在文件末尾,否则返回0。

    · fseek

    fseek用于设定指针位置,其语法格式为:

    alt

    其中fid是文件标识;offset是偏移量,以字节为单位,可以是整数(表示要往文件末尾方向移动指针)、0(不移动指针位置)或负数(表示往文件起始方向移动指针);origin是基准点,可以是'bof'(文件的起始位置)、'cof'(指针的目前位置)、'eof'(文件的末尾),也可以用-1、0或1来表示。

    如果返回值status为0表示操作成功,返回-1表示操作失败,如果要了解更多信息可以调用ferror函数。

    · ftell

    ftell用于返回现在的位置指针,其语法格式为:

    alt

    返回值position是距离文件起始位置的字节数,如果返回-1则说明操作失败。

    · frewind

    frewind用于将指针返回到文件开始,语法格式为:

    alt

    下面通过一个例子来介绍这几个命令的使用方法,示例代码如下:

    alt

    运行后,检查six、eof、status和position的值:

    alt