1.问题描述:

开发调试阶段经常需要在沙箱路径下构造测试文件,然后使用fs进行文件操作,有什么方法可快速在沙箱路径下构造文件吗?

解决方案:

开发者可以手动在\resource路径下创建resfile目录,支持创建多层子目录,子目录名称可以自定义,文件夹内可以自由放置各类资源文件。
目录中的资源文件会被直接打包进应用,不经过编译,也不会分配资源ID。应用安装后,resfile资源会被解压到应用沙箱路径,通过Context属性resourceDir获取到resfile资源目录后,可通过文件路径访问,且该路径仅能以只读方式访问。

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/resource-categories-and-access#%E8%B5%84%E6%BA%90%E5%88%86%E7%B1%BB

https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-inner-application-context#%E5%B1%9E%E6%80%A7

2.问题描述:

如何在用picker选择整个文件夹的文件?

解决方案:

对于PC/2in1/TV设备可以通过DocumentSelectMode设置文件夹模式,选择整个文件夹;对于非PC/2in1/TV设备当前只能通过用户进行批量选择文件。

3.问题描述:

如何通过DocumentViewPicker保存文件夹?

解决方案:

1.DocumentViewPicke.save只能保存文件,不支持保存文件夹。

2.可以使用DocumentViewPicke.select保存文件夹,设置documentSelectOptions.selectMode = picker.DocumentSelectMode.FOLDER,拉起FilePicker应用界面后选择需要保存的公共目录,然后应用在公共目录中创建需要保存的文件夹即可。示例代码如下:

import { common } from '@kit.AbilityKit';
import { fileIo as fs, fileUri, picker } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct Index {
  context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  @State fileName: string = 'startIcon.png';

  saveFileToSandbox(fileName: string) {
    const filePath = this.context.cacheDir + '/' + fileName;
    const file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
    const content = this.context.resourceManager.getRawFileContentSync(fileName);
    const arrayBuffer = content.buffer.slice(0);
    fs.writeSync(file.fd, arrayBuffer);
    fs.closeSync(file.fd);
  }

  build() {
    Column({ space: 20 }) {
      Button('在公共目录下保存test文件夹,并将rawfile中的文件保存到test文件夹中')
        .onClick(() => {
          this.saveFileToSandbox(this.fileName);
          const documentSelectOptions = new picker.DocumentSelectOptions();

          let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
          documentSelectOptions.selectMode = picker.DocumentSelectMode.FOLDER;
          // 创建文件选择器实例
          const documentViewPicker = new picker.DocumentViewPicker(context);
          documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) =&gt; {
            let folder = documentSelectResult[0] + '/test';
            folder = new fileUri.FileUri(folder).path;
            console.info(folder);
            fs.mkdirSync(folder);
            let fileDir = context.filesDir;
            let filePath = fileDir + '/' + this.fileName;
            let sandboxFile = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
            let copyFilePath = folder + '/' + this.fileName;
            let copyFile = fs.openSync(copyFilePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
            fs.copyFileSync(sandboxFile.fd, copyFile.fd);
            fs.close(sandboxFile);
            fs.close(copyFile);
          }).catch((err: BusinessError) =&gt; {
            console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
          });
        });
    }
    .height('100%')
    .width('100%');
  }
}
4.问题描述:

如何找到应用数据对应的路径?

解决方案:

应用沙箱路径和真实物理路径的对应关系:在应用沙箱路径下读写文件,经过映射转换,实际读写的是真实物理路径中的应用文件。
沙箱路径/data/storage/el2/base/files/映射到物理路径:/data/app/el2/[用户ID]/base/[包名]/files/,直接通过访问applicationContext下的filesDir。

5.问题描述:

使用readTextSync读取186M大文件,会直接出现crash。

解决方案

如果读取的是内容比较多的文本文件,可以使用fs.readLines逐行读取的方式(只支持读取UTF-8文本文件),fs.readLines类似于fs.readText,但是一次只读取文本文件当中的一行,适合处理大文本文件。或者采用fs.read设置缓冲缓冲区,循环读取,逐步拼接成完成内容,代码案例参考如下:

import fs from '@ohos.file.fs';
import { common } from '@kit.AbilityKit';
import { buffer } from '@kit.ArkTS';

@Entry
@Component
struct Index {
  build() {
    Column() {
      Button('fs.readLine')
        .onClick(() =&gt; {
          let context = this.getUIContext().getHostContext() as common.UIAbilityContext
          let filePath = context.filesDir + '/test.txt'
          let readerIterator = fs.readLinesSync(filePath);
          for (let it = readerIterator.next();!it.done; it = readerIterator.next()) {
            console.info('content: ' + it.value);
          }
        })

      Button('fs.read')
        .onClick(() =&gt; {
          let context = this.getUIContext().getHostContext() as common.UIAbilityContext
          let filePath = context.filesDir + '/test.txt'
          let file = fs.openSync(filePath, fs.OpenMode.READ_ONLY)
          let arrayBuffer = new ArrayBuffer(1024);
          let content = '';
          let readLen = 0;
          do {
            readLen = fs.readSync(file.fd, arrayBuffer);
            content += buffer.from(arrayBuffer, 0, readLen).toString();
          } while (readLen &gt; 0);
          console.info(content)
        })
    }
  }
}

Logo

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

更多推荐