Java implementation of a Disk-based LRU cache which specifically targets Android compatibility.

Related tags

Utility DiskLruCache
Overview

Disk LRU Cache

A cache that uses a bounded amount of space on a filesystem. Each cache entry has a string key and a fixed number of values. Each key must match the regex [a-z0-9_-]{1,120}. Values are byte sequences, accessible as streams or files. Each value must be between 0 and Integer.MAX_VALUE bytes in length.

The cache stores its data in a directory on the filesystem. This directory must be exclusive to the cache; the cache may delete or overwrite files from its directory. It is an error for multiple processes to use the same cache directory at the same time.

This cache limits the number of bytes that it will store on the filesystem. When the number of stored bytes exceeds the limit, the cache will remove entries in the background until the limit is satisfied. The limit is not strict: the cache may temporarily exceed it while waiting for files to be deleted. The limit does not include filesystem overhead or the cache journal so space-sensitive applications should set a conservative limit.

Clients call edit to create or update the values of an entry. An entry may have only one editor at one time; if a value is not available to be edited then edit will return null.

  • When an entry is being created it is necessary to supply a full set of values; the empty value should be used as a placeholder if necessary.
  • When an entry is being edited, it is not necessary to supply data for every value; values default to their previous value.

Every edit call must be matched by a call to Editor.commit or Editor.abort. Committing is atomic: a read observes the full set of values as they were before or after the commit, but never a mix of values.

Clients call get to read a snapshot of an entry. The read will observe the value at the time that get was called. Updates and removals after the call do not impact ongoing reads.

This class is tolerant of some I/O errors. If files are missing from the filesystem, the corresponding entries will be dropped from the cache. If an error occurs while writing a cache value, the edit will fail silently. Callers should handle other problems by catching IOException and responding appropriately.

Note: This implementation specifically targets Android compatibility.

Download

Download the latest .jar or grab via Maven:

<dependency>
  <groupId>com.jakewharton</groupId>
  <artifactId>disklrucache</artifactId>
  <version>2.0.2</version>
</dependency>

or Gradle:

compile 'com.jakewharton:disklrucache:2.0.2'

Snapshots of the development version are available in Sonatype's snapshots repository.

If you would like to compile your own version, the library can be built by running mvn clean verify. The output JAR will be in the target/ directory. (Note: this requires Maven be installed)

License

Copyright 2012 Jake Wharton
Copyright 2011 The Android Open Source Project

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.
Comments
  • Support absolute expiration

    Support absolute expiration

    I'm intending to use DiskLruCache to cache all Http Request from my application. Every request to a server will be cached for re-using.

    It would be great if we can configure the absolute expiration for the cache, so after an amount of time, cache will be cleared automatically, in order to get fresh data, and then cache it.

    Feature Request 
    opened by tonnguyen 14
  • Added method getFile() into Snapshot class.

    Added method getFile() into Snapshot class.

    This gives us the ability to work with File class and not only with InputStream. Since DiskLruCache is caching data in files it is useful to manipulate with File-s.

    Example: I used this cache to store .mp4 files. Android MediaPlayer class doesn't work with InputStream so I used absolute path of File to start playback. But to get File from cache I've added this code.

    opened by danylovolokh 9
  • Allow keys with dashes (-) so one can use the return of an object's .hashCode() as key

    Allow keys with dashes (-) so one can use the return of an object's .hashCode() as key

    Useful for HTTP caching and other cases.

    For instance:

    URL url = new URL("http://host/path");
    String myKey = String.valueOf(url.hashCode()); // may be a negative integer
    
    opened by jonasfa 9
  • Android aggresive cache clearing leads to crash

    Android aggresive cache clearing leads to crash

    I have the cache put inside a subdirectory in the application cache directory. On devices with low internal storage (Nexus One for example) this will eventually lead to low storage situations where Android will just clear the whole cache directory, including subdirectories.

    This gives this:

    java.io.FileNotFoundException: /data/data/<package>/cache/images/-1944396650.0.tmp (No such file or directory)
    at org.apache.harmony.luni.platform.OSFileSystem.open(Native Method)
    at dalvik.system.BlockGuard$WrappedFileSystem.open(BlockGuard.java:232)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:94)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:66)
    at <package>.DiskLruCache$Editor.newOutputStream(DiskLruCache.java:686)
    

    It's thrown because the images directory is now gone. I though listening for ACTION_DEVICE_STORAGE_LOW could solve this but that is broadcasted after Android has cleared the directory.

    If would be nice if it was possible to just reset the cache when the whole directory has gone missing or something.

    Bug Report Fixed Not Released 
    opened by lexs 9
  • Replaced synchronized with ReentrantReadWriteLock

    Replaced synchronized with ReentrantReadWriteLock

    This removes all synchronized statements in favor of a ReentrantReadWriteLock. This allows read operations to not block each other, but write operations to block everything (the way synchronized was working previously).

    With the addition of a simple contains() method, it is now super cheap to check if an image exists in the cache.

    Added unit tests for the new contains() method.

    opened by Wavesonics 7
  • Replaced synchronize's with ReentrantReadWriteLock & added contains() method

    Replaced synchronize's with ReentrantReadWriteLock & added contains() method

    This PR removes all synchronized statements in favor of a ReentrantReadWriteLock. This allows read operations to not block each other, but write operations to block everything (the way synchronized was working previously).

    With the addition of a simple contains() method, it is now super cheap to check if an image exists in the cache.

    opened by Wavesonics 7
  • Memoize Entry Files to reduce char[] allocations.

    Memoize Entry Files to reduce char[] allocations.

    While trying to reduce garbage collections in a sample app, I noticed that this library allocates a couple of strings per request (once for the file name, and once to join the directory and the file name) which generates enough garbage to cause gcs to noticeably increase in frequency.

    The largest strings I saw were around 300 characters so the memory overhead of holding on to the files for each entry is probably pretty small. Even with 5000 entries in memory at once the total overhead would be less than 3mb (300 characters * 2 bytes per character * 5000 entries). At the same time even with only a few items per row, scrolling a list could easily generate a couple of kB worth of garbage per row.

    opened by sjudd 6
  • Last DiskLruCache.get() in loop returns null on existing key

    Last DiskLruCache.get() in loop returns null on existing key

    Hi!

    I'm loading images in ListView from DiskLruCache. ListAdapter.getView() method creates AsyncTask which loads image from DiskLruCache. And there is very strange behavior - DiskLruCache.get() returns null on last one ListView element in bunch of lazy loaded ListView elements.

    To simplify situation imagine loop:

    for (i...) { SnapShot value = DiskLruCache.get("key"+i); }

    For the last "i" value is null. A checked that on UI thread also, but still same result.

    If it's not a bug but my mistake maybe someone would help me with issue?

    Thanks!

    P.S. DDMS shows that cache entry exist. Clearing and filling it again brings same result. P.P.S. It does not depend on items count. It could be different entry from time to time, but always last in bunch of get() calls

    opened by Bdiang 6
  • Feature Request: make DiskLruCache.Editor Closeable

    Feature Request: make DiskLruCache.Editor Closeable

    In order to always match an edit to a commit() or abort(), even in case of exceptions, it would be nice to be able to do this:

    Editor e = cache.edit(key);
    try {
      // edit values
      e.commit();
    } finally {
      e.close(); // will abort(), unless the editor has already been committed or aborted
    }
    

    I can submit a pull request if preferred.

    opened by orip 6
  • Hey! 61 tests 10 failed I have...

    Hey! 61 tests 10 failed I have...

    I have exported and uploaded test results. Maybe sth happen or OS security policy. But some tests show sth wrong for example;

    DiskLruCache.Editor creator = cache.edit("k1"); creator.set(0, "A"); DiskLruCache.Editor updater = cache.edit("k1"); updater.set(0, "C"); DiskLruCache.Snapshot snapshot = cache.get("k1"); assertThat(snapshot.getString(0)).isEqualTo("C");

    It was failed.

    Maybe, You will check all test result...

    testResults.pdf

    Thanks.

    opened by nurisezgin 5
  • Added contains() method

    Added contains() method

    This is a much faster way of checking if a given key exists in the cache.

    In a demanding use-case, scrolling very quickly, where every item in a ListView must check to see if it's object's key exists in the DiskCache: Some basic profiling showed this method taking ~3ms vs using get( key ) taking on average ~70ms. I believe this is because get() is synchronized.

    It should be safe to use contains() unsynchronized like this.

    This addresses issue #54

    opened by Wavesonics 5
  • Can you support the OpenHarmony JavaScript version?

    Can you support the OpenHarmony JavaScript version?

    I am developing an OpenHarmony application that uses the JavaScript language. Can you support the OpenHarmony JavaScript version? I am willing to participate in the development and look forward to reply.

    opened by DoraCoder 1
  • add: cache entry creation time param to Snapshot

    add: cache entry creation time param to Snapshot

    I added cache entry creation time param to Snapshot. With this simple feature we can make expiration cache. Example: private Bitmap getExpired( String key, long expire, TimeUnit timeUnit ) { Bitmap bitmap = null; try ( DiskLruCache.Snapshot snapshot = mDiskCache.get( key ) ) { if ( snapshot == null ) return bitmap; long expiredTime = new Date().getTime() - timeUnit.toMillis( expire ); if ( expire > 0 && snapshot.getCreatedTime() < expiredTime ) return null; final InputStream in = snapshot.getInputStream( 0 ); if ( in != null ) { final BufferedInputStream buffIn = new BufferedInputStream( in, IO_BUFFER_SIZE ); bitmap = BitmapFactory.decodeStream( buffIn ); } } catch ( IOException e ) { e.printStackTrace(); } return bitmap; }

    opened by feivur 1
  • Avoid IOExceptions in delete() when the cache dir is deleted externally.

    Avoid IOExceptions in delete() when the cache dir is deleted externally.

    File#listFiles() will return null if the directory has been deleted. This scenario isn’t totally far fetched because it’s fairly common for Android developers to place their disk caches in the Android application cache directory. The cache directory can be cleared at any time by the system, including while the app is open, which in turn can cause unexpected IOExceptions when delete() is called.

    See https://github.com/bumptech/glide/issues/2465 for additional context.

    opened by sjudd 0
  • Key length is 64 for dependencies resolved via maven/jcenter

    Key length is 64 for dependencies resolved via maven/jcenter

    https://github.com/JakeWharton/DiskLruCache/blob/3e016356cfc7e5f9644a7a732fe0223e9742e024/src/main/java/com/jakewharton/disklrucache/DiskLruCache.java#L95

    I came across an exception where my key length exceeded 64 characters, so I was browsing through the repo to figure out a reason for this cap on key length. It seems after the key length was increased, the newer jar never got deployed to maven/bintray.

    opened by rahul-a 1
  • Get entry count/iterator

    Get entry count/iterator

    It would be great if we can have a way to know the count of the entities and even better if we can have an iterator of the snapshots like the one in the OkHttp implementation.

    opened by miguelvillasenor 0
Android library to easily serialize and cache your objects to disk using key/value pairs.

Deprecated This project is no longer maintained. No new issues or pull requests will be accepted. You can still use the source or fork the project to

Anup Cowkur 667 Dec 22, 2022
DiskCache - Simple and readable disk cache for kotlin and android applications

DiskCache Simple and readable disk cache for kotlin and android applications (with journaled lru strategy) This is a simple lru disk cache, based on t

Giovanni Corte 14 Dec 2, 2022
Multiplaform kotlin library for calculating text differences. Based on java-diff-utils, supports JVM, JS and native targets.

kotlin-multiplatform-diff This is a port of java-diff-utils to kotlin with multiplatform support. All credit for the implementation goes to original a

Peter Trifanov 51 Jan 3, 2023
a simple cache for android and java

ASimpleCache ASimpleCache 是一个为android制定的 轻量级的 开源缓存框架。轻量到只有一个java文件(由十几个类精简而来)。 1、它可以缓存什么东西? 普通的字符串、JsonObject、JsonArray、Bitmap、Drawable、序列化的java对象,和 b

Michael Yang 3.7k Dec 14, 2022
Keep data as a linked list on disk. A alternative way to reduce redundant operation for DiskLruCache

DiskLinkedList Keep data as a linked list on disk. An alternative way to reduce redundant operation for DiskLruCache Use-case Android have build-in Di

Cuong V. Nguyen 6 Oct 29, 2021
A simple Android utils library to write any type of data into cache files and read them later.

CacheUtilsLibrary This is a simple Android utils library to write any type of data into cache files and then read them later, using Gson to serialize

Wesley Lin 134 Nov 25, 2022
WebSocket & WAMP in Java for Android and Java 8

Autobahn|Java Client library providing WAMP on Java 8 (Netty) and Android, plus (secure) WebSocket for Android. Autobahn|Java is a subproject of the A

Crossbar.io 1.5k Dec 9, 2022
General purpose utilities and hash functions for Android and Java (aka java-common)

Essentials Essentials are a collection of general-purpose classes we found useful in many occasions. Beats standard Java API performance, e.g. LongHas

Markus Junginger 1.4k Dec 29, 2022
WebSocket & WAMP in Java for Android and Java 8

Autobahn|Java Client library providing WAMP on Java 8 (Netty) and Android, plus (secure) WebSocket for Android. Autobahn|Java is a subproject of the A

Crossbar.io 1.5k Dec 9, 2022
General purpose utilities and hash functions for Android and Java (aka java-common)

Essentials Essentials are a collection of general-purpose classes we found useful in many occasions. Beats standard Java API performance, e.g. LongHas

Markus Junginger 1.4k Dec 29, 2022
Trail is a simple logging system for Java and Android. Create logs using the same API and the library will detect automatically in which platform the code is running.

Trail Trail is a simple logging system for Java and Android. Create logs using the same API and the library will detect automatically in which platfor

Mauricio Togneri 13 Aug 29, 2022
A lightning fast, transactional, file-based FIFO for Android and Java.

Tape by Square, Inc. Tape is a collection of queue-related classes for Android and Java. QueueFile is a lightning-fast, transactional, file-based FIFO

Square 2.4k Dec 30, 2022
Native Kotlin library for time-based TOTP and HMAC-based HOTP one-time passwords

A kotlin implementation of HOTP (RFC-4226) and TOTP (RFC-6238). Supports validation and generation of 2-factor authentication codes, recovery codes and randomly secure secrets.

Robin Ohs 6 Dec 19, 2022
OpenKeychain is an OpenPGP implementation for Android.

OpenKeychain (for Android) OpenKeychain is an OpenPGP implementation for Android. For a more detailed description and installation instructions go to

OpenKeychain 1.8k Jan 3, 2023
Encrypted overlay filesystems implementation for Android.

DroidFS DroidFS is an alternative way to use encrypted overlay filesystems on Android that uses its own internal file explorer instead of mounting vir

Hardcore Sushi 283 Dec 20, 2022
compaKTset is a small library aimed at providing you with the most memory efficient Set implementation for any particular data type of your choosing.

compaKTset is a small library aimed at providing you with the most memory efficient Set implementation for any particular data type of your choosing.

Ignat Beresnev 3 Nov 16, 2021
gRPC and protocol buffers for Android, Kotlin, and Java.

Wire “A man got to have a code!” - Omar Little See the project website for documentation and APIs. As our teams and programs grow, the variety and vol

Square 3.9k Dec 31, 2022
UPnP/DLNA library for Java and Android

Cling EOL: This project is no longer actively maintained, code may be outdated. If you are interested in maintaining and developing this project, comm

4th Line 1.6k Jan 4, 2023
Error handling library for Android and Java

ErrorHandler Error handling library for Android and Java Encapsulate error handling logic into objects that adhere to configurable defaults. Then pass

null 237 Dec 29, 2022