Appearance
文件存储
鸿蒙文件存储 API:内部/外部存储、rawfile vs resource、沙箱机制。
1. 存储目录结构
应用沙箱(Sandbox)
├── /data/storage/el2/base/com.example.app/
│ ├── files/ # 应用私有文件
│ ├── cache/ # 缓存目录
│ ├── rdb/ # 数据库文件
│ └── preferences/ # Preferences 文件
│
外部存储(公共目录)
├── /storage/media/0/
│ ├── Documents/
│ ├── Download/
│ ├── Pictures/
│ ├── DCIM/(相机)
│ └── Music/2. 内部存储
2.1 读取内部文件
typescript
import fs from '@ohos.file.fs';
// 获取内部文件目录
let filesDir = context.filesDir; // /data/storage/el2/base/com.example.app/files
let cacheDir = context.cacheDir; // /data/storage/el2/base/com.example.app/cache
// 写文件
let fileStr = fs.openSync('test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let msg = 'Hello HarmonyOS';
fs.writeSync(fileStr, new TextEncoder().encode(msg));
fs.closeSync(fileStr);
// 读文件
let fileStr2 = fs.openSync('test.txt', fs.OpenMode.READ_ONLY);
let fileStat = fs.lstatSync(fileStr2);
let buffer = new Uint8Array(fileStat.size);
fs.readSync(fileStr2, buffer, { buffer });
let content = new TextDecoder().decode(buffer);
fs.closeSync(fileStr2);2.2 目录操作
typescript
// 获取应用目录
let appDir = context.filesDir;
let cacheDir = context.cacheDir;
// 创建子目录
fs.mkdirSync(`${appDir}/subdir`);
// 列出目录内容
let files = fs.readdirSync(appDir);
for (let file of files) {
console.log('文件:', file);
}
// 删除文件
fs.unlinkSync(`${appDir}/test.txt`);
// 删除目录
fs.rmdirSync(`${appDir}/subdir`);3. rawfile vs resource
| 维度 | rawfile | resource |
|---|---|---|
| 访问方式 | 文件名字符串 | $r 引用 |
| 编译 | 原始文件,不编译 | 编译后的资源 |
| 多语言 | ❌ 不支持 | ✅ 自动适配 |
| 多设备 | ❌ 不支持 | ✅ 自动适配 |
| 推荐 | 大文件/二进制 | 图片/字符串/配置 |
typescript
// rawfile(原始文件)
let fd = fs.openSync('rawfile://config.json', fs.OpenMode.READ_ONLY);
let content = fs.readSync(fd, fs.readFileStatSync(fd).size);
fs.closeSync(fd);
let data = JSON.parse(new TextDecoder().decode(content));
// resource(编译资源,推荐)
let str = $r('app.string.hello');
let img = $r('app.media.icon');4. 文件 URI
4.1 获取相册图片 URI
typescript
// 使用 PhotoViewPicker 选择图片
import photoView from '@ohos.multimedia.photoView';
let picker = new photoView.PhotoViewPicker();
let viewList = picker.select({
maxSelectCount: 1,
mimeType: photoView.PhotoViewMimeType.JPEG
});
// URI 转 File
let uri = viewList[0].uri;
let fileFd = fs.openSync(uri, fs.OpenMode.READ_ONLY);4.2 URI 注意事项
⚠️ 用户文件 URI 是临时的!
├─ 需要长期访问 → 复制到应用沙箱
├─ 不能直接当文件路径用
└─ 用完及时关闭 FileDescriptor5. 外部存储
5.1 请求存储权限
json5
// module.json5
"reqPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohap.permission.READ_MEDIA"
}
]5.2 访问公共目录
typescript
import mediaLibrary from '@ohos.multimedia.mediaLibrary';
// 获取媒体库
let context = getContext(this);
let mediaSel = new mediaLibrary.MediaSession();
let photos = mediaSel.getPhotos();
// 遍历照片
let iter = photos.getPhotoIterator();
while (iter.hasNext()) {
let photo = iter.next();
console.log('照片 URI:', photo.uri);
}6. 面试高频考点
Q1: rawfile 和 resource 的区别?
回答:rawfile 是原始文件,需手动读流;resource 是编译后的资源,通过 $r 引用,支持多语言/多设备自动适配。
Q2: 用户文件 URI 注意事项?
回答:URI 是临时的,需要长期访问时复制到应用沙箱,不能直接当文件路径使用。
🐱 小猫提示:文件存储记住 "rawfile 原始文件、resource 编译资源、URI 临时、复制沙箱长期用"。