From 560adc4574c278247fcea306f5971851558e9905 Mon Sep 17 00:00:00 2001 From: zhoulisheng <635547767@qq.com> Date: Thu, 14 Jul 2022 22:58:53 -0700 Subject: [PATCH] 1.use disklrucache module intead by DiskLruCache.ets Signed-off-by: zhoulisheng <635547767@qq.com> --- disklrucache/.gitignore | 3 + disklrucache/build-profile.json5 | 5 + disklrucache/hvigorfile.js | 3 + .../app.ets => disklrucache/index.ets | 25 +- disklrucache/package.json | 18 + .../ets/components/disklrucache/CustomMap.ts | 115 +++++ .../components/disklrucache/DiskCacheEntry.ts | 47 +- .../components/disklrucache/DiskLruCache.ts | 444 ++++++++++++++++++ .../ets/components/disklrucache/FileReader.ts | 83 ++++ .../ets/components/disklrucache/FileUtils.ts | 240 ++++++++++ disklrucache/src/main/module.json5 | 11 + .../main/resources/base/element/string.json | 8 + 12 files changed, 961 insertions(+), 41 deletions(-) create mode 100644 disklrucache/.gitignore create mode 100644 disklrucache/build-profile.json5 create mode 100644 disklrucache/hvigorfile.js rename entry/src/main/ets/MainAbility/app.ets => disklrucache/index.ets (51%) create mode 100644 disklrucache/package.json create mode 100644 disklrucache/src/main/ets/components/disklrucache/CustomMap.ts rename imageknife/src/main/ets/components/cache/DiskCacheEntry.ets => disklrucache/src/main/ets/components/disklrucache/DiskCacheEntry.ts (56%) create mode 100644 disklrucache/src/main/ets/components/disklrucache/DiskLruCache.ts create mode 100644 disklrucache/src/main/ets/components/disklrucache/FileReader.ts create mode 100644 disklrucache/src/main/ets/components/disklrucache/FileUtils.ts create mode 100644 disklrucache/src/main/module.json5 create mode 100644 disklrucache/src/main/resources/base/element/string.json diff --git a/disklrucache/.gitignore b/disklrucache/.gitignore new file mode 100644 index 0000000..4f9a973 --- /dev/null +++ b/disklrucache/.gitignore @@ -0,0 +1,3 @@ +/node_modules +/.preview +/build \ No newline at end of file diff --git a/disklrucache/build-profile.json5 b/disklrucache/build-profile.json5 new file mode 100644 index 0000000..35dff6d --- /dev/null +++ b/disklrucache/build-profile.json5 @@ -0,0 +1,5 @@ +{ + "apiType": "stageMode", + "buildOption": { + } +} diff --git a/disklrucache/hvigorfile.js b/disklrucache/hvigorfile.js new file mode 100644 index 0000000..42ed4b4 --- /dev/null +++ b/disklrucache/hvigorfile.js @@ -0,0 +1,3 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').harTasks + diff --git a/entry/src/main/ets/MainAbility/app.ets b/disklrucache/index.ets similarity index 51% rename from entry/src/main/ets/MainAbility/app.ets rename to disklrucache/index.ets index b2d066b..d2d2c2f 100644 --- a/entry/src/main/ets/MainAbility/app.ets +++ b/disklrucache/index.ets @@ -1,29 +1,20 @@ /* * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http:// www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ -import app from '@system.app'; -import {ImageKnife} from '@ohos/imageknife' - -export default { - data: { - imageKnife: {} // ImageKnife - }, - onCreate() { - this.data.imageKnife = ImageKnife.with(); - }, - onDestroy() { - - }, -} +/** + * disklrucache + */ +export * from './src/main/ets/components/disklrucache/DiskLruCache' +export * from './src/main/ets/components/disklrucache/DiskCacheEntry' diff --git a/disklrucache/package.json b/disklrucache/package.json new file mode 100644 index 0000000..492598e --- /dev/null +++ b/disklrucache/package.json @@ -0,0 +1,18 @@ +{ + "license":"ISC", + "types":"", + "devDependencies":{ + "@types/spark-md5":"^3.0.2" + }, + "name":"@ohos/disklrucache", + "description":"a npm package which contains arkUI2.0 page", + "ohos":{ + "org":"" + }, + "main":"index.ets", + "repository":{}, + "version":"1.0.0", + "dependencies":{ + "spark-md5":"^3.0.2" + } +} \ No newline at end of file diff --git a/disklrucache/src/main/ets/components/disklrucache/CustomMap.ts b/disklrucache/src/main/ets/components/disklrucache/CustomMap.ts new file mode 100644 index 0000000..6e8b05a --- /dev/null +++ b/disklrucache/src/main/ets/components/disklrucache/CustomMap.ts @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http:// www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export class CustomMap { + map: Map = new Map() + + /** + * 获取键对应的值 + * + * @param key 键值 + */ + get(key: K): V | undefined { + if (key == null) { + throw new Error('key is null,checking the parameter'); + } + return this.map.get(key) + } + + /** + * 是否含有key的缓存 + * + * @param key 键值 + */ + hasKey(key: K) { + if (key == null) { + throw new Error('key is null,checking the parameter'); + } + return this.map.has(key) + } + + /** + * 添加键值对 + * + * @param key 键值 + * @param value 键对应的值 + */ + put(key: K, value: V): V | undefined { + if (key == null || value == null) { + throw new Error('key or value is invalid,checking the parameter'); + } + let pre = this.map.get(key) + if (this.hasKey(key)) { + this.map.delete(key) + } + this.map.set(key, value); + return pre + } + + /** + * 去除键值,(去除键数据中的键名及对应的值) + * + * @param key 键值 + */ + remove(key: K): boolean { + if (key == null) { + throw new Error('key is null,checking the parameter'); + } + return this.map.delete(key) + } + + /** + * 获取最先存储的数据的key + */ + getFirstKey(): K { // keys()可以遍历后需要优化put()方法,暂时仅获取index=0的key + return this.map.keys().next().value + } + + /** + * 判断键值元素是否为空 + */ + isEmpty(): boolean { + return this.map.size == 0; + } + + /** + * 获取键值元素大小 + */ + size(): number { + return this.map.size; + } + + /** + * 遍历Map,执行处理函数. 回调函数 function(key,value,index){..} + * + * @param fn 遍历回调方法 + */ + each(fn) { + this.map.forEach(fn) + } + + /** + * 清除键值对 + */ + clear() { + this.map.clear() + } + + /** + * 遍历key + */ + keys(): IterableIterator { + return this.map.keys() + } +} \ No newline at end of file diff --git a/imageknife/src/main/ets/components/cache/DiskCacheEntry.ets b/disklrucache/src/main/ets/components/disklrucache/DiskCacheEntry.ts similarity index 56% rename from imageknife/src/main/ets/components/cache/DiskCacheEntry.ets rename to disklrucache/src/main/ets/components/disklrucache/DiskCacheEntry.ts index ece37d8..ad2625d 100644 --- a/imageknife/src/main/ets/components/cache/DiskCacheEntry.ets +++ b/disklrucache/src/main/ets/components/disklrucache/DiskCacheEntry.ts @@ -13,35 +13,34 @@ * limitations under the License. */ export class DiskCacheEntry { + // 缓存的key + key: string = '' - // 缓存的key - key: string= '' + // 缓存文件大小 + length: number = 0 - // 缓存文件大小 - length: number= 0 + constructor(key: string, length?: number) { + this.key = key + this.length = length + } - constructor(key: string, length?: number) { - this.key = key - this.length = length - } + setKey(key: string) { + this.key = key + } - setKey(key: string) { - this.key = key - } + getKey(): string { + return this.key + } - getkey(): string{ - return this.key - } + setLength(length: number) { + this.length = length + } - setLength(length: number) { - this.length = length - } + getLength(): number { + return this.length + } - getLength(): number{ - return this.length - } - - toString(): string{ - return this.key + ' - ' + this.length - } + toString(): string { + return this.key + ' - ' + this.length + } } \ No newline at end of file diff --git a/disklrucache/src/main/ets/components/disklrucache/DiskLruCache.ts b/disklrucache/src/main/ets/components/disklrucache/DiskLruCache.ts new file mode 100644 index 0000000..f36800c --- /dev/null +++ b/disklrucache/src/main/ets/components/disklrucache/DiskLruCache.ts @@ -0,0 +1,444 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import fileio from '@ohos.fileio' +import { CustomMap } from './CustomMap' +import { FileUtils } from './FileUtils' +import { FileReader } from './FileReader' +import { DiskCacheEntry } from './DiskCacheEntry' +import SparkMD5 from "spark-md5" + + +export class DiskLruCache { + // 默认缓存数据最大值 + private static readonly DEFAULT_MAX_SIZE: number = 30 * 1024 * 1024 + + // 缓存journal文件名称 + private static readonly journal: string = 'journal' + + // 缓存journal备份文件名称 + private static readonly journalTemp: string = 'journal_temp' + + // 备份文件save标识符 + private static readonly SAVE: string = 'save' + + // 备份文件read标识符 + private static readonly READ: string = 'read' + + // 备份文件remove标识符 + private static readonly REMOVE: string = 'remove' + + // 缓存文件路径地址 + private path: string = '' + + // 缓存journal文件路径 + private journalPath: string = '' + + // 缓存journal备份文件路径 + private journalPathTemp: string = '' + + // 缓存数据最大值 + private maxSize: number = DiskLruCache.DEFAULT_MAX_SIZE + + // 当前缓存数据值 + private size: number = 0 + + // 缓存数据集合 + private cacheMap: CustomMap = new CustomMap() + + private constructor(path: string, maxSize: number) { + this.path = path + this.maxSize = maxSize + this.journalPath = path + DiskLruCache.journal + this.journalPathTemp = path + DiskLruCache.journalTemp + } + + /** + * 打开path中的缓存,如果不存在缓存,则创建新缓存 + * + * @param path 缓存文件路径地址 + * @param maxSize 缓存数据最大值,默认值为3M + */ + public static create(path: string, maxSize?: number): DiskLruCache { + if (!!!path) { + throw new Error('DiskLruCache create path is empty, checking the parameter'); + } + if (!!!maxSize) { + maxSize = DiskLruCache.DEFAULT_MAX_SIZE + } + if (maxSize <= 0) { + throw new Error("DiskLruCache create maxSize <= 0, checking the parameter"); + } + if (!FileUtils.getInstance().existFolder(path)) { + FileUtils.getInstance().createFolder(path, true) + } + if (path.endsWith(FileUtils.SEPARATOR)) { + path = path + } else { + path = path + FileUtils.SEPARATOR + } + let journalPath = path + DiskLruCache.journal + let journalPathTemp = path + DiskLruCache.journalTemp + + // 判断日志文件是否存在,如果没有初始化创建 + if (FileUtils.getInstance().exist(journalPath)) { + let stat = fileio.statSync(journalPath) + if (stat.size > 0) { + FileUtils.getInstance().createFile(journalPathTemp) + FileUtils.getInstance().copyFile(journalPath, journalPathTemp) + let diskLruCache: DiskLruCache = new DiskLruCache(path, maxSize) + diskLruCache.readJournal(journalPathTemp) + diskLruCache.resetJournalFile() + return diskLruCache + } else { + return new DiskLruCache(path, maxSize) + } + } else { + FileUtils.getInstance().createFile(journalPath) + return new DiskLruCache(path, maxSize) + } + } + + /** + * 处理journal文件数据 + * + * @param line 日志行字符串 + */ + private dealWithJournal(line: string) { + let filePath = '' + try { + let lineData = line.split(' ') + if (lineData.length > 1) { + if (lineData[0] != DiskLruCache.REMOVE) { + filePath = this.path + lineData[1] + let fileStat = fileio.statSync(filePath) + if (fileStat.isFile() && fileStat.size > 0) { + this.size = this.size + fileStat.size + FileUtils.getInstance().writeData(this.journalPath, line + FileReader.LF) + this.putCacheMap(lineData[1], fileStat.size) + } + } else { + if (this.cacheMap.hasKey(lineData[1])) { + let cacheEntry: DiskCacheEntry = this.cacheMap.get(lineData[1]) + this.size = this.size - cacheEntry.getLength() + this.cacheMap.remove(lineData[1]) + } + } + } + } catch (e) { + console.error('DiskLruCache - dealWithJournal e ' + e) + } + } + + /** + * 设置disk缓存最大数据值 + * + * @param max 缓存数据最大值 + */ + setMaxSize(max: number) { + this.maxSize = max + this.trimToSize() + } + + /** + * 存储disk缓存数据 + * + * @param key 键值 + * @param content 文件内容 + */ + set(key: string, content: ArrayBuffer) { + if (!!!key) { + throw new Error('key is null, checking the parameter') + } + if (content == null || content.byteLength == 0) { + throw new Error('content is null, checking the parameter') + } + let fileSize = content.byteLength + key = SparkMD5.hash(key) + this.size = this.size + fileSize + this.putCacheMap(key, fileSize) + FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.SAVE + ' ' + key + FileReader.LF) + this.trimToSize() + let tempPath = this.path + key + FileUtils.getInstance().writeNewFile(tempPath, content) + } + + /** + * 异步存储disk缓存数据 + * + * @param key 键值 + * @param content 文件内容 + */ + async setAsync(key: string, content: ArrayBuffer): Promise { + if (!!!key) { + throw new Error('key is null, checking the parameter') + } + if (content == null || content.byteLength == 0) { + throw new Error('content is null, checking the parameter') + } + let fileSize = content.byteLength + key = SparkMD5.hash(key) + this.size = this.size + fileSize + console.log('setAsync fileSize ='+ fileSize +' all size ='+this.size + ' max size ='+this.maxSize); + this.putCacheMap(key, fileSize) + await FileUtils.getInstance().writeDataAsync(this.journalPath, DiskLruCache.SAVE + ' ' + key + FileReader.LF) + this.trimToSize() + let tempPath = this.path + key + await FileUtils.getInstance().writeNewFileAsync(tempPath, content) + } + + /** + * 存储disk缓存数据 + * + * @param key key 键值 + * @param path 文件路径 + */ + setFileByPath(key: string, path: string) { + if (!!!key) { + throw new Error('key is null, checking the parameter') + } + if (!!!path || !FileUtils.getInstance().exist(path)) { + throw new Error('path is null or no exist file, checking the parameter') + } + let fileSize = FileUtils.getInstance().getFileSize(path) + if (fileSize == -1) { + throw new Error('path getFileSize error ') + } + key = SparkMD5.hash(key) + this.size = this.size + fileSize + this.putCacheMap(key, fileSize) + FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.SAVE + ' ' + key + FileReader.LF) + this.trimToSize() + fileSize = FileUtils.getInstance().getFileSize(path) + FileUtils.getInstance().copyFile(path, this.path + key) + } + + /** + * 异步存储disk缓存数据 + * + * @param key key 键值 + * @param path 文件路径 + */ + async setFileByPathAsync(key: string, path: string): Promise { + if (!!!key) { + throw new Error('key is null, checking the parameter') + } + if (!!!path || !FileUtils.getInstance().exist(path)) { + throw new Error('path is null or no exist file, checking the parameter') + } + let fileSize = FileUtils.getInstance().getFileSize(path) + if (fileSize == -1) { + throw new Error('path getFileSize error ') + } + key = SparkMD5.hash(key) + this.size = this.size + fileSize + this.putCacheMap(key, fileSize) + await FileUtils.getInstance().writeDataAsync(this.journalPath, DiskLruCache.SAVE + ' ' + key + FileReader.LF) + this.trimToSize() + fileSize = FileUtils.getInstance().getFileSize(path) + await FileUtils.getInstance().copyFileAsync(path, this.path + key) + } + + /** + * 获取key缓存数据 + * + * @param key key 键值 + */ + get(key: string): ArrayBuffer { + if (!!!key) { + throw new Error('key is null,checking the parameter'); + } + key = SparkMD5.hash(key) + let path = this.path + key; + if (FileUtils.getInstance().exist(path)) { + let ab: ArrayBuffer = FileUtils.getInstance().readFile(path) + this.putCacheMap(key, ab.byteLength) + FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.READ + ' ' + key + FileReader.LF) + return ab + } else { + return null; + } + } + + /** + * 异步获取key缓存数据 + * + * @param key 键值 + */ + async getAsync(key: string): Promise { + if (!!!key) { + throw new Error('key is null,checking the parameter'); + } + key = SparkMD5.hash(key) + let path = this.path + key; + if (FileUtils.getInstance().exist(path)) { + let ab: ArrayBuffer = await FileUtils.getInstance().readFileAsync(path) + this.putCacheMap(key, ab.byteLength) + await FileUtils.getInstance().writeDataAsync(this.journalPath, DiskLruCache.READ + ' ' + key + FileReader.LF) + return ab + } else { + return null; + } + } + + /** + * 获取key缓存数据绝对路径 + * + * @param key 键值 + */ + getFileToPath(key: string): string { + if (!!!key) { + throw new Error('key is null,checking the parameter'); + } + key = SparkMD5.hash(key); + let path = this.path + key; + if (FileUtils.getInstance().exist(path)) { + FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.READ + ' ' + key + FileReader.LF); + return path + } else { + return null + } + } + + /** + * 异步获取key缓存数据绝对路径 + * + * @param key 键值 + */ + async getFileToPathAsync(key: string): Promise { + if (!!!key) { + throw new Error('key is null,checking the parameter'); + } + key = SparkMD5.hash(key); + let path = this.path + key; + if (FileUtils.getInstance().exist(path)) { + await FileUtils.getInstance().writeDataAsync(this.journalPath, DiskLruCache.READ + ' ' + key + FileReader.LF); + return path + } else { + return null + } + } + + /** + * 删除key缓存数据 + * + * @param key 键值 + */ + deleteCacheDataByKey(key: string): DiskCacheEntry { + if (!!!key) { + throw new Error('key is null,checking the parameter'); + } + key = SparkMD5.hash(key) + let path = this.path + key; + if (FileUtils.getInstance().exist(path)) { + let ab = FileUtils.getInstance().readFile(path) + this.size = this.size - ab.byteLength + this.cacheMap.remove(key) + FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.REMOVE + ' ' + key + FileReader.LF) + FileUtils.getInstance().deleteFile(path) + } + return this.cacheMap.get(key) + } + + /** + *遍历当前的磁盘缓存数据 + * + * @param fn 遍历后方法回调 + */ + foreachDiskLruCache(fn) { + this.cacheMap.each(fn) + } + + /** + * 清除所有disk缓存数据 + */ + cleanCacheData() { + this.cacheMap.each((value, key) => { + FileUtils.getInstance().deleteFile(this.path + key) + }) + FileUtils.getInstance().deleteFile(this.journalPath) + this.cacheMap.clear() + this.size = 0 + } + + /** + * 重置journal文件数据 + */ + private resetJournalFile() { + FileUtils.getInstance().clearFile(this.journalPath) + for (let key of this.cacheMap.keys()) { + FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.SAVE + ' ' + key + FileReader.LF) + } + } + + /** + * 读取journal文件的缓存数据 + * + * @param path 日志缓存文件路径地址 + */ + private readJournal(path: string) { + let fileReader = new FileReader(path) + let line: string = '' + while (!fileReader.isEnd()) { + line = fileReader.readLine() + line = line.replace(FileReader.LF, '').replace(FileReader.CR, '') + this.dealWithJournal(line) + } + fileReader.close() + FileUtils.getInstance().deleteFile(this.journalPathTemp) + this.trimToSize() + } + + /** + * 缓存数据map集合 + * + * @param key 键值 + * @param length 缓存文件大小 + */ + private putCacheMap(key: string, length?: number) { + if (length > 0) { + console.log('key = '+key) + console.log('value length= '+ length) + this.cacheMap.put(key, new DiskCacheEntry(key, length)) + } else { + this.cacheMap.put(key, new DiskCacheEntry(key)) + } + } + + /** + * 根据LRU算法删除多余缓存数据 + */ + private trimToSize() { + + while (this.size > this.maxSize) { + let tempKey: string = this.cacheMap.getFirstKey() + let fileSize = FileUtils.getInstance().getFileSize(this.path + tempKey) + if (fileSize > 0) { + this.size = this.size - fileSize + } + console.log('trimToSize fileSize ='+ fileSize +' all size ='+this.size + ' max size ='+this.maxSize); + FileUtils.getInstance().deleteFile(this.path + tempKey) + this.cacheMap.remove(tempKey) + FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.REMOVE + ' ' + tempKey + FileReader.LF) + } + } + + getPath(){ + return this.path; + } + + getCacheMap(){ + return this.cacheMap; + } +} \ No newline at end of file diff --git a/disklrucache/src/main/ets/components/disklrucache/FileReader.ts b/disklrucache/src/main/ets/components/disklrucache/FileReader.ts new file mode 100644 index 0000000..42b2ddf --- /dev/null +++ b/disklrucache/src/main/ets/components/disklrucache/FileReader.ts @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import fileio from '@ohos.fileio' + +export class FileReader { + // 换行符 + static readonly LF: string = '\n' + + // CR符 + static readonly CR: string = '\r' + + // 文件大小 + fileLength: number = 0 + + // 读取的长度 + length: number = 0 + + // 读写stream + stream: any = null + + // 缓存buf + buf: ArrayBuffer = new ArrayBuffer(1) + + /** + * 读取文件行 + * + * @param path 文件路径 + */ + constructor(path: string) { + if (!path || Object.keys(path).length == 0) { + return + } + try { + this.stream = fileio.createStreamSync(path, 'r+'); + let stat = fileio.statSync(path) + this.fileLength = stat.size + } catch (e) { + } + } + + /** + * 循环读取文件数据 + */ + readLine(): string { + let line = '' + while (this.length <= this.fileLength) { + this.stream.readSync(this.buf, { position: this.length }) + this.length++ + let temp = String.fromCharCode.apply(null, new Uint8Array(this.buf)); + line = line + temp + if (temp == FileReader.LF || temp == FileReader.CR) { + return line + } + } + return line + } + + /** + * 判断文件是否结束 + */ + isEnd() { + return this.fileLength <= 0 || this.length == this.fileLength + } + + /** + * 关闭stream + */ + close() { + this.stream.closeSync() + } +} \ No newline at end of file diff --git a/disklrucache/src/main/ets/components/disklrucache/FileUtils.ts b/disklrucache/src/main/ets/components/disklrucache/FileUtils.ts new file mode 100644 index 0000000..1038004 --- /dev/null +++ b/disklrucache/src/main/ets/components/disklrucache/FileUtils.ts @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import fileio from '@ohos.fileio' + +export class FileUtils { + private static sInstance: FileUtils + static readonly SEPARATOR: string = '/' + base64Str: string = '' + + /** + * 单例实现FileUtils类 + */ + public static getInstance(): FileUtils { + if (!this.sInstance) { + this.sInstance = new FileUtils(); + } + return this.sInstance; + } + + private constructor() { + } + + /** + * 新建文件 + * + * @param path 文件绝对路径及文件名 + * @return number 文件句柄id + */ + createFile(path: string): number { + return fileio.openSync(path, 0o100, 0o664) + } + + /** + * 删除文件 + * + * @param path 文件绝对路径及文件名 + */ + deleteFile(path: string): void { + fileio.unlinkSync(path); + } + + /** + * 拷贝文件 + * + * @param src 文件绝对路径及文件名 + * @param dest 拷贝到对应的路径 + */ + copyFile(src: string, dest: string) { + fileio.copyFileSync(src, dest); + } + + /** + * 异步拷贝文件 + * + * @param src 文件绝对路径及文件名 + * @param dest 拷贝到对应的路径 + */ + async copyFileAsync(src: string, dest: string): Promise { + await fileio.copyFile(src, dest); + } + + /** + * 清空已有文件数据 + * + * @param path 文件绝对路径 + */ + clearFile(path: string): number { + return fileio.openSync(path, 0o1000) + } + + /** + * 向path写入数据 + * + * @param path 文件绝对路径 + * @param content 文件内容 + */ + writeData(path: string, content: ArrayBuffer | string) { + let fd = fileio.openSync(path, 0o102, 0o664) + let stat = fileio.statSync(path) + fileio.writeSync(fd, content, { position: stat.size }) + fileio.closeSync(fd) + } + + /** + * 异步向path写入数据 + * + * @param path 文件绝对路径 + * @param content 文件内容 + */ + async writeDataAsync(path: string, content: ArrayBuffer | string): Promise { + let fd = await fileio.open(path, 0o102, 0o664) + let stat = await fileio.stat(path) + await fileio.write(fd, content, { position: stat.size }) + await fileio.close(fd) + } + + /** + * 判断path文件是否存在 + * + * @param path 文件绝对路径 + */ + exist(path: string): boolean { + try { + let stat = fileio.statSync(path) + return stat.isFile() + } catch (e) { + console.error("FileUtils exist e " + e) + return false + } + } + + /** + * 向path写入数据 + * + * @param path 文件绝对路径 + * @param data 文件内容 + */ + writeNewFile(path: string, data: ArrayBuffer) { + this.createFile(path) + this.writeFile(path, data) + } + + /** + * 向path写入数据 + * + * @param path 文件绝对路径 + * @param data 文件内容 + */ + async writeNewFileAsync(path: string, data: ArrayBuffer): Promise { + await fileio.open(path, 0o100, 0o664) + let fd = await fileio.open(path, 0o102, 0o664) + await fileio.ftruncate(fd) + await fileio.write(fd, data) + await fileio.fsync(fd) + await fileio.close(fd) + } + + /** + * 获取path的文件大小 + * + * @param path 文件绝对路径 + */ + getFileSize(path: string): number { + try { + let stat = fileio.statSync(path) + return stat.size + } catch (e) { + console.error("FileUtils getFileSize e " + e) + return -1 + } + } + + /** + * 读取路径path的文件 + * + * @param path 文件绝对路径 + */ + readFile(path: string): ArrayBuffer { + let fd = fileio.openSync(path, 0o2); + let length = fileio.statSync(path).size + let buf = new ArrayBuffer(length); + fileio.readSync(fd, buf) + return buf + } + + /** + * 读取路径path的文件 + * + * @param path 文件绝对路径 + */ + async readFileAsync(path: string): Promise { + let stat = await fileio.stat(path); + let fd = await fileio.open(path, 0o2); + let length = stat.size; + let buf = new ArrayBuffer(length); + await fileio.read(fd, buf); + return buf + } + + /** + * 创建文件夹 + * + * @param path 文件夹绝对路径,只有是权限范围内的路径,可以生成 + * @param recursive + */ + createFolder(path: string, recursive?: boolean) { + if (recursive) { + if (!this.existFolder(path)) { + let lastInterval = path.lastIndexOf(FileUtils.SEPARATOR) + if (lastInterval == 0) { + return + } + let newPath = path.substring(0, lastInterval) + this.createFolder(newPath, true) + if (!this.existFolder(path)) { + fileio.mkdirSync(path) + } + } + } else { + if (!this.existFolder(path)) { + fileio.mkdirSync(path) + } + } + } + + /** + * 判断文件夹是否存在 + * + * @param path 文件夹绝对路径 + */ + existFolder(path: string): boolean { + try { + let stat = fileio.statSync(path) + return stat.isDirectory() + } catch (e) { + console.error("FileUtils folder exist e " + e) + return false + } + } + + private writeFile(path: string, content: ArrayBuffer | string) { + let fd = fileio.openSync(path, 0o102, 0o664) + fileio.ftruncateSync(fd) + fileio.writeSync(fd, content) + fileio.fsyncSync(fd) + fileio.closeSync(fd) + } +} \ No newline at end of file diff --git a/disklrucache/src/main/module.json5 b/disklrucache/src/main/module.json5 new file mode 100644 index 0000000..f2c566d --- /dev/null +++ b/disklrucache/src/main/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "disklrucache", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ], + "uiSyntax": "ets" + } +} diff --git a/disklrucache/src/main/resources/base/element/string.json b/disklrucache/src/main/resources/base/element/string.json new file mode 100644 index 0000000..1e76de0 --- /dev/null +++ b/disklrucache/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +}