package com.pandaq.pandaeye.disklrucache; import android.content.Context; import android.os.Environment; import com.jakewharton.disklrucache.DiskLruCache; import com.pandaq.pandaeye.CustomApplication; import com.pandaq.pandaeye.config.Constants; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Serializable; /** * Created by PandaQ on 2017/2/6. * email : 767807368@qq.com * 磁盘缓存工具类 */ public class DiskCacheManager { private static DiskLruCache mDiskLruCache = null; private DiskLruCache.Editor mEditor = null; private DiskLruCache.Snapshot mSnapshot = null; public DiskCacheManager(Context context, String uniqueName) { try { //先关闭已有的缓存 if (mDiskLruCache != null) { mDiskLruCache.close(); mDiskLruCache = null; } File cacheFile = getCacheFile(context, uniqueName); mDiskLruCache = DiskLruCache.open(cacheFile, CustomApplication.getAppVersionCode(), 1, Constants.CACHE_MAXSIZE); } catch (IOException e) { e.printStackTrace(); } } /** * 获取缓存的路径 两个路径在卸载程序时都会删除,因此不会在卸载后还保留乱七八糟的缓存 * 有SD卡时获取 /sdcard/Android/data/<application package>/cache * 无SD卡时获取 /data/data/<application package>/cache * * @param context 上下文 * @param uniqueName 缓存目录下的细分目录,用于存放不同类型的缓存 * @return 缓存目录 File */ private File getCacheFile(Context context, String uniqueName) { String cachePath = null; if ((Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) && context.getExternalCacheDir() != null) { cachePath = context.getExternalCacheDir().getPath(); } else { cachePath = context.getCacheDir().getPath(); } return new File(cachePath + File.separator + uniqueName); } /** * 获取缓存 editor * * @param key 缓存的key * @return editor * @throws IOException */ private DiskLruCache.Editor edit(String key) throws IOException { key = SecretUtil.getMD5Result(key); //存取的 key if (mDiskLruCache != null) { mEditor = mDiskLruCache.edit(key); } return mEditor; } /** * 根据 key 获取缓存缩略 * * @param key 缓存的key * @return Snapshot */ private DiskLruCache.Snapshot snapshot(String key) { if (mDiskLruCache != null) { try { mSnapshot = mDiskLruCache.get(key); } catch (IOException e) { e.printStackTrace(); } } return mSnapshot; } /************************* * 字符串读写 *************************/ /** * 缓存 String * * @param key 缓存文件键值(MD5加密结果作为缓存文件名) * @param value 缓存内容 */ public void put(String key, String value) { DiskLruCache.Editor editor = null; BufferedWriter writer = null; try { editor = edit(key); if (editor == null) { return; } OutputStream os = editor.newOutputStream(0); writer = new BufferedWriter(new OutputStreamWriter(os)); writer.write(value); editor.commit(); } catch (IOException e) { e.printStackTrace(); try { if (editor != null) editor.abort(); } catch (IOException e1) { e1.printStackTrace(); } } finally { try { if (writer != null) { writer.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * 获取字符串缓存 * * @param key cache'key * @return string */ public String getString(String key) { InputStream inputStream = getCacheInputStream(key); if (inputStream == null) { return null; } try { return inputStream2String(inputStream); } catch (IOException e) { e.printStackTrace(); return null; } finally { try { inputStream.close(); } catch (IOException e1) { e1.printStackTrace(); } } } /************************* * Json对象读写 *************************/ //Json 数据转换成 String 存储 public void put(String key, JSONObject value) { put(key, value.toString()); } //取得 json 字符串再转为 Json对象 public JSONObject getJsonObject(String key) { String json = getString(key); try { return new JSONObject(json); } catch (JSONException e) { e.printStackTrace(); return null; } } /************************* * Json数组对象读写 *************************/ public void put(String key, JSONArray array) { put(key, array.toString()); } public JSONArray getJsonArray(String key) { try { return new JSONArray(getString(key)); } catch (JSONException e) { e.printStackTrace(); return null; } } /************************* * byte 数据读写 *************************/ /** * 存入byte数组 * * @param key cache'key * @param bytes bytes to save */ public void put(String key, byte[] bytes) { OutputStream out = null; DiskLruCache.Editor editor = null; try { editor = edit(key); if (editor == null) { return; } out = editor.newOutputStream(0); out.write(bytes); out.flush(); editor.commit(); } catch (IOException e) { e.printStackTrace(); try { if (editor != null) { editor.abort(); } } catch (IOException e1) { e1.printStackTrace(); } } finally { if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 获取缓存的 byte 数组 * * @param key cache'key * @return bytes */ public byte[] getBytes(String key) { byte[] bytes = null; InputStream inputStream = getCacheInputStream(key); if (inputStream == null) { return null; } ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buf = new byte[256]; int len = 0; try { while ((len = inputStream.read(buf)) != -1) { bos.write(buf, 0, len); } bytes = bos.toByteArray(); } catch (IOException e) { e.printStackTrace(); } return bytes; } /************************* * 序列化对象数据读写 *************************/ /** * 序列化对象写入 * * @param key cache'key * @param object 待缓存的序列化对象 */ public void put(String key, Serializable object) { ObjectOutputStream oos = null; DiskLruCache.Editor editor = null; try { editor = edit(key); if (editor == null) { return; } oos = new ObjectOutputStream(editor.newOutputStream(0)); oos.writeObject(object); oos.flush(); editor.commit(); } catch (IOException e) { e.printStackTrace(); try { if (editor != null) editor.abort(); } catch (IOException e1) { e1.printStackTrace(); } } finally { try { if (oos != null) { oos.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * 获取 序列化对象 * * @param key cache'key * @param <T> 对象类型 * @return 读取到的序列化对象 */ @SuppressWarnings("unchecked") public <T> T getSerializable(String key) { T object = null; ObjectInputStream ois = null; InputStream in = getCacheInputStream(key); if (in == null) { return null; } try { ois = new ObjectInputStream(in); object = (T) ois.readObject(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } return object; } /************************************************************************ ********************** 辅助工具方法 分割线 **************************** ************************************************************************/ /** * inputStream 转 String * * @param is 输入流 * @return 结果字符串 */ private String inputStream2String(InputStream is) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8")); StringBuilder buffer = new StringBuilder(); String line; while ((line = in.readLine()) != null) { buffer.append(line); } return buffer.toString(); } /** * 获取 缓存数据的 InputStream * * @param key cache'key * @return InputStream */ private InputStream getCacheInputStream(String key) { key = SecretUtil.getMD5Result(key); InputStream in; DiskLruCache.Snapshot snapshot = snapshot(key); if (snapshot == null) { return null; } in = snapshot.getInputStream(0); return in; } /** * 同步记录文件 */ public static void flush() { if (mDiskLruCache != null) { try { mDiskLruCache.flush(); } catch (IOException e) { e.printStackTrace(); } } } }