Alex_McAvoy

想要成为渔夫的猎手

Matlab IO操作

【IO 操作】

IO 操作在不同层次有不同的概念和单位,每一次 IO 就是一次请求,对于磁盘来说,一个 IO 就是读或者写磁盘的某个或者某段扇区,读写完了,这个 IO 也就结束了

在 matlab 中,IO 操作即将数据从磁盘读入 matlab 的工作区,或将数据从 matlab 的工作区写入磁盘

【文件打开与关闭】

  • FID=fopen(fileName,permission):根据 fileName 所指定的路径,依照 permission 所指定的模式打开文件,返回文件标识符 FID
  • status=fclose(FID):关闭 FID 所映射的文件,并返回状态码 status

说明:

  1. FID:文件标识符,在系统(无论何种系统均有 FID,类似 PID)中用于唯一标识文件,需要注意的是,如果 FID 不代表打开文件或其等于 0(标准输入)、1(标准输出)、2(标准错误),关闭文件时会引发错误
  2. fileName:可以是相对路径,也可以是绝对路径
  3. permission 的模式如下表:
标识 模式 标识 模式
‘r’ 读文件,要求文件必须存在 ‘r+’ 读写文件,要求文件必须存在
‘w’ 写文件,若文件已存在会将内容覆盖,若文件不存在会创建文件 ‘w+’ 读写文件,若文件已存在会将内容覆盖,若文件不存在会创建文件
‘a’ 写文件,若文件已存在会将内容追加,若文件不存在会创建文件 ‘a+’ 读写文件,若文件已存在会将内容追加,若文件不存在会创建文件
‘b’ 表明打开文件为二进制文件,一般与上述 6 种标识混合使用,例如:’rb’、’ab+’
  1. status:关闭文件的状态码,关闭成功返回 0,关闭失败返回 1
1
2
3
4
>> fid=fopen('test.txt','r')
fid = 4
>> status=fclose(fid)
status = 0

【fread 与 fwrite】

fread()fwrite() 函数对二进制文件进行读写

  • a = fread(FID,num,precision):根据 FID 读取文件信息,用 precision 指定的数据格式,用 num 指定读取个数

  • num=fwrite(FID,data,precision):根据 FID 写入数据 data,用 precision 指定的数据格式,返回写入数据个数

注:

  1. 关于 precision:其数据格式为 int32float 等,若未指定,默认为 uint8
  2. 关于 num:在 fread()中,若 num 未指定,默认读取所有元素
  3. 无法利用 fread 和 fwrite 同时读写
  4. 由于 fread 和 fwrite 涉及到二进制编码问题,因此很少使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>> fid=fopen('test.bin','r+');
>> a=magic(3);
>> num=fwrite(fid,a,'int32')
num = 9
>> fclose(fid);

>> fid=fopen('test.bin','r+');
>> data=fread(fid,'int32');
>> fclose(fid);
>> data
data =
8
3
4
1
5
9
6
7
2

【fscanf 与 fprintf】

fscanf()fprintf() 函数对文本文件进行读写

  • data=fscanf(FID,formatSpec,num):根据 FID 读取文件信息,用 formatSpec 指定的数据格式,num 表示读取个数,inf 表示读取到末尾(默认)
  • num=fprintf(FID,formatSpec,data):根据 FID 写入文件信息,用 formatSpec 指定的数据格式

注:每次读写完数据后,指针句柄会指向接下来要读数据的位置

1
2
3
4
5
6
7
8
9
10
11
12
>> fid=fopen('test.txt','r+');
>> a=magic(3);
>> num=fprintf(fid,'%d %d %d\n',a);
>> fclose(fid);

>> fid=fopen('test.txt','r+');
>> data=fscanf(fid,'%d %d %d\n',[3,inf])
data =
8 1 6
3 5 7
4 9 2
>> fclose(fid);

【importdata 与 load】

importdata()load() 用于将文件加载到工作区,一般来说,对于文本数据(.txt),利用 importdata() 加载,对于 matlab 标准数据(.mat),利用 load() 加载

  • a=importdata(fileName,delimiter,num):加载 fileName 指定的文件,delimiter 为分隔符,num 为跳过的标题行数
  • load(fileName):将 mat 文件中的变量加载到工作区

注:可以利用 whos -file fileName.mat 来查看 mat 文件中的内容,使用该命令时不需将文件利用 load 载入,只要 mat 文件处于检测目录中即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>> importdata('test.txt',' ')
ans =
data: [3x3 double]
textdata: {'dwd' 'qwq' 'qaq'}
colheaders: {'dwd' 'qwq' 'qaq'}

>> importdata('test.txt',' ',2)
ans =
data: [2x3 double]
textdata: {2x3 cell}
colheaders: {'8' '3' '4'}

>> whos -file bird_small.mat
Name Size Bytes Class Attributes
A 128x128x3 393216 double

【textscan 与 textread】

matlab 中,一般利用 textscan()textread() 来读取格式化文本文件

  • a=textscan(FID,formatSpec):按照 formatSpec 格式读取 FID 所标识的文件,按列返回到元胞数组
  • a=textscan(FID,formatSpec,'headerlines',num):按照 formatSpec 格式读取 FID 所标识的文件,读取过程中跳过第 num 行,按列返回到元胞数组
  • a=textscan(FID,formatSpec,n):按照 formatSpec 格式读取 n 次 FID 所标识的文件,按列返回到元胞数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
>> fid=fopen('test.txt');
>> a=textscan(fid,'%s %s');
>> fclose(fid)

>> fid=fopen('test.txt');
>> b=textscan(fid,'%d %f','headerlines',1);
>> fclose(fid)

>> fileId=fopen('test.txt');
>> c=textscan(fid,'%d %d',1,'headerlines',1);
>> fclose(fid)

>> a{1}
ans =
'asd'
'1'
'5'
>> b{1}
ans =
1
5
>> b{2}
ans =
3.4000
3.5000
>> c{1}
ans =
1
>> c{2}
ans =
3
  • [A,B,C...]=textread(filename,formatSpec):按照 formatSpec 格式读取 filename 所标识的文件,按列返回到向量
  • [A,B,C...]=textread(filename,formatSpec,'headerlines',num):按照 formatSpec 格式读取 filename 所标识的文件,读取过程中跳过第 num 行,按列返回到向量
  • [A,B,C...]=textread(filename,formatSpec,n):按照 formatSpec 格式读取 n 次 filename 所标识的文件,按列返回到向量
1
2
3
4
5
6
7
8
9
10
11
>> [a,b]=textread('test.txt','%s %s');
>> a
a =
'asd'
'1'
'5'
>> b
b =
'qwe'
'3.4'
'3.5'

注:

  1. 对于 a=textscan(FID,formatSpec,n)[A,B,C...]=textread(filename,formatSpec,n),其一般用于每 n 行格式相同的数据
  2. textscan() 将多组数据读到一个元胞矩阵中;textread() 将数据分别读取到不同的向量中
  3. textscan() 使用前要先 fopen(),完成后要 fclose()textread() 不需 fopen()fclose(),适用于格式统一的 txt 的一次性大批量读取
  4. textscan() 每次读完数据后,指针句柄会指向接下来要读数据的位置;textread() 每次读完数据后,指针句柄会返回文件头
  5. 不推荐使用 textread()

【xlsread 与 csvread】

xlsread 用于读取 xls 文件

  • a=xlsread(fileName):读取 xls 文件中的所有单元格的数据

  • a=xlsread(fileName,-1):读取 xls 文件中的单元格的数据,用户可以利用鼠标来选定范围。执行后,会后台打开 xls 文件并弹窗,在 xls 文件中用鼠标选定单元格后,点击弹窗的确认即可

  • a=xlsread(fileName,sheet):读取 xls 文件中所在的 sheet,例如:’sheet1’
  • a=xlsread(fileName,range):读取 xls 文件中的单元格范围,例如:’A1:B2’
  • a=xlsread(fileName,sheet,range):读取 xls 文件中所在的 sheet 与 范围

csvread 用于读取 csv 文件

  • a=csvread(fileName):读取 csv 文件中的所有数据
  • a=csvread(fileName,R,C):从 csv 文件中的行偏移 R 和列偏移 C 开始读取数据
  • a=csvread(fileName,R1,C1,R2,C2):读取从 csv 文件中的行偏移 R1、列偏移 C1 和 行偏移 R2、列偏移 C2 范围内的数据

注:当需要写 xls 文件或写 csv 文件时,利用 xlswrite()csvwrite() 即可,使用方法与上述基本相同

【dlmread】

dlmread() 用于将 ASCII 分隔的数值数据文件读取到矩阵中,一般用于读取 tsv 文件

  • dlmread(fileName):将文件中重复的空白视为分隔符进行读取
  • dlmread(fileName,'delimiter'):使用指定的分隔符 delimiter 读取数据,同时会将重复的分隔符视为单独的分隔符
  • dlmread(fileName,delimiter,R,C):使用指定的分隔符 delimiter 从行偏移 R 和列偏移 C 开始读取数据读取数据
  • dlmread(fileName,delimiter,R1,C1,R2,C2):使用指定的分隔符 delimiter 读取行偏移 R1、列偏移 C1 和 行偏移 R2、列偏移 C2 范围内的数据

注:当需要写 ASCII 分隔的文件时,利用 dlmwrite() ,使用方法与上述基本相同

【文件读写句柄控制】

在大多数 I/O 函数中,读写完毕后,指针都会指向接下来要读文件的位置,这就造成了无法连续的读写数据,因此可以利用以下几个函数来控制句柄,从而实现自主控制文件读写

  • st=feof(FID):如果文件设置了文件结束指示符且已到达,则返回 1;如果未设置文件标识符,则返回 0
  • frewind(FID):将文件指针位置重定向至开头
  • pos=ftell(FID):返回文件指针位置,以字节为单位从头开始计算,若返回 -1 表示查询失败
  • status=fseek(FID,offset,origin):重新定位文件指针位置,定位成功返回 1,定位失败返回 -1
    • origin >= 0:在 origin 后移动指针 offset 个字节
    • origin <0:在 origin 前移动指针 offset 个字节

注:

  1. 关于文件结束符 EOF:End of File,是程序中判断 I/O 结尾的标志,其值为 1
  2. origin 常见取值解释为:
    1. bof 或 -1:文件开头
    2. cof 或 0:文件当前位置
    3. eof 或 1:文件结尾
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
>> fid=fopen('test.txt','r+');
>> data=fscanf(fid,'%d %d %d\n',[3,inf])
data =
8 1 6
3 5 7
4 9 2

>> data=fscanf(fid,'%d %d %d\n',[3,inf])
data = []
>> feof(fid)
ans = 1

>> frewind(fid)
>> data=fscanf(fid,'%d %d %d\n',[3,inf])
data =
8 1 6
3 5 7
4 9 2

>> ftell(fid)
ans = 18
>> frewind(fid)
>> ftell(fid)
ans = 0

>> data=fscanf(fid,'%d %d %d\n',[1,3])
data =
8 3 4
>> ftell(fid)
ans = 6


>> fclose(fid);
>> fseek(fid,6,0);
>> data=fscanf(fid,'%d %d %d\n')
data =
6
7
2
感谢您对我的支持,让我继续努力分享有用的技术与知识点!