EasyClick 入门指南(十七):文件操作完全指南
本文基于 EasyClick 官方文档整理
目录
- 前言
- 三平台API差异概览
- [Android 平台文件操作](#Android 平台文件操作 "#%E4%B8%89android-%E5%B9%B3%E5%8F%B0%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C")
- [iOS USB版 文件操作](#iOS USB版 文件操作 "#%E5%9B%9Bios-usb%E7%89%88-%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C")
- [iOS 脱机版 文件操作](#iOS 脱机版 文件操作 "#%E4%BA%94ios-%E8%84%B1%E6%9C%BA%E7%89%88-%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C")
- [鸿蒙 Next 平台文件操作](#鸿蒙 Next 平台文件操作 "#%E5%85%AD%E9%B8%BF%E8%92%99-next-%E5%B9%B3%E5%8F%B0%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C")
- [Excel 数据解析(iOS/鸿蒙)](#Excel 数据解析(iOS/鸿蒙) "#%E4%B8%83excel-%E6%95%B0%E6%8D%AE%E8%A7%A3%E6%9E%90ios%E9%B8%BF%E8%92%99")
- 常见问题
一、前言
为什么需要文件操作?
在自动化脚本中,文件操作是不可或缺的基础能力:
- 日志记录:保存脚本执行日志,方便排查问题
- 配置持久化:保存用户配置、任务状态
- 数据缓存:本地缓存 API 数据,减少网络请求
- 文件处理:读取 Excel、解析 CSV、批量处理文件
- 素材管理:截图保存、安装包管理
EasyClick 文件模块特点
- 支持读写文本文件
- 支持 Excel 文件(iOS 4.0.0+ / 鸿蒙 1.0.0+)
- 支持文件夹遍历、批量操作
- 三平台通用 API 保持一致
- iOS/鸿蒙使用沙盒路径管理
二、三平台API差异概览
2.1 运行环境说明
| 平台 | 运行环境 | 文件操作说明 |
|---|---|---|
| Android | 设备端 | 直接操作设备文件系统 |
| iOS USB版 | PC端中控 | 可操作PC本地文件 或连接设备的沙盒文件 |
| iOS 脱机版 | 设备端 | 仅可操作应用沙盒内文件 |
| 鸿蒙 | PC端中控 | 可操作PC本地文件 或连接设备的沙盒文件 |
注意:iOS USB版和鸿蒙版类似,都运行在PC端中控,支持PC本地路径和设备沙盒路径两种模式。 iOS 脱机版运行在设备端,只能使用沙盒路径。
2.2 通用API(三平台共有)
以下API在 Android、iOS(USB/脱机)、鸿蒙三平台通用:
| API | 功能说明 |
|---|---|
file.readFile(path) |
读取文件为字符串 |
file.writeFile(data, path) |
写入文件(覆盖模式) |
file.readLine(path, lineNo) |
读取指定行 |
file.appendLine(data, path) |
追加一行到文件 |
file.readAllLines(path) |
读取所有行到数组 |
file.deleteLine(path, line, contains) |
删除指定行或匹配行 |
file.listDir(path) |
列出目录下所有文件(递归) |
file.create(path) |
创建空文件 |
file.mkdirs(path) |
创建文件夹(支持多级) |
file.deleteAllFile(path) |
删除文件或文件夹 |
file.exists(path) |
检查文件是否存在 |
file.copy(src, dest) |
复制文件 |
2.3 平台特有API
| API | Android | iOS USB | iOS 脱机 | 鸿蒙 | 说明 |
|---|---|---|---|---|---|
file.readAssets(path) |
✅ | ❌ | ❌ | ❌ | 读取APK assets文件 |
file.getSandBoxDir() |
❌ | ✅ | ✅ | ✅ | 获取沙盒根目录 |
file.getSandBoxFilePath(name) |
❌ | ✅ | ✅ | ✅ | 拼接沙盒文件路径 |
file.getInternalDir(type) |
❌ | ❌ | ✅ | ❌ | 获取内部存储地址(脱机版特有) |
file.readExcelRow(path, sheet, row) |
❌ | ✅ | ✅ | ✅ | 读取Excel一行 |
file.readExcelAllRow(path, sheet) |
❌ | ✅ | ✅ | ✅ | 读取Excel所有数据 |
file.listDir2(path, recursion) |
❌ | ❌ | ✅ | ❌ | 列出文件(可配置是否递归,脱机版特有) |
file.readLineEx(path, lineNo) |
❌ | ❌ | ✅ | ❌ | 读取一行(适合大文件,脱机版特有) |
file.appendLineEx(data, path) |
❌ | ❌ | ✅ | ❌ | 追加一行(适合大文件,脱机版特有) |
file.deleteLineEx(path, line, contains) |
❌ | ❌ | ✅ | ❌ | 删除行(适合大文件,脱机版特有) |
2.4 文件路径差异
| 平台 | 路径写法 | 示例 |
|---|---|---|
| Android | 直接写绝对路径 | /sdcard/test.txt |
| iOS USB版 | PC本地路径 或 设备沙盒路径 | D:/test.txt 或 file.getSandBoxFilePath("test.txt") |
| iOS 脱机版 | 沙盒路径 | 使用 file.getSandBoxFilePath("test.txt") |
| 鸿蒙 | PC本地路径 或 设备沙盒路径 | D:/test.txt 或 file.getSandBoxFilePath("test.txt") |
三、Android 平台文件操作
3.1 文件路径
Android 平台可以直接使用绝对路径访问外部存储:
javascript
/**
* Android 平台文件路径示例
*/
function androidFilePath() {
// 直接写绝对路径
var filePath = "/sdcard/test.txt";
var dirPath = "/sdcard/easyclick/logs/";
// 检查文件是否存在
if (file.exists(filePath)) {
logd("文件存在: " + filePath);
} else {
logd("文件不存在: " + filePath);
}
// 确保目录存在
if (!file.exists(dirPath)) {
file.mkdirs(dirPath);
logd("创建目录: " + dirPath);
}
}
3.2 读取文件
javascript
/**
* Android: 读取整个文件为字符串
*/
function readFileAndroid() {
var filePath = "/sdcard/config.json";
// 检查文件是否存在
if (!file.exists(filePath)) {
loge("文件不存在: " + filePath);
return null;
}
// 读取文件内容
var content = file.readFile(filePath);
if (content) {
logd("文件内容:\n" + content);
return content;
} else {
loge("读取失败");
return null;
}
}
3.3 逐行读取
javascript
/**
* Android: 逐行读取文件
*/
function readLineByLineAndroid() {
var filePath = "/sdcard/app.log";
var lineNo = 1;
var maxLines = 100;
while (lineNo <= maxLines) {
var line = file.readLine(filePath, lineNo);
if (!line) {
logd("到达文件末尾,已读取 " + (lineNo - 1) + " 行");
break;
}
logd("第 " + lineNo + " 行: " + line);
// 过滤包含 ERROR 的行
if (line.indexOf("ERROR") >= 0) {
loge("发现错误: " + line);
}
lineNo++;
}
}
3.4 写入文件
javascript
/**
* Android: 写入文件(覆盖模式)
*/
function writeFileAndroid() {
var filePath = "/sdcard/output.txt";
var content = "Hello EasyClick!\n" + "这是第一行数据\n" + "这是第二行数据";
var result = file.writeFile(content, filePath);
if (result) {
logd("写入成功");
} else {
loge("写入失败");
}
}
3.5 追加写入
javascript
/**
* Android: 追加写入文件(适合日志)
*/
function appendToLogAndroid() {
var logFile = "/sdcard/script.log";
file.appendLine("[2024-01-01 10:00:00] 脚本启动", logFile);
file.appendLine("[2024-01-01 10:00:05] 任务开始执行", logFile);
file.appendLine("[2024-01-01 10:00:10] 点击按钮成功", logFile);
logd("日志已追加写入");
}
3.6 文件夹操作
javascript
/**
* Android: 创建文件夹
*/
function createFolderAndroid() {
var dirPath = "/sdcard/easyclick/projects/";
var result = file.mkdirs(dirPath);
if (result) {
logd("文件夹创建成功: " + dirPath);
} else {
loge("文件夹创建失败");
}
}
/**
* Android: 列出文件夹内容
*/
function listFilesAndroid() {
var dirPath = "/sdcard/";
var files = file.listDir(dirPath);
if (files) {
logd("目录下共有 " + files.length + " 个文件/文件夹:");
for (var i = 0; i < files.length; i++) {
var fileName = files[i].substring(files[i].lastIndexOf("/") + 1);
logd(" " + (i + 1) + ". " + fileName);
}
}
}
3.7 文件增删改查
javascript
/**
* Android: 创建文件
*/
function createFileAndroid() {
var filePath = "/sdcard/new_file.txt";
if (file.exists(filePath)) {
logd("文件已存在");
return false;
}
var result = file.create(filePath);
if (result) {
logd("文件创建成功");
file.writeFile("初始化内容", filePath);
return true;
} else {
loge("文件创建失败");
return false;
}
}
/**
* Android: 删除文件/文件夹
*/
function deleteFileAndroid() {
var result1 = file.deleteAllFile("/sdcard/temp.txt");
logd("删除文件: " + (result1 ? "成功" : "失败"));
var result2 = file.deleteAllFile("/sdcard/temp_dir/");
logd("删除文件夹: " + (result2 ? "成功" : "失败"));
}
/**
* Android: 复制文件
*/
function copyFileAndroid() {
var srcPath = "/sdcard/source.txt";
var destPath = "/sdcard/backup/source.txt";
var destDir = "/sdcard/backup/";
// 确保目标目录存在
if (!file.exists(destDir)) {
file.mkdirs(destDir);
}
var result = file.copy(srcPath, destPath);
logd("复制: " + (result ? "成功" : "失败"));
}
/**
* Android: 删除指定行
*
* 参数说明:
* - line: 行号,从1开始。如果为-1,则按contains条件删除
* - contains: 包含的字符串,如果为null则按行号删除
*
* 使用规则:
* - line > 0, contains = null: 删除指定行号
* - line = -1, contains = "xxx": 删除包含"xxx"的行
*/
function deleteLinesAndroid() {
var filePath = "/sdcard/data.txt";
// 删除第3行 (line=3, contains=null: 按行号删除)
var result1 = file.deleteLine(filePath, 3, null);
logd("删除第3行: " + (result1 ? "成功" : "失败"));
// 删除包含 ERROR 的行 (line=-1: 按包含条件删除)
var result2 = file.deleteLine(filePath, -1, "ERROR");
logd("删除包含 ERROR 的行: " + (result2 ? "成功" : "失败"));
}
3.8 读取Assets(Android特有)
javascript
/**
* Android: 读取APK assets文件
*/
function readAssetsAndroid() {
// 读取 assets/data/config.json
var data = file.readAssets("data/config.json");
logd("Assets内容: " + data);
}
iOS 平台文件操作
重要区别:iOS 有两个版本,文件操作方式不同:
- iOS USB版:运行在PC端中控,支持PC本地路径和设备沙盒路径
- iOS 脱机版:运行在设备端,只能使用沙盒路径
四、iOS USB版 文件操作
iOS USB版运行在PC端中控,与鸿蒙版类似,支持两种路径模式。
4.1 两种路径模式
javascript
/**
* iOS USB版: 两种路径模式说明
*/
function iosUsbFilePath() {
// 模式1:PC本地路径(直接操作电脑文件)
var pcPath = "D:/test.txt";
var pcDir = "D:/easyclick/data/";
logd("PC本地路径: " + pcPath);
// 模式2:设备沙盒路径(操作连接设备的文件)
// 获取当前设备的沙盒根目录
var sandboxDir = file.getSandBoxDir();
logd("设备沙盒根目录: " + sandboxDir);
// 拼接设备沙盒中的文件路径
var deviceConfigPath = file.getSandBoxFilePath("config.json");
var deviceLogPath = file.getSandBoxFilePath("logs/app.log");
logd("设备配置文件: " + deviceConfigPath);
logd("设备日志文件: " + deviceLogPath);
}
4.2 PC本地文件操作
javascript
/**
* iOS USB版: 操作PC本地文件
*/
function readFilePC_IOS() {
// 操作PC本地文件
var filePath = "D:/config.json";
if (!file.exists(filePath)) {
loge("文件不存在: " + filePath);
return null;
}
var content = file.readFile(filePath);
logd("PC文件内容: " + content);
return content;
}
/**
* iOS USB版: 写入PC本地文件
*/
function writeFilePC_IOS() {
var filePath = "D:/output.txt";
var result = file.writeFile("iOS USB版PC端写入测试", filePath);
logd("PC文件写入: " + (result ? "成功" : "失败"));
}
/**
* iOS USB版: PC本地日志
*/
function appendLogPC_IOS() {
var logFile = "D:/logs/app.log";
// 确保日志目录存在
var logDir = "D:/logs/";
if (!file.exists(logDir)) {
file.mkdirs(logDir);
}
file.appendLine("[" + new Date().toISOString() + "] PC端日志", logFile);
logd("PC日志已追加");
}
4.3 设备沙盒文件操作
javascript
/**
* iOS USB版: 读取设备沙盒文件
*/
function readFileDevice_IOS() {
// 操作连接设备的沙盒文件
var filePath = file.getSandBoxFilePath("config.json");
if (!file.exists(filePath)) {
loge("设备文件不存在");
return null;
}
var content = file.readFile(filePath);
logd("设备文件内容: " + content);
return content;
}
/**
* iOS USB版: 写入设备沙盒文件
*/
function writeFileDevice_IOS() {
var filePath = file.getSandBoxFilePath("output.txt");
var result = file.writeFile("设备沙盒写入测试", filePath);
logd("设备文件写入: " + (result ? "成功" : "失败"));
}
/**
* iOS USB版: 创建设备沙盒文件夹
*/
function createDeviceFolder_IOS() {
var dirPath = file.getSandBoxFilePath("projects/");
var result = file.mkdirs(dirPath);
logd("创建设备文件夹: " + (result ? "成功" : "失败"));
}
/**
* iOS USB版: 列出设备沙盒文件
*/
function listDeviceFiles_IOS() {
var sandboxDir = file.getSandBoxDir();
var files = file.listDir(sandboxDir);
if (files) {
logd("设备沙盒文件数: " + files.length);
}
}
五、iOS 脱机版 文件操作
iOS 脱机版运行在设备端,只能使用沙盒路径,不能访问PC本地路径。
5.1 沙盒路径
javascript
/**
* iOS 脱机版: 沙盒路径使用
*/
function iosOfflineFilePath() {
// 获取沙盒根目录
var sandboxDir = file.getSandBoxDir();
logd("沙盒根目录: " + sandboxDir);
// 拼接沙盒文件路径(推荐)
var configPath = file.getSandBoxFilePath("config.json");
var logPath = file.getSandBoxFilePath("logs/app.log");
logd("配置文件: " + configPath);
logd("日志文件: " + logPath);
}
/**
* iOS 脱机版: 获取内部存储地址(脱机版特有)
*/
function getInternalDir_IOS() {
// documents, library, temp, libraryCaches
// documents文件夹类型可以通过爱思导出
var docPath = file.getInternalDir("documents");
logd("Documents路径: " + docPath);
var tempPath = file.getInternalDir("temp");
logd("Temp路径: " + tempPath);
}
5.2 读取文件
javascript
/**
* iOS 脱机版: 读取文件
*/
function readFileIOS_Offline() {
// 使用沙盒路径
var filePath = file.getSandBoxFilePath("config.json");
if (!file.exists(filePath)) {
loge("文件不存在: " + filePath);
return null;
}
var content = file.readFile(filePath);
if (content) {
logd("文件内容:\n" + content);
return content;
} else {
loge("读取失败");
return null;
}
}
5.3 写入文件
javascript
/**
* iOS 脱机版: 写入文件
*/
function writeFileIOS_Offline() {
var filePath = file.getSandBoxFilePath("output.txt");
var content = "Hello EasyClick!\n" + "iOS 脱机版沙盒写入测试";
var result = file.writeFile(content, filePath);
logd("写入: " + (result ? "成功" : "失败"));
}
/**
* iOS 脱机版: 追加日志
*/
function appendLogIOS_Offline() {
var logFile = file.getSandBoxFilePath("app.log");
file.appendLine("[" + new Date().toISOString() + "] 日志内容", logFile);
logd("日志已追加");
}
5.4 文件夹操作
javascript
/**
* iOS 脱机版: 创建文件夹
*/
function createFolderIOS_Offline() {
var dirPath = file.getSandBoxFilePath("easyclick/projects/");
var result = file.mkdirs(dirPath);
logd("创建文件夹: " + (result ? "成功" : "失败"));
}
/**
* iOS 脱机版: 列出沙盒文件(递归)
*/
function listFilesIOS_Offline() {
var dirPath = file.getSandBoxDir();
// listDir 默认递归列出所有子文件夹
var files = file.listDir(dirPath);
if (files) {
logd("沙盒下共有 " + files.length + " 个文件:");
for (var i = 0; i < files.length; i++) {
var fileName = files[i].substring(files[i].lastIndexOf("/") + 1);
logd(" " + (i + 1) + ". " + fileName);
}
}
}
/**
* iOS 脱机版: 列出文件(可配置是否递归)
* 适配EC脱机 4.1.0+,脱机版特有API
*/
function listFilesIOS_NoRecurse() {
var dirPath = file.getSandBoxDir();
// listDir2 可以配置是否递归
// 第二个参数: true=递归, false=不递归
var files = file.listDir2(dirPath, false);
if (files) {
logd("当前目录下共有 " + files.length + " 个文件/文件夹");
}
}
5.5 文件增删改查
javascript
/**
* iOS 脱机版: 文件操作示例
*/
function fileOperationsIOS_Offline() {
// 创建文件
var filePath = file.getSandBoxFilePath("test.txt");
if (!file.exists(filePath)) {
file.create(filePath);
file.writeFile("初始化内容", filePath);
logd("文件已创建");
}
// 复制文件
var backupPath = file.getSandBoxFilePath("test_backup.txt");
file.copy(filePath, backupPath);
logd("文件已备份");
// 删除文件
// file.deleteAllFile(filePath);
}
/**
* iOS 脱机版: 删除指定行
*/
function deleteLinesIOS_Offline() {
var filePath = file.getSandBoxFilePath("data.txt");
// 删除第3行
var result1 = file.deleteLine(filePath, 3, null);
logd("删除第3行: " + (result1 ? "成功" : "失败"));
// 删除包含 ERROR 的行
var result2 = file.deleteLine(filePath, -1, "ERROR");
logd("删除包含 ERROR 的行: " + (result2 ? "成功" : "失败"));
}
/**
* iOS 脱机版: 大文件操作(Ex系列API,脱机版特有)
* 适配 EC 4.7.3+
*/
function largeFileOperationsIOS_Offline() {
var filePath = file.getSandBoxFilePath("large.log");
// readLineEx - 适合大文件的读取一行
var line = file.readLineEx(filePath, 1000);
logd("第1000行: " + line);
// appendLineEx - 适合大文件的追加写入
var result = file.appendLineEx("新日志内容", filePath);
logd("追加: " + (result ? "成功" : "失败"));
// deleteLineEx - 适合大文件的删除行
var delResult = file.deleteLineEx(filePath, -1, "过期数据");
logd("删除包含'过期数据'的行: " + (delResult ? "成功" : "失败"));
}
六、鸿蒙 Next 平台文件操作
注意:鸿蒙版运行在PC端中控,支持两种路径:
- PC本地路径 (如
D:/test.txt)- 直接操作电脑文件- 设备沙盒路径 (通过
getSandBoxFilePath)- 操作连接设备的沙盒文件
6.1 两种路径模式
javascript
/**
* 鸿蒙: 两种路径模式说明
*/
function harmonyFilePath() {
// 模式1:PC本地路径(直接操作电脑文件)
var pcPath = "D:/test.txt";
var pcDir = "D:/easyclick/data/";
logd("PC本地路径: " + pcPath);
// 模式2:设备沙盒路径(操作连接设备的文件)
// 获取当前设备的沙盒根目录
var sandboxDir = file.getSandBoxDir();
logd("设备沙盒根目录: " + sandboxDir);
// 拼接设备沙盒中的文件路径
var deviceConfigPath = file.getSandBoxFilePath("config.json");
var deviceLogPath = file.getSandBoxFilePath("logs/app.log");
logd("设备配置文件: " + deviceConfigPath);
logd("设备日志文件: " + deviceLogPath);
}
6.2 PC本地文件操作
javascript
/**
* 鸿蒙: 操作PC本地文件
*/
function readFilePCHarmony() {
// 操作PC本地文件
var filePath = "D:/config.json";
if (!file.exists(filePath)) {
loge("文件不存在: " + filePath);
return null;
}
var content = file.readFile(filePath);
logd("PC文件内容: " + content);
return content;
}
/**
* 鸿蒙: 写入PC本地文件
*/
function writeFilePCHarmony() {
var filePath = "D:/output.txt";
var result = file.writeFile("鸿蒙PC端写入测试", filePath);
logd("PC文件写入: " + (result ? "成功" : "失败"));
}
/**
* 鸿蒙: PC本地日志
*/
function appendLogPCHarmony() {
var logFile = "D:/logs/app.log";
// 确保日志目录存在
var logDir = "D:/logs/";
if (!file.exists(logDir)) {
file.mkdirs(logDir);
}
file.appendLine("[" + new Date().toISOString() + "] PC端日志", logFile);
logd("PC日志已追加");
}
6.3 设备沙盒文件操作
javascript
/**
* 鸿蒙: 读取设备沙盒文件
*/
function readFileDeviceHarmony() {
// 操作连接设备的沙盒文件
var filePath = file.getSandBoxFilePath("data.txt");
if (!file.exists(filePath)) {
loge("设备文件不存在");
return null;
}
var content = file.readFile(filePath);
logd("设备文件内容: " + content);
return content;
}
/**
* 鸿蒙: 写入设备沙盒文件
*/
function writeFileDeviceHarmony() {
var filePath = file.getSandBoxFilePath("output.txt");
var result = file.writeFile("设备沙盒写入测试", filePath);
logd("设备文件写入: " + (result ? "成功" : "失败"));
}
/**
* 鸿蒙: 创建设备沙盒文件夹
*/
function createDeviceFolderHarmony() {
var dirPath = file.getSandBoxFilePath("projects/");
var result = file.mkdirs(dirPath);
logd("创建设备文件夹: " + (result ? "成功" : "失败"));
}
/**
* 鸿蒙: 列出设备沙盒文件
*/
function listDeviceFilesHarmony() {
var sandboxDir = file.getSandBoxDir();
var files = file.listDir(sandboxDir);
if (files) {
logd("设备沙盒文件数: " + files.length);
}
}
七、Excel 数据解析(iOS/鸿蒙)
⚠️ 注意:Excel API 仅支持 iOS 4.0.0+ 和 鸿蒙 1.0.0+,Android 平台官方API暂不支持(需要自行Java插件实现)。
7.1 iOS 读取 Excel
javascript
/**
* iOS: 读取 Excel 指定行
* 适合版本: EC iOS 4.0.0+
*/
function readExcelRowIOS() {
// iOS 直接使用文件名(相对于沙盒)
var excelPath = "users.xlsx";
var sheetIndex = 0; // 第1个工作表
var rowIndex = 1; // 第2行(第0行是表头)
var rowData = file.readExcelRow(excelPath, sheetIndex, rowIndex);
if (rowData) {
logd("第 " + (rowIndex + 1) + " 行数据:");
for (var key in rowData) {
logd(" " + key + ": " + rowData[key]);
}
}
}
/**
* iOS: 读取 Excel 所有数据
* 适合版本: EC iOS 4.0.0+
*/
function readExcelAllIOS() {
var excelPath = "users.xlsx";
var sheetIndex = 0;
var allData = file.readExcelAllRow(excelPath, sheetIndex);
if (allData) {
logd("共读取 " + allData.length + " 条记录");
for (var i = 0; i < allData.length; i++) {
var row = allData[i];
logd("记录 " + (i + 1) + ":");
logd(" 姓名: " + row.姓名);
logd(" 年龄: " + row.年龄);
}
}
}
7.2 鸿蒙读取 Excel
鸿蒙版Excel文件可以放在PC本地或设备沙盒中
javascript
/**
* 鸿蒙: 从PC本地读取 Excel
* 适合版本: EC 鸿蒙 1.0.0+
*/
function readExcelRowHarmonyPC() {
// 从PC本地路径读取
var excelPath = "D:/data/users.xlsx";
var sheetIndex = 0;
var rowIndex = 1;
var rowData = file.readExcelRow(excelPath, sheetIndex, rowIndex);
if (rowData) {
logd("第 " + (rowIndex + 1) + " 行数据:");
for (var key in rowData) {
logd(" " + key + ": " + rowData[key]);
}
}
}
/**
* 鸿蒙: 从设备沙盒读取 Excel
* 适合版本: EC 鸿蒙 1.0.0+
*/
function readExcelRowHarmonyDevice() {
// 从设备沙盒读取(直接使用文件名)
var excelPath = "users.xlsx";
var sheetIndex = 0;
var rowIndex = 1;
var rowData = file.readExcelRow(excelPath, sheetIndex, rowIndex);
if (rowData) {
logd("第 " + (rowIndex + 1) + " 行数据:");
for (var key in rowData) {
logd(" " + key + ": " + rowData[key]);
}
}
}
/**
* 鸿蒙: 读取 Excel 所有数据
* 适合版本: EC 鸿蒙 1.0.0+
*/
function readExcelAllHarmony() {
// 可以从PC本地或设备沙盒读取
var excelPath = "users.xlsx"; // 设备沙盒
// var excelPath = "D:/data/users.xlsx"; // PC本地
var sheetIndex = 0;
var allData = file.readExcelAllRow(excelPath, sheetIndex);
if (allData) {
logd("共读取 " + allData.length + " 条记录");
for (var i = 0; i < allData.length; i++) {
var row = allData[i];
logd("记录 " + (i + 1) + ":");
logd(" 姓名: " + row.姓名);
logd(" 年龄: " + row.年龄);
}
}
}
7.3 批量处理 Excel 数据(iOS/鸿蒙)
javascript
/**
* 从 Excel 读取数据并执行自动化操作
* 适用于 iOS 4.0.0+ / 鸿蒙 1.0.0+
*/
function batchProcessFromExcel() {
var excelPath = "tasks.xlsx";
// 读取所有任务
var tasks = file.readExcelAllRow(excelPath, 0);
if (!tasks) {
loge("读取任务失败");
return;
}
logd("共找到 " + tasks.length + " 个任务");
// 逐个执行任务
for (var i = 0; i < tasks.length; i++) {
var task = tasks[i];
logd("执行任务 " + (i + 1) + ": " + task.任务名称);
try {
executeTask(task);
logd("任务完成");
} catch (e) {
loge("任务执行失败: " + e.message);
}
}
}
function executeTask(task) {
switch (task.操作类型) {
case "登录":
login(task.用户名, task.密码);
break;
case "提交":
submitForm(task.表单内容);
break;
case "截图":
captureScreen(task.保存路径);
break;
default:
loge("未知操作类型: " + task.操作类型);
}
}
function login(username, password) {
logd("执行登录: " + username);
}
function submitForm(content) {
logd("提交表单: " + content);
}
function captureScreen(path) {
logd("截图保存: " + path);
}
八、常见问题
Q1: 文件读写失败怎么办?
javascript
// 1. 检查路径是否正确
var filePath = "/sdcard/test.txt"; // Android
// var filePath = file.getSandBoxFilePath("test.txt"); // iOS脱机版/鸿蒙设备沙盒
// var filePath = "D:/test.txt"; // iOS USB版/鸿蒙PC本地
logd("检查文件: " + file.exists(filePath));
// 2. 检查目录是否存在
var dirPath = "/sdcard/mydir/"; // Android
// var dirPath = file.getSandBoxFilePath("mydir/"); // iOS脱机版/鸿蒙设备沙盒
// var dirPath = "D:/mydir/"; // iOS USB版/鸿蒙PC本地
if (!file.exists(dirPath)) {
file.mkdirs(dirPath);
logd("目录不存在,已创建");
}
// 3. Android 需要存储权限
// iOS脱机版/鸿蒙设备沙盒无需额外权限
// iOS USB版/鸿蒙PC本地路径无需额外权限
Q2: iOS/鸿蒙如何查看沙盒文件?
javascript
// iOS脱机版: 获取沙盒路径并打印
var sandboxDir = file.getSandBoxDir();
logd("iOS沙盒路径: " + sandboxDir);
// iOS USB版/鸿蒙: 获取设备沙盒路径
var deviceSandboxDir = file.getSandBoxDir();
logd("设备沙盒路径: " + deviceSandboxDir);
// 使用 EasyClick IDE 的文件管理器查看
// 或通过 iTunes 文件共享导出(iOS脱机版如支持)
Q3: iOS USB版/鸿蒙版如何选择PC本地路径还是设备沙盒路径?
javascript
/**
* iOS USB版/鸿蒙版两种路径模式选择指南
*/
// 场景1:配置文件、日志文件放在PC本地(推荐)
// 优点:方便查看和管理,重启后保留
var pcConfigPath = "D:/easyclick/config.json";
var pcLogPath = "D:/easyclick/logs/app.log";
// 场景2:临时数据、截图等放在设备沙盒
// 优点:与设备关联,多设备隔离
var deviceTempPath = file.getSandBoxFilePath("temp/data.tmp");
var deviceScreenshotPath = file.getSandBoxFilePath("screenshots/");
// 场景3:Excel数据文件可以放在任意位置
var excelPathPC = "D:/data/users.xlsx"; // PC本地
var excelPathDevice = "users.xlsx"; // 设备沙盒
Q4: 大文件读取内存溢出怎么办?
javascript
// 使用 readLine 逐行读取,避免一次性加载
function readLargeFile() {
var filePath = "/sdcard/big.log"; // Android
// var filePath = file.getSandBoxFilePath("big.log"); // iOS/鸿蒙设备沙盒
// var filePath = "D:/logs/big.log"; // 鸿蒙PC本地
for (var i = 1; i <= 10000; i++) {
var line = file.readLine(filePath, i);
if (!line) break;
logd("第 " + i + " 行: " + line);
}
}
Q5: 如何递归遍历所有子文件夹?
javascript
// 递归遍历函数(三平台通用)
function recursiveListDir(dirPath) {
var files = file.listDir(dirPath);
if (!files) return;
for (var i = 0; i < files.length; i++) {
var fullPath = files[i];
var fileName = fullPath.substring(fullPath.lastIndexOf("/") + 1);
// 判断是否为文件夹(无扩展名或以/结尾)
if (fileName.indexOf(".") < 0 || fullPath.endsWith("/")) {
// 是文件夹,递归遍历
recursiveListDir(fullPath);
} else {
// 是文件,处理
logd("文件: " + fullPath);
}
}
}
// Android 使用
recursiveListDir("/sdcard/");
// iOS脱机版 使用
// recursiveListDir(file.getSandBoxDir());
// iOS USB版/鸿蒙 PC本地使用
// recursiveListDir("D:/easyclick/");
// iOS USB版/鸿蒙 设备沙盒使用
// recursiveListDir(file.getSandBoxDir());
Q6: iOS脱机版有哪些特有的大文件API?
iOS脱机版提供了Ex系列API,专门用于处理大文件,避免内存溢出:
javascript
/**
* iOS脱机版特有的大文件API(适配EC 4.7.3+)
*/
function largeFileOperationsIOS() {
var filePath = file.getSandBoxFilePath("large.log");
// readLineEx - 适合大文件的读取一行
var line = file.readLineEx(filePath, 1000);
logd("第1000行: " + line);
// appendLineEx - 适合大文件的追加写入
var result = file.appendLineEx("新日志内容", filePath);
logd("追加: " + (result ? "成功" : "失败"));
// deleteLineEx - 适合大文件的删除行
var delResult = file.deleteLineEx(filePath, -1, "过期数据");
logd("删除包含'过期数据'的行: " + (delResult ? "成功" : "失败"));
}
/**
* iOS脱机版: 可配置递归的目录遍历(适配EC脱机 4.1.0+)
*/
function listDirWithConfig_IOS() {
var dirPath = file.getSandBoxDir();
// listDir2 可以配置是否递归
// 第二个参数: true=递归, false=不递归
var files = file.listDir2(dirPath, false);
logd("当前目录文件数: " + files.length);
}
Q7: Android 能否使用 Excel API?
根据官方文档,Android 平台暂不支持 file.readExcelRow 和 file.readExcelAllRow API。如需在 Android 处理 Excel,建议:
- 使用第三方库实现Java插件方式解析 Excel
- 将 Excel 转换为 CSV 格式处理
- 通过 HTTP 接口在服务端处理
结语
本文基于 EasyClick 官方文档整理,各平台API以知识库为准:
| 平台 | 运行环境 | 通用API | 特有API |
|---|---|---|---|
| Android | 设备端 | ✅ 全部通用 | file.readAssets |
| iOS USB版 | PC端中控 | ✅ 全部通用 | file.getSandBoxDir, file.getSandBoxFilePath, file.readExcelRow, file.readExcelAllRow |
| iOS 脱机版 | 设备端 | ✅ 全部通用 | file.getSandBoxDir, file.getSandBoxFilePath, file.readExcelRow, file.readExcelAllRow, file.getInternalDir, file.listDir2, file.readLineEx, file.appendLineEx, file.deleteLineEx |
| 鸿蒙 | PC端中控 | ✅ 全部通用 | file.getSandBoxDir, file.getSandBoxFilePath, file.readExcelRow, file.readExcelAllRow |
相关资源:
-
EasyClick 官网:www.ieasyclick.com
-
EasyClick 文档:laoleng.vip/docs/easycl...