/** * Returns an unbuffered input stream to read the last committed value, * or null if no value has been committed. */ public InputStream newInputStream(int index)throws IOException { synchronized (DiskLruCache.this) { if (entry.currentEditor != this) { thrownewIllegalStateException(); } if (!entry.readable) { returnnull; } try { returnnewFileInputStream(entry.getCleanFile(index)); } catch (FileNotFoundException e) { returnnull; } } }
/** * Returns the last committed value as a string, or null if no value * has been committed. */ public String getString(int index)throws IOException { InputStreamin= newInputStream(index); return in != null ? inputStreamToString(in) : null; }
/** * Returns a new unbuffered output stream to write the value at * {@code index}. If the underlying output stream encounters errors * when writing to the filesystem, this edit will be aborted when * {@link #commit} is called. The returned output stream does not throw * IOExceptions. */ public OutputStream newOutputStream(int index)throws IOException { if (index < 0 || index >= valueCount) { thrownewIllegalArgumentException("Expected index " + index + " to " + "be greater than 0 and less than the maximum value count " + "of " + valueCount); } synchronized (DiskLruCache.this) { if (entry.currentEditor != this) { thrownewIllegalStateException(); } if (!entry.readable) { written[index] = true; } FiledirtyFile= entry.getDirtyFile(index); FileOutputStream outputStream; try { outputStream = newFileOutputStream(dirtyFile); } catch (FileNotFoundException e) { // Attempt to recreate the cache directory. directory.mkdirs(); try { outputStream = newFileOutputStream(dirtyFile); } catch (FileNotFoundException e2) { // We are unable to recover. Silently eat the writes. return NULL_OUTPUT_STREAM; } } returnnewFaultHidingOutputStream(outputStream); } }
/** Sets the value at {@code index} to {@code value}. */ publicvoidset(int index, String value)throws IOException { Writerwriter=null; try { writer = newOutputStreamWriter(newOutputStream(index), Util.UTF_8); writer.write(value); } finally { Util.closeQuietly(writer); } }
/** * Commits this edit so it is visible to readers. This releases the * edit lock so another edit may be started on the same key. */ publicvoidcommit()throws IOException { if (hasErrors) { completeEdit(this, false); remove(entry.key); // The previous entry is stale. } else { completeEdit(this, true); } committed = true; }
/** * Aborts this edit. This releases the edit lock so another edit may be * started on the same key. */ publicvoidabort()throws IOException { completeEdit(this, false); }
publicstatic DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize) throws IOException { if (maxSize <= 0) { thrownewIllegalArgumentException("maxSize <= 0"); } if (valueCount <= 0) { thrownewIllegalArgumentException("valueCount <= 0"); }
// If a bkp file exists, use it instead. // 流程:优先使用JOURNAL_FILE,删除JOURNAL_FILE_BACKUP备份文件, // 否则,JOURNAL_FILE_BACKUP备份文件重命名为JOURNAL_FILE FilebackupFile=newFile(directory, JOURNAL_FILE_BACKUP); if (backupFile.exists()) { FilejournalFile=newFile(directory, JOURNAL_FILE); // If journal file also exists just delete backup file. if (journalFile.exists()) { backupFile.delete(); } else { renameTo(backupFile, journalFile, false); } }
// Prefer to pick up where we left off. DiskLruCachecache=newDiskLruCache(directory, appVersion, valueCount, maxSize); if (cache.journalFile.exists()) { try { // 读取Jonrnal文件,恢复记录到内存 lruEntries 中 cache.readJournal(); // 根据 lruEntries 内存中的数据简化 Journal 文件 cache.processJournal(); return cache; } catch (IOException journalIsCorrupt) { System.out .println("DiskLruCache " + directory + " is corrupt: " + journalIsCorrupt.getMessage() + ", removing"); cache.delete(); } }
// If we ended on a truncated line, rebuild the journal before appending to it. if (reader.hasUnterminatedLine()) { rebuildJournal(); } else { journalWriter = newBufferedWriter(newOutputStreamWriter( newFileOutputStream(journalFile, true), Util.US_ASCII)); } } finally { Util.closeQuietly(reader); } }
// 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. InputStream[] ins = newInputStream[valueCount]; try { for (inti=0; i < valueCount; i++) { ins[i] = newFileInputStream(entry.getCleanFile(i)); } } catch (FileNotFoundException e) { // A file must have been deleted manually! for (inti=0; i < valueCount; i++) { if (ins[i] != null) { Util.closeQuietly(ins[i]); } else { break; } } returnnull; }
// If this edit is creating the entry for the first time, every index must have a value. // 下面是editor和entry的dirtyFile做检查 if (success && !entry.readable) { for (inti=0; i < valueCount; i++) { if (!editor.written[i]) { editor.abort(); thrownewIllegalStateException("Newly created entry didn't create value for index " + i); } if (!entry.getDirtyFile(i).exists()) { editor.abort(); return; } } }