# 12.1:文件操作

ArkUI开发框架在 @ohos.ability.featureAbility 模块里提供了获取当前 Ability 上下文 Context 的 API,然后通过 Context 获取文件目录。在 @ohos.fileio 模块里提供了相关API对文件的读写操作,本节笔者简单介绍一下 OpenHarmony 应用安装后的文件沙盒目录获取方式以及文件的基本读写操作。

# 12.1.1:获取APP目录

OpenHarmony 应用安装后,系统会根据应用的 bundleName 创建相应的沙盒目录,APP的数据可以存储在该目录下,获取该目录需要借助 @ohos.ability.featureAbility 模块里的API获取当前 Ability 的上下文 Context,然后调用 ContextgetXXXDir() 方法获取相关目录,源码如下所示:

// featureAbility库提供的API
declare namespace featureAbility {
  function getContext(): Context;
}

// Context提供的API
export interface Context extends BaseContext {
  getFilesDir(callback: AsyncCallback<string>): void;
  getCacheDir(callback: AsyncCallback<string>): void;
  getExternalCacheDir(callback: AsyncCallback<string>): void;
  getOrCreateLocalDir(callback: AsyncCallback<string>): void;
  getOrCreateDistributedDir(callback: AsyncCallback<string>): void;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
  • getContext:获取当前 Ability 的上下文对象。
  • getFilesDir:表示 APP 内部存储目录,可读写,随 APP 卸载时删除。
  • getCacheDir:表示 APP 内部存储的缓存目录,可读写,但是随时可能被清楚,不保证持久性,一般用作下载临时目录或者缓存目录。

简单样例如下所示:

// 引入featureAbility库
import featureAbility from '@ohos.ability.featureAbility';

@Entry @Component struct Index {

  build() {
    Column({space: 10}) {
      Button('获取根目录')
        .onClick(() => {
          featureAbility.getContext().getFilesDir((error, path) => {
            console.log("files dir: " + path)
          });
          featureAbility.getContext().getCacheDir((error, path) => {
            console.log("cache dir: " + path)
          });
        })
    }
    .padding(10)
    .size({width: "100%", height: '100%'})
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

输出日志如下所示:

cache dir: /data/data/com.example.myapplication/cache
files dir: /data/data/com.example.myapplication/files
1
2

# 12.1.2:打开文件操作

对文件读写操作的第一步是打开文件,因为 @ohos.fileio 模块里提供的 read()write() 方法需要传递一个文件描述符 fd ,所以先要调用 @ohos.fileio 模块里的 open() 方法打开文件:

declare function openSync(path: string, flags?: number, mode?: number): number;
1
  • path:待打开文件的绝对路径。

  • flags:打开文件的选项,必须指定如下选项中的一个,默认为 0o0

    • 0o0:只读打开。
    • 0o1:只写打开。
    • 0o2:读写打开。

    📢:同时,也可给定如下选项,以按位或的方式追加,默认不给定任何额外选项:

    • 0o100:若文件不存在,则创建文件。使用该选项时必须指定第三个参数 mode。
    • 0o200:如果追加了 0o100 选项,且文件已经存在,则出错。
    • 0o1000:如果文件存在且以只写或读写的方式打开文件,则将其长度裁剪为零。
    • 0o2000:以追加方式打开,后续写将追加到文件末尾。
    • 0o4000:如果path指向 FIFO 、块特殊文件或字符特殊文件,则本次打开及后续 IO 进行非阻塞操作。
    • 0o200000:如果path指向目录,则出错。
    • 0o400000:如果path指向符号链接,则出错。
    • 0o4010000:以同步IO的方式打开文件。
  • mode:若创建文件,则指定文件的权限,可给定如下权限,以按位或的方式追加权限,默认为0o666

    • 0o666:所有者具有读、写权限,所有用户组具有读、写权限,其余用户具有读、写权限。
    • 0o700:所有者具有读、写及可执行权限。
    • 0o400:所有者具有读权限。
    • 0o200:所有者具有写权限。
    • 0o100:所有者具有可执行权限。
    • 0o070:所有用户组具有读、写及可执行权限。
    • 0o040:所有用户组具有读权限。
    • 0o020:所有用户组具有写权限。
    • 0o010:所有用户组具有可执行权限。
    • 0o007:其余用户具有读、写及可执行权限。
    • 0o004:其余用户具有读权限。
    • 0o002:其余用户具有写权限。
    • 0o001:其余用户具有可执行权限。

简单样例如下所示:

private open(path: string) {
  // 注意:0o102是0o2 | 0o100的结果。
  let fd = fileio.openSync(path + "/" + this.fileName, 0o102, 0o666);
  console.log("open file result: " + fd);
}
1
2
3
4
5

# 12.1.3:写入文件操作

对文件进行写数据操作,调用 @ohos.fileio 模块里提供的 writeXXX()相关方法即可:

declare function write(fd: number, buffer: ArrayBuffer | string, callback: AsyncCallback<number>): void;
1
  • fd:文件描述符。
  • buffer:待写入内容。
  • callback:写入结果回调。

简单样例如下所示:

private write(path: string) {
  let fd = fileio.openSync(path + "/" + this.fileName, 0o102, 0o666);
  fileio.write(fd, "你好,OpenHarmony", (error, length) => {
    if(!error) {
      console.log("write success, write length: " + length);
    }
  })
}
1
2
3
4
5
6
7
8

日志打印如下所示:

app Log: files dir: /data/data/com.example.myapplication/files
app Log: write success, write length: 20
1
2

# 12.1.4:读取文件操作

文件读取操作同样是使用 @ohos.fileio 模块里的 readXXX() 方法,代码如下所示:

declare function read(fd: number, buffer: ArrayBuffer, callback: AsyncCallback<ReadOut>): void;
1
  • fd:文件描述符。
  • buffer:缓存数组。
  • callback:读取结果回调。

简单样例如下所示:

private read(path: string) {
  let fd = fileio.openSync(path + "/" + this.fileName, 0o102, 0o666);
  let buffer = new ArrayBuffer(4096);
  fileio.read(fd, buffer, (error, data) => {
    if(!error) {
      let s = String.fromCodePoint.apply(null, new Uint8Array(data.buffer));
      console.log("" + s);
      let d = decodeURIComponent(escape(s));
      console.log("read success, read content: " + d);
    }
  })
}
1
2
3
4
5
6
7
8
9
10
11
12

日志打印如下所示:

app Log: files dir: /data/data/com.example.myapplication/files // 路径
app Log: ä½ å¥½ï¼ŒOpenHarmony                                 // 乱码
app Log: read success, read content: 你好,OpenHarmony          // 正常
1
2
3

📢:文件读取的时候,如果内容有中文,需要进行特殊处理,否则会有乱码。

# 12.1.5:文件拷贝操作

# 12.1.6:压缩解压缩操作

@ohos.zlib 模块提供了对文件的压缩和解压缩操作,需要对文件进行压缩或者解压缩的时候,直接调用该模块的相关 API 即可。

declare namespace zlib {
  // 压缩文件
  function zipFile(inFile:string, outFile:string, options: Options): Promise<void>;
  // 解压文件
  function unzipFile(inFile:string, outFile:string, options: Options): Promise<void>;
  
  // 省略部分API
  
}
1
2
3
4
5
6
7
8
9
  • 压缩文件

    function zipFile(inFile:string, outFile:string, options: Options): Promise<void>;
    
    1
    • inFile:需要压缩的文件。
    • outFile:压缩到指定的zip文件。
    • option:压缩的相关参数。

    简单样例如下所示:

    private zip(path: string) {
      let inFile = path + "/" + this.fileName;
      let outFile = path + "/test.zip";
      zlib.zlib.zipFile(inFile, outFile, {})
        .then((result) => {
          console.log(JSON.stringify(result));
        })
        .catch((error) => {
          console.log(JSON.stringify(error));
        })
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  • 解压缩文件

    function unzipFile(inFile:string, outFile:string, options: Options): Promise<void>;
    
    1
    • inFile:需要解压缩的文件。
    • outFile:解压缩到目的目录。
    • option:解压缩的相关参数。

    简单样例如下所示:

    private unzip(path: string) {
      let inFile = path + "/test.zip";
      let outFile = path;
      zlib.zlib.unzipFile(inFile, outFile, {})
        .then((result) => {
          console.log(JSON.stringify(result));
        })
        .catch((error) => {
          console.log(JSON.stringify(error));
        })
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

# 12.1.7:完整样例代码

文件进行读写操作的完整代码如下所示:

import featureAbility from '@ohos.ability.featureAbility';
import fileio from '@ohos.fileio';
import zlib from '@ohos.zlib';

@Entry @Component struct Index {

  private fileName = "test.txt";

  private rootDir: string = null;

  build() {
    Column({space: 10}) {
      Button('获取根目录')
        .onClick(() => {
          featureAbility.getContext().getFilesDir((error, path) => {
            console.log("files dir: " + path)
            this.rootDir = path;
          });
          featureAbility.getContext().getCacheDir((error, path) => {
            console.log("cache dir: " + path)
          });
        })

      Button('打开文件')
        .onClick(() => {
          if(this.rootDir) {
            this.open(this.rootDir);
          }
        })
      Button('写入文件')
        .onClick(() => {
          if(this.rootDir) {
            this.write(this.rootDir);
          }
        })

      Button('读取文件')
        .onClick(() => {
          if(this.rootDir) {
            this.read(this.rootDir);
          }
        })
      Button('关闭文件')
        .onClick(() => {
          if(this.rootDir) {
            this.close(this.rootDir);
          }
        })
      Button('压缩文件')
        .onClick(() => {
          if(this.rootDir) {
            this.zip(this.rootDir);
          }
        })
      Button('解压缩文件')
        .onClick(() => {
          if(this.rootDir) {
            this.unzip(this.rootDir);
          }
        })
    }
    .padding(10)
    .size({width: "100%", height: '100%'})
  }

  private unzip(path: string) {
    let inFile = path + "/test.zip";
    let outFile = path;
    zlib.zlib.unzipFile(inFile, outFile, {})
      .then((result) => {
        console.log(JSON.stringify(result));
      })
      .catch((error) => {
        console.log(JSON.stringify(error));
      })
  }

  private zip(path: string) {
    let inFile = path + "/" + this.fileName;
    let outFile = path + "/test.zip";
    zlib.zlib.zipFile(inFile, outFile, {})
      .then((result) => {
        console.log(JSON.stringify(result));
      })
      .catch((error) => {
        console.log(JSON.stringify(error));
      })
  }

  private close(path: string) {
    let fd = fileio.openSync(path + "/" + this.fileName, 0o102, 0o666);
    fileio.closeSync(fd);
  }

  private open(path: string) {
    let fd = fileio.openSync(path + "/" + this.fileName, 0o102, 0o666);
    console.log("open file result: " + fd);
  }

  private read(path: string) {
    let fd = fileio.openSync(path + "/" + this.fileName, 0o102, 0o666);
    let buffer = new ArrayBuffer(4096);
    fileio.read(fd, buffer, (error, data) => {
      if(!error) {
        let s = String.fromCodePoint.apply(null, new Uint8Array(data.buffer));
        console.log("" + s);
        let d = decodeURIComponent(escape(s));
        console.log("read success, read content: " + d);
      }
    })
  }

  private write(path: string) {
    let fd = fileio.openSync(path + "/" + this.fileName, 0o102, 0o666);
    fileio.write(fd, "你好,OpenHarmony", (error, length) => {
      if(!error) {
        console.log("write success, write length: " + length);
      }
    })
  }
}
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

# 12.1.8:小结

本节简单介绍了 OpenHarmony 应用的目录获取和文件读写操作,有关 @ohos.fileio 模块里更多 API 的用法,读者自行查看一下源码,笔者就不多多介绍了。

(adsbygoogle = window.adsbygoogle || []).push({});
请作者喝杯咖啡

津公网安备 12011402001367号

津ICP备2020008934号-2