diff --git a/disklrucache/src/main/ets/components/disklrucache/CustomMap.ts b/disklrucache/src/main/ets/components/disklrucache/CustomMap.ts index 6e8b05a..5ed4253 100644 --- a/disklrucache/src/main/ets/components/disklrucache/CustomMap.ts +++ b/disklrucache/src/main/ets/components/disklrucache/CustomMap.ts @@ -1,18 +1,18 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the 'License'); + * Copyright (C) 2022 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 + * 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. */ -export class CustomMap { +export class CustomMap { map: Map = new Map() /** diff --git a/disklrucache/src/main/ets/components/disklrucache/DiskCacheEntry.ts b/disklrucache/src/main/ets/components/disklrucache/DiskCacheEntry.ts index ad2625d..d092323 100644 --- a/disklrucache/src/main/ets/components/disklrucache/DiskCacheEntry.ts +++ b/disklrucache/src/main/ets/components/disklrucache/DiskCacheEntry.ts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2022 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 diff --git a/disklrucache/src/main/ets/components/disklrucache/DiskLruCache.ts b/disklrucache/src/main/ets/components/disklrucache/DiskLruCache.ts index f36800c..5de2ca7 100644 --- a/disklrucache/src/main/ets/components/disklrucache/DiskLruCache.ts +++ b/disklrucache/src/main/ets/components/disklrucache/DiskLruCache.ts @@ -1,13 +1,13 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the 'License'); + * Copyright (C) 2022 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, + * 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. @@ -22,7 +22,10 @@ import SparkMD5 from "spark-md5" export class DiskLruCache { // 默认缓存数据最大值 - private static readonly DEFAULT_MAX_SIZE: number = 30 * 1024 * 1024 + private static readonly DEFAULT_MAX_SIZE: number = 300 * 1024 * 1024 + + // 默认缓存文件名 + private static readonly DEFAULT_NAME: string = 'diskLruCache' // 缓存journal文件名称 private static readonly journal: string = 'journal' @@ -70,9 +73,9 @@ export class DiskLruCache { * @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'); + public static create(context, maxSize?: number): DiskLruCache { + if (!!!context) { + throw new Error('DiskLruCache create context is empty, checking the parameter'); } if (!!!maxSize) { maxSize = DiskLruCache.DEFAULT_MAX_SIZE @@ -80,6 +83,9 @@ export class DiskLruCache { if (maxSize <= 0) { throw new Error("DiskLruCache create maxSize <= 0, checking the parameter"); } + + // 使用默认应用在内部存储上的缓存路径,作为存储地址 + let path = context.cacheDir + FileUtils.SEPARATOR + DiskLruCache.DEFAULT_NAME if (!FileUtils.getInstance().existFolder(path)) { FileUtils.getInstance().createFolder(path, true) } @@ -110,43 +116,15 @@ export class DiskLruCache { } } - /** - * 处理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) { + if (max <= 0 || max > DiskLruCache.DEFAULT_MAX_SIZE) { + throw new Error('setMaxSize error, checking the parameter'); + } this.maxSize = max this.trimToSize() } @@ -157,14 +135,26 @@ export class DiskLruCache { * @param key 键值 * @param content 文件内容 */ - set(key: string, content: ArrayBuffer) { + set(key: string, content: ArrayBuffer | string) { 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 + if (content instanceof ArrayBuffer) { + if (content == null || content.byteLength == 0) { + throw new Error('content is null. checking the parameter') + } + fileSize = content.byteLength + } else { + if (!!!content) { + throw new Error('content is null, checking the parameter') + } + fileSize = content.length; + } + if (this.fileSizeMoreThenMaxSize(fileSize)) { + throw new Error('content must be less then DiskLruCache Size, checking the parameter') + return } - let fileSize = content.byteLength key = SparkMD5.hash(key) this.size = this.size + fileSize this.putCacheMap(key, fileSize) @@ -180,17 +170,28 @@ export class DiskLruCache { * @param key 键值 * @param content 文件内容 */ - async setAsync(key: string, content: ArrayBuffer): Promise { + async setAsync(key: string, content: ArrayBuffer | string): 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 + if (content instanceof ArrayBuffer) { + if (content == null || content.byteLength == 0) { + throw new Error('content is null. checking the parameter') + } + fileSize = content.byteLength + } else { + if (!!!content) { + throw new Error('content is null, checking the parameter') + } + fileSize = content.length; + } + if (this.fileSizeMoreThenMaxSize(fileSize)) { + throw new Error('content must be less then DiskLruCache Size, checking the parameter') + return } - 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() @@ -198,58 +199,6 @@ export class DiskLruCache { 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缓存数据 * @@ -330,6 +279,13 @@ export class DiskLruCache { } } + /** + * 获取缓存路径 + */ + getPath(): string{ + return this.path; + } + /** * 删除key缓存数据 * @@ -372,6 +328,100 @@ export class DiskLruCache { this.size = 0 } + getCacheMap() { + return this.cacheMap; + } + + /** + * 返回当前DiskLruCache的size大小 + */ + getSize() { + return this.size; + } + + /** + * 处理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 key key 键值 + * @param path 文件路径 + */ + private 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 文件路径 + */ + private 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) + } + /** * 重置journal文件数据 */ @@ -408,8 +458,6 @@ export class DiskLruCache { */ 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)) @@ -420,25 +468,25 @@ export class DiskLruCache { * 根据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; + /** + * 图片文件过大 直接超过DiskLruCache上限 + */ + private fileSizeMoreThenMaxSize(fileSize: number): boolean{ + if (fileSize > this.maxSize) { + return true; + } + return false; } } \ 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 index 42b2ddf..fabb463 100644 --- a/disklrucache/src/main/ets/components/disklrucache/FileReader.ts +++ b/disklrucache/src/main/ets/components/disklrucache/FileReader.ts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2022 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 @@ -21,6 +21,7 @@ export class FileReader { // CR符 static readonly CR: string = '\r' + // 文件大小 fileLength: number = 0 @@ -39,15 +40,13 @@ export class FileReader { * @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) { + if (!!!path) { + throw new Error('FileReader constructor path is null, checking the parameter') + return; } + this.stream = fileio.createStreamSync(path, 'r+'); + let stat = fileio.statSync(path) + this.fileLength = stat.size } /** @@ -55,13 +54,30 @@ export class FileReader { */ readLine(): string { let line = '' - while (this.length <= this.fileLength) { + 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 + // check CRLF + if (temp == FileReader.CR) { + // 边界判断 首先拿到下一个字符判断是否是LF 如果是CRLF需要再向后挪一位 + if(this.length < this.fileLength) { + let nextBuf = new ArrayBuffer(1) + this.stream.readSync(nextBuf, { position: this.length }) + let nextTemp = String.fromCharCode.apply(null, new Uint8Array(nextBuf)) + // 如果是CRLF 需要给当前length+1 向后挪一位 + if (nextTemp == FileReader.LF) { + this.length++ + } + } + // 如果不是CRLF 只有一个CR结尾length不用变 + return line; + } else { + // 判断LF情况 + if (temp == FileReader.LF) { + return line + } } } return line diff --git a/disklrucache/src/main/ets/components/disklrucache/FileUtils.ts b/disklrucache/src/main/ets/components/disklrucache/FileUtils.ts index 1038004..1f9d70d 100644 --- a/disklrucache/src/main/ets/components/disklrucache/FileUtils.ts +++ b/disklrucache/src/main/ets/components/disklrucache/FileUtils.ts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2022 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 @@ -15,10 +15,13 @@ import fileio from '@ohos.fileio' export class FileUtils { - private static sInstance: FileUtils static readonly SEPARATOR: string = '/' + private static sInstance: FileUtils base64Str: string = '' + private constructor() { + } + /** * 单例实现FileUtils类 */ @@ -29,9 +32,6 @@ export class FileUtils { return this.sInstance; } - private constructor() { - } - /** * 新建文件 * @@ -127,7 +127,7 @@ export class FileUtils { * @param path 文件绝对路径 * @param data 文件内容 */ - writeNewFile(path: string, data: ArrayBuffer) { + writeNewFile(path: string, data: ArrayBuffer | string) { this.createFile(path) this.writeFile(path, data) } @@ -138,7 +138,7 @@ export class FileUtils { * @param path 文件绝对路径 * @param data 文件内容 */ - async writeNewFileAsync(path: string, data: ArrayBuffer): Promise { + async writeNewFileAsync(path: string, data: ArrayBuffer | string): Promise { await fileio.open(path, 0o100, 0o664) let fd = await fileio.open(path, 0o102, 0o664) await fileio.ftruncate(fd)