大家都知道文件的保存和读取是如何使用,少量的文件可以通过获取文件名来读取文件,但是对于大批量下载的临时文件都是不规则存储的,如何保存和获取各个文件的信息,那接下来我们就来讲下如何通过DiskLruCache工具类来处理这些事情。
首先需要初始化工具类:很简单一句话:
mDiskCache = DiskLruCache.open(file,1,1,1024*1024*16/8,100);
复制代码
分析一下这个方法: 首先新建了一个Journal.tmp临时文件,再把临时文件重命名为Journal,该文件用于存储所以缓存的文件信息key和count等。
public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize, int maxFileCount)
throws IOException {
...省略了
cache = new DiskLruCache(directory, appVersion, valueCount, maxSize, maxFileCount);
cache.rebuildJournal();
return cache;
}
private synchronized void rebuildJournal() throws IOException {
...
Writer writer = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(journalFileTmp), Util.US_ASCII));
...略
if (journalFile.exists()) {
renameTo(journalFile, journalFileBackup, true);
}
renameTo(journalFileTmp, journalFile, false);
journalFileBackup.delete();
journalWriter = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(journalFile, true), Util.US_ASCII));
}
复制代码
存储文件:获取Editor,得到一个Ops,给Ops赋值,然后调用commit方法实现写文件和写存储的文件信息。
DiskLruCache.Editor editor = mDiskCache.edit(generateKey(url));
if(editor != null){
OutputStream outputStream = editor.newOutputStream(0);
downLoadFile(url,outputStream);
editor.commit();
}
复制代码
接下来重点来看下工具类的get方法,即读文件。观源码可知,通过Entry entry = lruEntries.get(key);最后获取一个Snapshot对象。通过该对象获取文件信息。
public synchronized Snapshot get(String key) throws IOException {
checkNotClosed();
validateKey(key);
Entry entry = lruEntries.get(key);
if (entry == null) {
return null;
}
if (!entry.readable) {
return null;
}
// Open all streams eagerly to guarantee that we see a single published
// snapshot. If we opened streams lazily then the streams could come
// from different edits.
File[] files = new File[valueCount];
InputStream[] ins = new InputStream[valueCount];
try {
File file;
for (int i = 0; i < valueCount; i++) {
file = entry.getCleanFile(i);
files[i] = file;
ins[i] = new FileInputStream(file);
}
} catch (FileNotFoundException e) {
// A file must have been deleted manually!
for (int i = 0; i < valueCount; i++) {
if (ins[i] != null) {
Util.closeQuietly(ins[i]);
} else {
break;
}
}
return null;
}
redundantOpCount++;
journalWriter.append(READ + ' ' + key + '\n');
if (journalRebuildRequired()) {
如果文件超过最大存储数,会优先除去不经常使用的文件。
executorService.submit(cleanupCallable);
}
return new Snapshot(key, entry.sequenceNumber, files, ins, entry.lengths);
}
复制代码