MATLAB文本文件读写实操fopen/fscanf/fprintf/fclose全解析

文章目录

文本文件读写是MATLAB数据处理的基础技能,不管是读取实验数据、导出计算结果,还是批量处理文本格式的日志文件,都离不开 fopen()fscanf()fprintf()fclose()这四个核心函数。本文从实际应用场景出发,详解每个函数的用法、参数含义和实战案例,新手也能快速掌握从"读文件"到"写文件"的完整流程。

一、核心函数基础认知

先理清四个核心函数的定位,避免混淆用法:

函数名 核心作用 关键特点
fopen() 打开文本文件 返回文件句柄(唯一标识),需判断是否打开成功
fscanf() 读取文本文件内容 按指定格式读取,支持批量读取、按行读取
fprintf() 写入内容到文本文件 支持格式化输出,可自定义文本格式(如数值、字符串)
fclose() 关闭打开的文件 必须执行,避免文件占用、数据丢失

前置知识点:文件打开模式

fopen()的第二个参数决定文件打开方式,新手必记常用模式:

  • 'r':只读(默认),文件不存在则报错
  • 'w':写入(覆盖原有内容),文件不存在则创建
  • 'a':追加(在文件末尾写入),文件不存在则创建
  • 'r+':读写,文件不存在则报错
  • 'w+':读写(覆盖原有内容),文件不存在则创建

二、fopen():打开文件的"第一步"

1. 基本语法

matlab 复制代码
fid = fopen(filename, mode);  % 核心用法
[fid, message] = fopen(filename, mode);  % 带错误信息返回(推荐)
  • fid:文件句柄(整数),成功打开时返回≥3的整数;失败时返回-1
  • filename:文件路径(字符串),如'data.txt'(当前目录)、'D:\test\log.txt'(绝对路径)
  • message:错误信息(文件打开失败时返回具体原因,如文件不存在、权限不足)

2. 实战示例:判断文件是否打开成功

matlab 复制代码
% 打开当前目录下的data.txt,只读模式
[fid, msg] = fopen('data.txt', 'r');
if fid == -1  % 打开失败
    disp(['文件打开失败:', msg]);  % 输出错误原因
else  % 打开成功
    disp(['文件打开成功,句柄:', num2str(fid)]);
end

关键提醒 :打开文件后必须先判断fid是否为-1,避免后续读写操作报错。

三、fscanf():读取文本文件内容

1. 基本语法

matlab 复制代码
% 格式1:按指定格式读取全部内容
data = fscanf(fid, format);
% 格式2:指定读取数量(如读取N个数据)
[data, count] = fscanf(fid, format, size);
  • format:读取格式(核心),常用'%d'(整数)、'%f'(浮点数)、'%s'(字符串)、'%c'(字符)
  • size:读取数量,如[m,n](读取m行n列)、Inf(读取全部内容)
  • count:实际读取的元素个数(可选)

2. 场景1:读取纯数值文本文件

目标文件(data.txt)内容:

复制代码
10 20 30
40 50 60
70 80 90

读取代码

matlab 复制代码
% 打开文件
[fid, msg] = fopen('data.txt', 'r');
if fid == -1
    disp(msg);
    return;  % 打开失败则退出
end

% 按浮点数格式读取全部内容,转为3行3列矩阵
data = fscanf(fid, '%f', [3,3]);
data = data';  % 转置(fscanf默认按列存储,需转置匹配原文件行列)

% 关闭文件
fclose(fid);

% 输出结果
disp('读取的矩阵:');
disp(data);

输出结果

复制代码
读取的矩阵:
    10    20    30
    40    50    60
    70    80    90

3. 场景2:读取混合格式文本文件

目标文件(info.txt)内容:

复制代码
姓名:张三 年龄:25 成绩:92.5
姓名:李四 年龄:23 成绩:88.0

读取代码

matlab 复制代码
[fid, msg] = fopen('info.txt', 'r');
if fid == -1
    disp(msg);
    return;
end

% 循环读取每一行(feof(fid)判断是否到文件末尾)
while ~feof(fid)
    % 按自定义格式读取:跳过固定字符,提取姓名、年龄、成绩
    line = fscanf(fid, '姓名:%s 年龄:%d 成绩:%f\n', [1,3]);
    % 解析数据
    name = line{1};
    age = line{2};
    score = line{3};
    % 输出
    disp(['姓名:', name, ' 年龄:', num2str(age), ' 成绩:', num2str(score)]);
end

fclose(fid);

关键技巧feof(fid)是"文件末尾判断函数",返回1表示到末尾,0表示未到,适合循环读取多行文本。

4. 场景3:读取纯文本字符串(如日志文件)

目标文件(log.txt)内容:

复制代码
2024-10-10 09:00:00 程序启动
2024-10-10 09:05:00 数据处理完成
2024-10-10 09:10:00 程序退出

读取代码

matlab 复制代码
[fid, msg] = fopen('log.txt', 'r');
if fid == -1
    disp(msg);
    return;
end

% 按字符读取全部内容(保留换行符)
log_content = fscanf(fid, '%c', Inf);
fclose(fid);

% 按换行符拆分每行
log_lines = strsplit(log_content, '\n');
% 遍历输出每行
for i = 1:length(log_lines)
    if ~isempty(log_lines{i})  % 跳过空行
        disp(['第', num2str(i), '行:', log_lines{i}]);
    end
end

四、fprintf():写入内容到文本文件

1. 基本语法

matlab 复制代码
count = fprintf(fid, format, A, B, ...);
  • count:写入的字符个数(可选)
  • format:写入格式,与fscanf()一致,支持\n(换行)、\t(制表符)
  • A,B,...:要写入的变量(数值、字符串均可)

2. 场景1:写入数值矩阵到文本文件

需求:将3x3矩阵按行列格式写入文件,保留1位小数。

matlab 复制代码
% 准备数据
data = [1.23, 4.56, 7.89; 2.34, 5.67, 8.90; 3.45, 6.78, 9.01];

% 打开文件(写入模式,不存在则创建)
[fid, msg] = fopen('output.txt', 'w');
if fid == -1
    disp(msg);
    return;
end

% 循环写入每行
for i = 1:size(data, 1)
    % 按格式写入:每行3个浮点数,保留1位小数,空格分隔,末尾换行
    fprintf(fid, '%.1f %.1f %.1f\n', data(i,1), data(i,2), data(i,3));
end

% 关闭文件
fclose(fid);
disp('数据写入完成!');

生成的output.txt内容

复制代码
1.2 4.6 7.9
2.3 5.7 8.9
3.5 6.8 9.0

3. 场景2:追加内容到文本文件

需求:在上述output.txt末尾追加一行备注信息。

matlab 复制代码
[fid, msg] = fopen('output.txt', 'a');  % 追加模式
if fid == -1
    disp(msg);
    return;
end

% 写入备注(字符串+当前时间)
fprintf(fid, '\n备注:数据生成时间 - %s\n', datestr(now()));
fclose(fid);
disp('备注追加完成!');

追加后的文件内容

复制代码
1.2 4.6 7.9
2.3 5.7 8.9
3.5 6.8 9.0

备注:数据生成时间 - 10-Oct-2024 15:30:00

4. 场景3:写入混合格式内容(字符串+数值)

需求:生成包含实验信息的文本文件,格式如下:

复制代码
实验编号:EXP001
测试温度:25.5 ℃
测试次数:10 次
测试结果:[98.5, 97.8, 99.2]

实现代码

matlab 复制代码
exp_id = 'EXP001';
temp = 25.5;
test_times = 10;
results = [98.5, 97.8, 99.2];

[fid, msg] = fopen('exp_info.txt', 'w');
if fid == -1
    disp(msg);
    return;
end

% 按自定义格式写入
fprintf(fid, '实验编号:%s\n', exp_id);
fprintf(fid, '测试温度:%.1f ℃\n', temp);
fprintf(fid, '测试次数:%d 次\n', test_times);
fprintf(fid, '测试结果:[%.1f, %.1f, %.1f]\n', results(1), results(2), results(3));

fclose(fid);
disp('实验信息写入完成!');

五、fclose():关闭文件的"最后一步"

1. 基本语法

matlab 复制代码
status = fclose(fid);  % 关闭指定句柄的文件
status = fclose('all');  % 关闭所有打开的文件(推荐批量处理时用)
  • status:关闭状态,0表示成功,-1表示失败

2. 关键注意事项

  • 无论读写是否成功,都必须执行fclose(),否则会导致:
    1. 文件被MATLAB占用,无法手动删除/修改;
    2. 写入的内容可能未完全保存(缓存未刷新);
    3. 打开的文件句柄过多,导致后续fopen()失败。
  • 批量处理文件时,用fclose('all')避免遗漏关闭某个文件。

六、避坑指南:新手常见错误与解决方案

1. 坑1:文件路径错误导致fopen失败

  • 现象:fid=-1,错误信息提示"找不到文件";
  • 原因:使用相对路径时,MATLAB当前工作目录不是文件所在目录;
  • 解决方案:
    1. pwd查看当前工作目录,cd切换到文件目录(如cd D:\test);
    2. 直接使用绝对路径(如'D:\test\data.txt')。

2. 坑2:fscanf读取矩阵时行列颠倒

  • 现象:读取的矩阵行列与原文件相反;
  • 原因:fscanf默认按列存储数据;
  • 解决方案:读取后用data = data'转置矩阵。

3. 坑3:写入文件后内容为空

  • 现象:文件创建成功,但内容为空;
  • 原因:未关闭文件(缓存未刷新),或写入格式错误;
  • 解决方案:
    1. 确保执行fclose(fid)
    2. 检查fprintf的格式符与变量类型匹配(如数值用%f,字符串用%s)。

4. 坑4:覆盖原有文件导致数据丢失

  • 现象:原有文件内容被清空;
  • 原因:误使用'w'模式打开文件;
  • 解决方案:
    1. 写入前确认文件是否需要保留,重要文件先备份;
    2. 追加内容用'a'模式,而非'w'模式。

七、实战综合案例:批量处理文本数据

需求

读取多个实验数据文件(data1.txt、data2.txt、data3.txt),计算每个文件的平均值,将结果汇总写入result.txt。

实现代码

matlab 复制代码
% 定义文件列表
file_list = {'data1.txt', 'data2.txt', 'data3.txt'};
% 打开汇总文件
[fid_result, msg] = fopen('result.txt', 'w');
if fid_result == -1
    disp(msg);
    return;
end
fprintf(fid_result, '实验文件\t平均值\n');  % 写入表头

% 遍历每个数据文件
for i = 1:length(file_list)
    filename = file_list{i};
    % 打开数据文件
    [fid_data, msg_data] = fopen(filename, 'r');
    if fid_data == -1
        disp(['跳过文件', filename, ':', msg_data]);
        fprintf(fid_result, '%s\t读取失败\n', filename);
        continue;
    end
    % 读取数据并计算平均值
    data = fscanf(fid_data, '%f', Inf);
    avg = mean(data);
    % 写入汇总文件
    fprintf(fid_result, '%s\t%.2f\n', filename, avg);
    % 关闭数据文件
    fclose(fid_data);
end

% 关闭汇总文件
fclose(fid_result);
disp('批量处理完成,结果已写入result.txt!');
相关推荐
编织幻境的妖2 小时前
Python垃圾回收机制详解
开发语言·python
BrianGriffin2 小时前
JS異步:setTimeout包裝為sleep
开发语言·javascript·ecmascript
遇印记2 小时前
javaOCA考点(基础)
java·开发语言·青少年编程
学困昇2 小时前
Linux基础开发工具(下):调试器gdb/cgdb的使用详解
linux·运维·服务器·开发语言·c++
biter down2 小时前
C++ 组合与继承:从设计本质到实战,吃透高内聚低耦合
开发语言·c++
灰灰勇闯IT2 小时前
C语言实战:字符串元音字母提取器的实现与优化
c语言·开发语言
fantasy5_52 小时前
C++11 核心特性实战博客
java·开发语言·c++
listhi5202 小时前
MOEAD算法实现详解(基于Python与MATLAB)
python·算法·matlab
天若有情6733 小时前
从构造函数到Vue3响应式:C++中“常量转特殊类型”的隐藏大招
开发语言·c++