一、核心文件操作接口

1. 基础文件IO接口(fileio)

import fileio from '@ohos.fileio'; // 正确的文件系统模块

// 创建目录(确保目录存在,递归创建)
fileio.mkdirSync('/data/storage/el2/base/app/documents', { recursive: true });

// 文本文件读写(同步方式)
const file = fileio.openSync('internal://app/test.txt', fileio.OpenMode.READ_WRITE);
fileio.writeSync(file.fd, new TextEncoder().encode('Hello HarmonyOS').buffer);
const buffer = new ArrayBuffer(1024);
fileio.readSync(file.fd, buffer);
fileio.closeSync(file.fd); // 必须关闭文件描述符

// 文本文件读写(异步方式)
const readTextFile = async (filePath: string) => {
  try {
    const file = await fileio.open(filePath, fileio.OpenMode.READ_ONLY);
    const buffer = new ArrayBuffer(1024);
    const bytesRead = await fileio.read(file.fd, buffer);
    const text = new TextDecoder().decode(buffer.slice(0, bytesRead));
    await fileio.close(file.fd);
    return text;
  } catch (error) {
    console.error('Failed to read file:', error);
    throw error;
  }
};

2. 文件选择器接口(filePicker)

import filePicker from '@ohos.filePicker'; // 正确的文件选择器模块

// 调用系统文件选择器(异步方式)
const selectFile = async () => {
  const options = {
    type: filePicker.FileType.IMAGE,
    multiple: false
  };
  try {
    const result = await filePicker.getFilePicker().select(options);
    return result;
  } catch (error) {
    console.error('File selection failed:', error);
    throw error;
  }
};

3. 文件预览接口(filePreview)

import filePreview from '@ohos.filePreview'; // 正确的文件预览模块

// PDF文件预览(异步方式)
const previewPDF = async (filePath: string) => {
  try {
    await filePreview.openPreview({
      uri: filePath,
      mimeType: 'application/pdf'
    });
  } catch (error) {
    console.error('Failed to preview PDF:', error);
  }
};

4.分布式文件系统操作(distributedFile)

由于篇幅有限,参考我的专栏文章《鸿蒙分布式文件操作实际开发案例

二、典型开发案例

案例1:日志文件管理

// 创建每日日志文件(异步方式)
const createDailyLog = async () => {
  const dateStr = new Date().toISOString().split('T')[0];
  const logDir = 'internal://app/logs';
  const logPath = `${logDir}/${dateStr}.log`;
  
  // 确保日志目录存在
  if (!await fileio.access(logDir)) {
    await fileio.mkdir(logDir, { recursive: true });
  }
  
  // 创建日志文件(如果不存在)
  if (!await fileio.access(logPath)) {
    await fileio.createFile(logPath);
  }
  
  return logPath;
};

案例2:配置文件读写

// 读取JSON配置文件(异步方式)
const readConfig = async () => {
  const configPath = 'internal://app/config.json';
  if (!await fileio.access(configPath)) {
    throw new Error('Config file not found');
  }
  
  const file = await fileio.open(configPath, fileio.OpenMode.READ_ONLY);
  const buffer = new ArrayBuffer(1024);
  const bytesRead = await fileio.read(file.fd, buffer);
  await fileio.close(file.fd);
  
  return JSON.parse(new TextDecoder().decode(buffer.slice(0, bytesRead)));
};

// 写入配置修改(异步方式)
const saveConfig = async (configObj) => {
  const configPath = 'internal://app/config.json';
  const data = new TextEncoder().encode(JSON.stringify(configObj));
  
  const file = await fileio.open(configPath, fileio.OpenMode.WRITE_ONLY);
  await fileio.write(file.fd, data.buffer);
  await fileio.close(file.fd);
};

案例3:多格式文件预览

// 通用文件预览方法(异步方式)
const previewFile = async (fileUri) => {
  const mimeMap = {
    'pdf': 'application/pdf',
    'jpg': 'image/jpeg',
    'jpeg': 'image/jpeg',
    'png': 'image/png',
    'mp4': 'video/mp4',
    'mp3': 'audio/mpeg',
    'txt': 'text/plain'
  };
  
  const ext = fileUri.split('.').pop().toLowerCase();
  const mimeType = mimeMap[ext] || 'application/octet-stream';
  
  try {
    await filePreview.openPreview({
      uri: fileUri,
      mimeType: mimeType
    });
  } catch (error) {
    console.error('Failed to preview file:', error);
  }
};

三、关键注意事项

1. 沙箱路径规范

  • 应用私有目录internal://app/(对应路径:/data/storage/el2/base/app/
  • 公共存储目录external://(对应路径:/data/storage/el2/base/external/
  • 系统目录/data/storage/el1/(需要特殊权限,一般不推荐直接访问)
  • 避免路径拼写错误:路径中不要包含空格和特殊字符

2. 权限声明策略

// module.json5配置
"requestPermissions": [
  { "name": "ohos.permission.READ_USER_STORAGE" },
  { "name": "ohos.permission.WRITE_USER_STORAGE" }
]

3. 资源释放原则

  • 文件描述符必须显式关闭(fileio.closeSync(fd)
  • 使用try...finally确保文件描述符总是被关闭
  • 对于异步操作,使用await确保操作完成

4. 安全限制要点

  • 应用私有目录(internal://app/)不需要额外权限
  • 公共存储(external://)需要READ_MEDIAWRITE_MEDIA权限
  • 敏感数据建议加密存储(如使用@ohos.security加密)
  • 避免在文件路径中使用特殊字符和空格

5. 性能优化建议

  • 大文件操作使用@ohos.taskPool启动任务线程
  • 频繁读写场景采用内存缓存机制
  • 使用异步API避免阻塞主线程
  • 对于大文件,采用分块读写方式

6. 常见错误码及处理

  • 13900012:权限不足(检查权限声明)
  • 13900013:文件不存在(检查路径和文件是否存在)
  • 13900015:文件过大(分块读写)
  • 13900016:存储空间不足(检查设备存储空间)
  • 14800021:数据库操作错误(与文件操作无关,但常见)

7. 文件大小限制

  • 单个文件最大支持1GB
  • 总存储空间受设备限制
  • 大文件处理建议分块读写

四、调试技巧

1. 真机文件管理

  • 通过DevEco Studio的Device File Explorer查看沙箱文件
  • 使用hdc shell命令导出文件:
    hdc file send /data/storage/el2/base/app/yourfile localpath
    

2. 日志分析

  • 通过DevEco Studio的Logcat工具查看文件操作日志
  • 使用fileio.statSync检查文件状态:
    const stat = fileio.statSync('internal://app/test.txt');
    console.log('File size:', stat.size);
    

3. 错误排查

  • 对于文件不存在错误,先使用fileio.access检查路径是否存在
  • 对于权限错误,确认module.json5中已正确声明权限
  • 对于路径错误,使用fileio.statSync检查路径是否有效
  • 使用fileio.mkdirrecursive参数确保目录存在

4. 跨设备同步

  • 使用@ohos.distributedDataManager实现跨设备文件同步
  • 适合需要在多设备间同步文件的应用场景
  • 通过DistributedDataManagerputget方法实现数据同步

五、最佳实践总结

  1. 优先使用应用私有目录internal://app/路径不需要额外权限,安全性更高
  2. 正确声明权限:在module.json5中声明READ_USER_STORAGEWRITE_USER_STORAGE
  3. 确保资源释放:始终关闭文件描述符,使用try...finally确保资源释放
  4. 处理常见错误:针对13900012、13900013等常见错误码制定处理策略
  5. 优化大文件操作:对于大文件使用分块读写和异步处理
  6. 安全存储敏感数据:对敏感数据进行加密存储,避免明文存储
  7. 测试不同设备:确保文件操作在不同设备类型(手机、平板、手表)上正常工作
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐