317 lines
8.5 KiB
Plaintext
317 lines
8.5 KiB
Plaintext
/*
|
|
* 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 {CustomMap} from './CustomMap'
|
|
import {FileUtils} from './FileUtils'
|
|
import {FileReader} from './FileReader'
|
|
import {DiskCacheEntry} from './DiskCacheEntry'
|
|
import fileio from '@ohos.fileio';
|
|
import featureability from '@ohos.ability.featureAbility'
|
|
import {Md5} from './Md5.ets'
|
|
|
|
export class DiskLruCache {
|
|
|
|
// 缓存数据集合
|
|
cacheMap: CustomMap<string, DiskCacheEntry> = new CustomMap<string, DiskCacheEntry>()
|
|
fileUtils: FileUtils = FileUtils.getInstance()
|
|
diskCacheFolder: string = 'GlideDiskCache'
|
|
|
|
// 缓存文件路劲地址
|
|
dirPath: string= ''
|
|
|
|
// 缓存数据最大值
|
|
maxSize: number = 30 * 1024 * 1024
|
|
|
|
// 当前缓存数据值
|
|
size: number = 0
|
|
|
|
// 缓存journal文件名称
|
|
|
|
journal: string = 'journal'
|
|
|
|
// 缓存journal备份文件名称
|
|
journalTemp: string = 'journal_temp'
|
|
|
|
// 缓存journal文件路径
|
|
journalPath: string = ''
|
|
|
|
// 缓存journal备份文件路径
|
|
journalPathTemp: string = ''
|
|
|
|
constructor(maxSize: number, direction?: string) {
|
|
if (maxSize > 0) {
|
|
this.maxSize = maxSize
|
|
}
|
|
if (!this.isNull(direction)) {
|
|
if (direction.endsWith('/')) {
|
|
this.dirPath = direction
|
|
} else {
|
|
this.dirPath = direction + '/'
|
|
}
|
|
} else {
|
|
featureability.getContext()
|
|
.getFilesDir()
|
|
.then((data) => {
|
|
console.log('DiskLruCache - FileDir= ' + data)
|
|
let dirPathFolder = data + '/' + this.diskCacheFolder
|
|
this.dirPath = dirPathFolder;
|
|
FileUtils.getInstance()
|
|
.createFolder(dirPathFolder)
|
|
this.init()
|
|
})
|
|
.catch((error) => {
|
|
console.log('DiskLruCache FileDir Error Cause:' + error.message);
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 初始化缓存文件
|
|
*/
|
|
private init() {
|
|
if (this.dirPath.endsWith('/')) {
|
|
this.dirPath = this.dirPath
|
|
} else {
|
|
this.dirPath = this.dirPath + '/'
|
|
}
|
|
this.journalPath = this.dirPath + this.journal
|
|
this.journalPathTemp = this.dirPath + this.journalTemp
|
|
try {
|
|
var stat = fileio.statSync(this.journalPath)
|
|
if (stat.isFile() && stat.size > 0) {
|
|
this.fileUtils.createFile(this.journalPathTemp)
|
|
this.fileUtils.copyFile(this.journalPath, this.journalPathTemp)
|
|
this.readJournal(this.journalPathTemp)
|
|
this.resetJournalFile()
|
|
} else {
|
|
this.fileUtils.createFile(this.journalPath)
|
|
}
|
|
} catch (e) {
|
|
console.log('DiskLruCache - init e ' + e)
|
|
this.fileUtils.createFile(this.journalPath)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 重置journal文件数据
|
|
*/
|
|
resetJournalFile(){
|
|
this.fileUtils.clearFile(this.journalPath)
|
|
for(let key of this.cacheMap.keys()){
|
|
this.fileUtils.writeData(this.journalPath, 'save ' + key + '\n')
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 读取journal文件的缓存数据
|
|
*/
|
|
readJournal(path: string) {
|
|
var fileReader = new FileReader(path)
|
|
var line: string = ''
|
|
while (!fileReader.isEnd()) {
|
|
line = fileReader.readLine()
|
|
line = line.replace('\n', '').replace('\r', '')
|
|
this.dealwithJournal(line)
|
|
}
|
|
this.fileUtils.deleteFile(this.journalPathTemp)
|
|
this.trimToSize()
|
|
}
|
|
|
|
/**
|
|
* 处理journal文件数据
|
|
*/
|
|
dealwithJournal(line: string) {
|
|
var picPath = ''
|
|
try {
|
|
var datas = line.split(' ')
|
|
if (datas.length > 1) {
|
|
if (datas[0] != 'remove') {
|
|
picPath = this.dirPath + datas[1]
|
|
var picstat = fileio.statSync(picPath)
|
|
if (picstat.isFile() && picstat.size > 0) {
|
|
this.size = this.size + picstat.size
|
|
this.fileUtils.writeData(this.journalPath, line + '\n')
|
|
this.putCacheMap(datas[1], picstat.size)
|
|
}
|
|
} else {
|
|
if (this.cacheMap.hasKey(datas[1])) {
|
|
var cacheEntry: DiskCacheEntry = this.cacheMap.get(datas[1])
|
|
this.size = this.size - cacheEntry.getLength()
|
|
this.cacheMap.remove(datas[1])
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.log('DiskLruCache - dealwithJournal e = ' + e)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 设置disk缓存最大数据值
|
|
*/
|
|
setMaxSize(max: number) {
|
|
this.maxSize = max
|
|
}
|
|
|
|
/**
|
|
* 缓存数据map集合
|
|
*/
|
|
private putCacheMap(key: string, length?: number) {
|
|
if (this.cacheMap.hasKey(key)) {
|
|
this.cacheMap.remove(key)
|
|
}
|
|
if (length > 0) {
|
|
this.cacheMap.put(key, new DiskCacheEntry(key, length))
|
|
} else {
|
|
this.cacheMap.put(key, new DiskCacheEntry(key))
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 存储disk缓存数据
|
|
*/
|
|
putCacheData(key: string, content?: ArrayBuffer, path?: string) {
|
|
if (key == null) {
|
|
throw new Error('key is null,checking the parameter');
|
|
}
|
|
var fileSize = 0
|
|
var isvalid: boolean = false
|
|
key = Md5.hashStr(key)
|
|
if (content != null && content.byteLength > 0) {
|
|
isvalid = true
|
|
var tempPath = this.dirPath + key
|
|
fileSize = content.byteLength
|
|
this.fileUtils.writePic(tempPath, content)
|
|
}
|
|
if (!this.isNull(path) && this.fileUtils.exist(path)) {
|
|
isvalid = true
|
|
fileSize = this.fileUtils.getFileSize(path)
|
|
this.fileUtils.copyFile(path, this.dirPath + key)
|
|
}
|
|
if (isvalid) {
|
|
this.size = this.size + fileSize
|
|
this.putCacheMap(key, fileSize)
|
|
this.fileUtils.writeData(this.journalPath, 'save ' + key + '\n')
|
|
this.trimToSize()
|
|
} else {
|
|
throw ('putCacheData() key or content or path is invalid')
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* 根据LRU算法删除多余缓存数据
|
|
*/
|
|
private trimToSize() {
|
|
while (this.size > this.maxSize) {
|
|
var tempkey: string = this.cacheMap.getFirstKey()
|
|
var fileSize = this.fileUtils.getFileSize(this.dirPath + tempkey)
|
|
if (fileSize > 0) {
|
|
this.size = this.size - fileSize
|
|
}
|
|
this.fileUtils.deleteFile(this.dirPath + tempkey)
|
|
this.cacheMap.remove(tempkey)
|
|
this.fileUtils.writeData(this.journalPath, 'remove ' + tempkey + '\n')
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取key缓存数据
|
|
*/
|
|
getCacheDataByKey(key: string): ArrayBuffer{
|
|
if (key == null) {
|
|
throw new Error('key is null,checking the parameter');
|
|
}
|
|
key = Md5.hashStr(key)
|
|
var path = this.dirPath + key;
|
|
if (this.fileUtils.exist(path)) {
|
|
var ab: ArrayBuffer = this.fileUtils.readFilePic(path)
|
|
this.putCacheMap(key, ab.byteLength)
|
|
this.fileUtils.writeData(path, 'read ' + key + '\n')
|
|
return ab
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取key缓存数据绝对路径
|
|
*/
|
|
getCacheFileByKey(key: string): string{
|
|
if (key == null) {
|
|
throw new Error('key is null,checking the parameter');
|
|
}
|
|
key = Md5.hashStr(key)
|
|
if (this.dirPath.endsWith('/')) {
|
|
this.dirPath = this.dirPath
|
|
} else {
|
|
this.dirPath = this.dirPath + '/'
|
|
}
|
|
var path = this.dirPath + key;
|
|
if (this.fileUtils.exist(path)) {
|
|
this.fileUtils.writeData(path, 'read ' + key + '\n')
|
|
return path
|
|
} else {
|
|
return null
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 删除key缓存数据
|
|
*/
|
|
deleteCacheDataBykey(key: string): DiskCacheEntry{
|
|
if (key == null) {
|
|
throw new Error('key is null,checking the parameter');
|
|
}
|
|
key = Md5.hashStr(key)
|
|
var path = this.dirPath + key;
|
|
if (this.fileUtils.exist(path)) {
|
|
var ab = this.fileUtils.readFilePic(path)
|
|
this.size = this.size - ab.byteLength
|
|
this.cacheMap.remove(key)
|
|
this.fileUtils.writeData(this.journalPath, 'remove ' + key + '\n')
|
|
this.fileUtils.deleteFile(path)
|
|
}
|
|
return this.cacheMap.get(key)
|
|
}
|
|
|
|
/**
|
|
* 清除所有disk缓存数据
|
|
*/
|
|
cleanCacheData() {
|
|
var length = this.cacheMap.size()
|
|
for (var index = 0; index < length; index++) {
|
|
this.fileUtils.deleteFile(this.dirPath + this.cacheMap[index])
|
|
}
|
|
this.fileUtils.deleteFile(this.journalPath)
|
|
this.cacheMap.clear()
|
|
this.size = 0
|
|
}
|
|
|
|
/**
|
|
* 空字符串判断
|
|
*/
|
|
private isNull(str: string): boolean{
|
|
if (!str || Object.keys(str).length == 0) {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
foreachDiskLruCache(fn){
|
|
this.cacheMap.each(fn)
|
|
}
|
|
|
|
} |