你想要的CacheUtils
Foreword
好久沒發(fā)布新的工具類了,這次就來個勁爆點的,就是大家熟悉的緩存相關(guān)工具類,花了好幾天時間方才擼出來的一個工具類,現(xiàn)已通過單元測試,相關(guān)單元測試代碼的鏈接可以在下面的API介紹看到,該工具類參考ASimpleCache來實現(xiàn),由于它的代碼是三年多前的,存在bug還是有挺多的,不過我重構(gòu)的代碼已修復(fù)我所發(fā)現(xiàn)的bug了,而且如今的代碼閱讀性極佳,條理清楚,大家可以好好學(xué)一學(xué)。
Feature
- 支持配置緩存大小和緩存數(shù)量,不配置的話就是沒有上限,如果配置了緩存大小的和上限的話,當(dāng)緩存到達(dá)最大緩存尺寸或者超過緩存?zhèn)€數(shù)的時候便會自動刪除最老的緩存;
- 支持配置緩存路徑,不配置的話默認(rèn)在
/data/data/com.xxx.xxx/cache/cacheUtils目錄下; - 支持多個實例緩存,也就是可以把緩存放在不同的文件夾下,他們會根據(jù)你的緩存實例各司其職;
- 支持緩存眾多數(shù)據(jù)類型,分有字節(jié)數(shù)組、String、JSONObject、JSONArray、Bitmap、Drawable、Parcelable、Serializable這八種;
- 支持緩存寫入有效時長,在下次讀取時失效的話默認(rèn)返回
null,也可返回自定義的默認(rèn)值; - 緩存讀寫速度快,采用了NIO的數(shù)據(jù)讀寫,讀取更是使用了內(nèi)存映射,相當(dāng)于讀寫內(nèi)存的速率;
- 支持獲取緩存大小和個數(shù);
- 支持移除某個緩存和清除所有緩存;
- 還有就是誰用誰知道有多爽。
API
緩存相關(guān)→CacheUtils.java→Test
getInstance : 獲取緩存實例
put : 緩存中寫入數(shù)據(jù)
getBytes : 緩存中讀取字節(jié)數(shù)組
getString : 緩存中讀取String
getJSONObject : 緩存中讀取JSONObject
getJSONArray : 緩存中讀取JSONArray
getBitmap : 緩存中讀取Bitmap
getDrawable : 緩存中讀取Drawable
getParcelable : 緩存中讀取Parcelable
getSerializable: 緩存中讀取Serializable
getCacheSize : 獲取緩存大小
getCacheCount : 獲取緩存?zhèn)€數(shù)
remove : 根據(jù)鍵值移除緩存
clear : 清除所有緩存
Usage
CacheUtils mCacheUtils = CacheUtils.getInstance();
mCacheUtils.put("test_key1", "test value");
mCacheUtils.put("test_key2", "test value", 10);// 保存10s,10s后獲取返回null
mCacheUtils.put("test_key3", "test value", 12 * CacheUtils.HOUR);// 保存12小時,12小時后獲取返回null
mCacheUtils.getString("test_key1");
mCacheUtils.getString("test_key2", "defaultValue")// 存在且沒過期返回對應(yīng)值,否則返回defaultValue
更多用法參見單元測試
Source Code
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
import android.support.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* <pre>
* author: Blankj
* blog : http://blankj.com
* time : 2017/05/24
* desc : 緩存相關(guān)工具類
* </pre>
*/
public class CacheUtils {
private static final long DEFAULT_MAX_SIZE = Long.MAX_VALUE;
private static final int DEFAULT_MAX_COUNT = Integer.MAX_VALUE;
public static final int SEC = 1;
public static final int MIN = 60;
public static final int HOUR = 3600;
public static final int DAY = 86400;
private static Map<String, CacheUtils> sCacheMap = new HashMap<>();
private CacheManager mCacheManager;
/**
* 獲取緩存實例
* <p>在/data/data/com.xxx.xxx/cache/cacheUtils目錄</p>
* <p>緩存尺寸不限</p>
* <p>緩存?zhèn)€數(shù)不限</p>
*
* @return {@link CacheUtils}
*/
public static CacheUtils getInstance() {
return getInstance("", DEFAULT_MAX_SIZE, DEFAULT_MAX_COUNT);
}
/**
* 獲取緩存實例
* <p>在/data/data/com.xxx.xxx/cache/cacheName目錄</p>
* <p>緩存尺寸不限</p>
* <p>緩存?zhèn)€數(shù)不限</p>
*
* @param cacheName 緩存目錄名
* @return {@link CacheUtils}
*/
public static CacheUtils getInstance(String cacheName) {
return getInstance(cacheName, DEFAULT_MAX_SIZE, DEFAULT_MAX_COUNT);
}
/**
* 獲取緩存實例
* <p>在/data/data/com.xxx.xxx/cache/cacheUtils目錄</p>
*
* @param maxSize 最大緩存尺寸,單位字節(jié)
* @param maxCount 最大緩存?zhèn)€數(shù)
* @return {@link CacheUtils}
*/
public static CacheUtils getInstance(long maxSize, int maxCount) {
return getInstance("", maxSize, maxCount);
}
/**
* 獲取緩存實例
* <p>在/data/data/com.xxx.xxx/cache/cacheName目錄</p>
*
* @param cacheName 緩存目錄名
* @param maxSize 最大緩存尺寸,單位字節(jié)
* @param maxCount 最大緩存?zhèn)€數(shù)
* @return {@link CacheUtils}
*/
public static CacheUtils getInstance(String cacheName, long maxSize, int maxCount) {
if (isSpace(cacheName)) cacheName = "cacheUtils";
File file = new File(Utils.getContext().getCacheDir(), cacheName);
return getInstance(file, maxSize, maxCount);
}
/**
* 獲取緩存實例
* <p>在cacheDir目錄</p>
* <p>緩存尺寸不限</p>
* <p>緩存?zhèn)€數(shù)不限</p>
*
* @param cacheDir 緩存目錄
* @return {@link CacheUtils}
*/
public static CacheUtils getInstance(@NonNull File cacheDir) {
return getInstance(cacheDir, DEFAULT_MAX_SIZE, DEFAULT_MAX_COUNT);
}
/**
* 獲取緩存實例
* <p>在cacheDir目錄</p>
*
* @param cacheDir 緩存目錄
* @param maxSize 最大緩存尺寸,單位字節(jié)
* @param maxCount 最大緩存?zhèn)€數(shù)
* @return {@link CacheUtils}
*/
public static CacheUtils getInstance(@NonNull File cacheDir, long maxSize, int maxCount) {
final String cacheKey = cacheDir.getAbsoluteFile() + "_" + Process.myPid();
CacheUtils cache = sCacheMap.get(cacheKey);
if (cache == null) {
cache = new CacheUtils(cacheDir, maxSize, maxCount);
sCacheMap.put(cacheKey, cache);
}
return cache;
}
private CacheUtils(@NonNull File cacheDir, long maxSize, int maxCount) {
if (!cacheDir.exists() && !cacheDir.mkdirs()) {
throw new RuntimeException("can't make dirs in " + cacheDir.getAbsolutePath());
}
mCacheManager = new CacheManager(cacheDir, maxSize, maxCount);
}
///////////////////////////////////////////////////////////////////////////
// byte 讀寫
///////////////////////////////////////////////////////////////////////////
/**
* 緩存中寫入字節(jié)數(shù)組
*
* @param key 鍵
* @param value 值
*/
public void put(@NonNull String key, @NonNull byte[] value) {
put(key, value, -1);
}
/**
* 緩存中寫入字節(jié)數(shù)組
*
* @param key 鍵
* @param value 值
* @param saveTime 保存時長,單位:秒
*/
public void put(@NonNull String key, @NonNull byte[] value, int saveTime) {
if (value.length <= 0) return;
if (saveTime >= 0) value = CacheHelper.newByteArrayWithTime(saveTime, value);
File file = mCacheManager.getFileBeforePut(key);
CacheHelper.writeFileFromBytes(file, value);
mCacheManager.updateModify(file);
mCacheManager.put(file);
}
/**
* 緩存中讀取字節(jié)數(shù)組
*
* @param key 鍵
* @return 存在且沒過期返回對應(yīng)值,否則返回{@code null}
*/
public byte[] getBytes(@NonNull String key) {
return getBytes(key, null);
}
/**
* 緩存中讀取字節(jié)數(shù)組
*
* @param key 鍵
* @param defaultValue 默認(rèn)值
* @return 存在且沒過期返回對應(yīng)值,否則返回默認(rèn)值{@code defaultValue}
*/
public byte[] getBytes(@NonNull String key, byte[] defaultValue) {
final File file = mCacheManager.getFileIfExists(key);
if (file == null) return defaultValue;
byte[] data = CacheHelper.readFile2Bytes(file);
if (CacheHelper.isDue(data)) {
mCacheManager.removeByKey(key);
return defaultValue;
}
mCacheManager.updateModify(file);
return CacheHelper.getDataWithoutDueTime(data);
}
///////////////////////////////////////////////////////////////////////////
// String 讀寫
///////////////////////////////////////////////////////////////////////////
/**
* 緩存中寫入String
*
* @param key 鍵
* @param value 值
*/
public void put(@NonNull String key, @NonNull String value) {
put(key, value, -1);
}
/**
* 緩存中寫入String
*
* @param key 鍵
* @param value 值
* @param saveTime 保存時長,單位:秒
*/
public void put(@NonNull String key, @NonNull String value, int saveTime) {
put(key, CacheHelper.string2Bytes(value), saveTime);
}
/**
* 緩存中讀取String
*
* @param key 鍵
* @return 存在且沒過期返回對應(yīng)值,否則返回{@code null}
*/
public String getString(@NonNull String key) {
return getString(key, null);
}
/**
* 緩存中讀取String
*
* @param key 鍵
* @param defaultValue 默認(rèn)值
* @return 存在且沒過期返回對應(yīng)值,否則返回默認(rèn)值{@code defaultValue}
*/
public String getString(@NonNull String key, String defaultValue) {
byte[] bytes = getBytes(key);
if (bytes == null) return defaultValue;
return CacheHelper.bytes2String(bytes);
}
///////////////////////////////////////////////////////////////////////////
// JSONObject 讀寫
///////////////////////////////////////////////////////////////////////////
/**
* 緩存中寫入JSONObject
*
* @param key 鍵
* @param value 值
*/
public void put(@NonNull String key, @NonNull JSONObject value) {
put(key, value, -1);
}
/**
* 緩存中寫入JSONObject
*
* @param key 鍵
* @param value 值
* @param saveTime 保存時長,單位:秒
*/
public void put(@NonNull String key, @NonNull JSONObject value, int saveTime) {
put(key, CacheHelper.jsonObject2Bytes(value), saveTime);
}
/**
* 緩存中讀取JSONObject
*
* @param key 鍵
* @return 存在且沒過期返回對應(yīng)值,否則返回{@code null}
*/
public JSONObject getJSONObject(@NonNull String key) {
return getJSONObject(key, null);
}
/**
* 緩存中讀取JSONObject
*
* @param key 鍵
* @param defaultValue 默認(rèn)值
* @return 存在且沒過期返回對應(yīng)值,否則返回默認(rèn)值{@code defaultValue}
*/
public JSONObject getJSONObject(@NonNull String key, JSONObject defaultValue) {
byte[] bytes = getBytes(key);
if (bytes == null) return defaultValue;
return CacheHelper.bytes2JSONObject(bytes);
}
///////////////////////////////////////////////////////////////////////////
// JSONArray 讀寫
///////////////////////////////////////////////////////////////////////////
/**
* 緩存中寫入JSONArray
*
* @param key 鍵
* @param value 值
*/
public void put(@NonNull String key, @NonNull JSONArray value) {
put(key, value, -1);
}
/**
* 緩存中寫入JSONArray
*
* @param key 鍵
* @param value 值
* @param saveTime 保存時長,單位:秒
*/
public void put(@NonNull String key, @NonNull JSONArray value, int saveTime) {
put(key, CacheHelper.jsonArray2Bytes(value), saveTime);
}
/**
* 緩存中讀取JSONArray
*
* @param key 鍵
* @return 存在且沒過期返回對應(yīng)值,否則返回{@code null}
*/
public JSONArray getJSONArray(@NonNull String key) {
return getJSONArray(key, null);
}
/**
* 緩存中讀取JSONArray
*
* @param key 鍵
* @param defaultValue 默認(rèn)值
* @return 存在且沒過期返回對應(yīng)值,否則返回默認(rèn)值{@code defaultValue}
*/
public JSONArray getJSONArray(@NonNull String key, JSONArray defaultValue) {
byte[] bytes = getBytes(key);
if (bytes == null) return defaultValue;
return CacheHelper.bytes2JSONArray(bytes);
}
///////////////////////////////////////////////////////////////////////////
// Bitmap 讀寫
///////////////////////////////////////////////////////////////////////////
/**
* 緩存中寫入Bitmap
*
* @param key 鍵
* @param value 值
*/
public void put(@NonNull String key, @NonNull Bitmap value) {
put(key, value, -1);
}
/**
* 緩存中寫入Bitmap
*
* @param key 鍵
* @param value 值
* @param saveTime 保存時長,單位:秒
*/
public void put(@NonNull String key, @NonNull Bitmap value, int saveTime) {
put(key, CacheHelper.bitmap2Bytes(value), saveTime);
}
/**
* 緩存中讀取Bitmap
*
* @param key 鍵
* @return 存在且沒過期返回對應(yīng)值,否則返回{@code null}
*/
public Bitmap getBitmap(@NonNull String key) {
return getBitmap(key, null);
}
/**
* 緩存中讀取Bitmap
*
* @param key 鍵
* @param defaultValue 默認(rèn)值
* @return 存在且沒過期返回對應(yīng)值,否則返回默認(rèn)值{@code defaultValue}
*/
public Bitmap getBitmap(@NonNull String key, Bitmap defaultValue) {
byte[] bytes = getBytes(key);
if (bytes == null) return defaultValue;
return CacheHelper.bytes2Bitmap(bytes);
}
///////////////////////////////////////////////////////////////////////////
// Drawable 讀寫
///////////////////////////////////////////////////////////////////////////
/**
* 緩存中寫入Drawable
*
* @param key 鍵
* @param value 值
*/
public void put(@NonNull String key, @NonNull Drawable value) {
put(key, CacheHelper.drawable2Bytes(value));
}
/**
* 緩存中寫入Drawable
*
* @param key 鍵
* @param value 值
* @param saveTime 保存時長,單位:秒
*/
public void put(@NonNull String key, @NonNull Drawable value, int saveTime) {
put(key, CacheHelper.drawable2Bytes(value), saveTime);
}
/**
* 緩存中讀取Drawable
*
* @param key 鍵
* @return 存在且沒過期返回對應(yīng)值,否則返回{@code null}
*/
public Drawable getDrawable(@NonNull String key) {
return getDrawable(key, null);
}
/**
* 緩存中讀取Drawable
*
* @param key 鍵
* @param defaultValue 默認(rèn)值
* @return 存在且沒過期返回對應(yīng)值,否則返回默認(rèn)值{@code defaultValue}
*/
public Drawable getDrawable(@NonNull String key, Drawable defaultValue) {
byte[] bytes = getBytes(key);
if (bytes == null) return defaultValue;
return CacheHelper.bytes2Drawable(bytes);
}
///////////////////////////////////////////////////////////////////////////
// Parcelable 讀寫
///////////////////////////////////////////////////////////////////////////
/**
* 緩存中寫入Parcelable
*
* @param key 鍵
* @param value 值
*/
public void put(@NonNull String key, @NonNull Parcelable value) {
put(key, value, -1);
}
/**
* 緩存中寫入Parcelable
*
* @param key 鍵
* @param value 值
* @param saveTime 保存時長,單位:秒
*/
public void put(@NonNull String key, @NonNull Parcelable value, int saveTime) {
put(key, CacheHelper.parcelable2Bytes(value), saveTime);
}
/**
* 緩存中讀取Parcelable
*
* @param key 鍵
* @param creator 建造器
* @return 存在且沒過期返回對應(yīng)值,否則返回{@code null}
*/
public <T> T getParcelable(@NonNull String key, @NonNull Parcelable.Creator<T> creator) {
return getParcelable(key, creator, null);
}
/**
* 緩存中讀取Parcelable
*
* @param key 鍵
* @param creator 建造器
* @param defaultValue 默認(rèn)值
* @return 存在且沒過期返回對應(yīng)值,否則返回默認(rèn)值{@code defaultValue}
*/
public <T> T getParcelable(@NonNull String key, @NonNull Parcelable.Creator<T> creator, T defaultValue) {
byte[] bytes = getBytes(key);
if (bytes == null) return defaultValue;
return CacheHelper.bytes2Parcelable(bytes, creator);
}
///////////////////////////////////////////////////////////////////////////
// Serializable 讀寫
///////////////////////////////////////////////////////////////////////////
/**
* 緩存中寫入Serializable
*
* @param key 鍵
* @param value 值
*/
public void put(@NonNull String key, @NonNull Serializable value) {
put(key, value, -1);
}
/**
* 緩存中寫入Serializable
*
* @param key 鍵
* @param value 值
* @param saveTime 保存時長,單位:秒
*/
public void put(@NonNull String key, @NonNull Serializable value, int saveTime) {
put(key, CacheHelper.serializable2Bytes(value), saveTime);
}
/**
* 緩存中讀取Serializable
*
* @param key 鍵
* @return 存在且沒過期返回對應(yīng)值,否則返回{@code null}
*/
public Object getSerializable(@NonNull String key) {
return getSerializable(key, null);
}
/**
* 緩存中讀取Serializable
*
* @param key 鍵
* @param defaultValue 默認(rèn)值
* @return 存在且沒過期返回對應(yīng)值,否則返回默認(rèn)值{@code defaultValue}
*/
public Object getSerializable(@NonNull String key, Object defaultValue) {
byte[] bytes = getBytes(key);
if (bytes == null) return defaultValue;
return CacheHelper.bytes2Object(getBytes(key));
}
/**
* 獲取緩存大小
* <p>單位:字節(jié)</p>
*
* @return 緩存大小
*/
public long getCacheSize() {
return mCacheManager.getCacheSize();
}
/**
* 獲取緩存?zhèn)€數(shù)
*
* @return 緩存?zhèn)€數(shù)
*/
public int getCacheCount() {
return mCacheManager.getCacheCount();
}
/**
* 根據(jù)鍵值移除緩存
*
* @param key 鍵
* @return {@code true}: 移除成功<br>{@code false}: 移除失敗
*/
public boolean remove(@NonNull String key) {
return mCacheManager.removeByKey(key);
}
/**
* 清除所有緩存
*
* @return {@code true}: 清除成功<br>{@code false}: 清除失敗
*/
public boolean clear() {
return mCacheManager.clear();
}
private class CacheManager {
private final AtomicLong cacheSize;
private final AtomicInteger cacheCount;
private final long sizeLimit;
private final int countLimit;
private final Map<File, Long> lastUsageDates = Collections.synchronizedMap(new HashMap<File, Long>());
private final File cacheDir;
private CacheManager(File cacheDir, long sizeLimit, int countLimit) {
this.cacheDir = cacheDir;
this.sizeLimit = sizeLimit;
this.countLimit = countLimit;
cacheSize = new AtomicLong();
cacheCount = new AtomicInteger();
calculateCacheSizeAndCacheCount();
}
private void calculateCacheSizeAndCacheCount() {
new Thread(new Runnable() {
@Override
public void run() {
int size = 0;
int count = 0;
final File[] cachedFiles = cacheDir.listFiles();
if (cachedFiles != null) {
for (File cachedFile : cachedFiles) {
size += cachedFile.length();
count += 1;
lastUsageDates.put(cachedFile, cachedFile.lastModified());
}
cacheSize.getAndAdd(size);
cacheCount.getAndAdd(count);
}
}
}).start();
}
private long getCacheSize() {
return cacheSize.get();
}
private int getCacheCount() {
return cacheCount.get();
}
private File getFileBeforePut(String key) {
File file = new File(cacheDir, String.valueOf(key.hashCode()));
if (file.exists()) {
cacheCount.addAndGet(-1);
cacheSize.addAndGet(-file.length());
}
return file;
}
private File getFileIfExists(String key) {
File file = new File(cacheDir, String.valueOf(key.hashCode()));
if (!file.exists()) return null;
return file;
}
private void put(File file) {
cacheCount.addAndGet(1);
cacheSize.addAndGet(file.length());
while (cacheCount.get() > countLimit || cacheSize.get() > sizeLimit) {
cacheSize.addAndGet(-removeOldest());
cacheCount.addAndGet(-1);
}
}
private void updateModify(File file) {
Long millis = System.currentTimeMillis();
file.setLastModified(millis);
lastUsageDates.put(file, millis);
}
private boolean removeByKey(String key) {
File file = getFileIfExists(key);
if (file == null) return true;
if (!file.delete()) return false;
cacheSize.addAndGet(-file.length());
cacheCount.addAndGet(-1);
lastUsageDates.remove(file);
return true;
}
private boolean clear() {
File[] files = cacheDir.listFiles();
if (files == null || files.length <= 0) return true;
boolean flag = true;
for (File file : files) {
if (!file.delete()) {
flag = false;
continue;
}
cacheSize.addAndGet(-file.length());
cacheCount.addAndGet(-1);
lastUsageDates.remove(file);
}
if (flag) {
lastUsageDates.clear();
cacheSize.set(0);
cacheCount.set(0);
}
return flag;
}
/**
* 移除舊的文件
*
* @return 移除的字節(jié)數(shù)
*/
private long removeOldest() {
if (lastUsageDates.isEmpty()) return 0;
Long oldestUsage = Long.MAX_VALUE;
File oldestFile = null;
Set<Map.Entry<File, Long>> entries = lastUsageDates.entrySet();
synchronized (lastUsageDates) {
for (Map.Entry<File, Long> entry : entries) {
Long lastValueUsage = entry.getValue();
if (lastValueUsage < oldestUsage) {
oldestUsage = lastValueUsage;
oldestFile = entry.getKey();
}
}
}
if (oldestFile == null) return 0;
long fileSize = oldestFile.length();
if (oldestFile.delete()) {
lastUsageDates.remove(oldestFile);
return fileSize;
}
return 0;
}
}
private static class CacheHelper {
static final int timeInfoLen = 14;
private static byte[] newByteArrayWithTime(int second, byte[] data) {
byte[] time = createDueTime(second).getBytes();
byte[] content = new byte[time.length + data.length];
System.arraycopy(time, 0, content, 0, time.length);
System.arraycopy(data, 0, content, time.length, data.length);
return content;
}
/**
* 創(chuàng)建過期時間
*
* @param second 秒
* @return _$millis$_
*/
private static String createDueTime(int second) {
return String.format(Locale.getDefault(), "_$%010d$_", System.currentTimeMillis() / 1000 + second);
}
private static boolean isDue(byte[] data) {
long millis = getDueTime(data);
return millis != -1 && System.currentTimeMillis() > millis;
}
private static long getDueTime(byte[] data) {
if (hasTimeInfo(data)) {
String millis = new String(copyOfRange(data, 2, 12));
try {
return Long.parseLong(millis) * 1000;
} catch (NumberFormatException e) {
return -1;
}
}
return -1;
}
private static byte[] getDataWithoutDueTime(byte[] data) {
if (hasTimeInfo(data)) {
return copyOfRange(data, timeInfoLen, data.length);
}
return data;
}
private static byte[] copyOfRange(byte[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0) throw new IllegalArgumentException(from + " > " + to);
byte[] copy = new byte[newLength];
System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
return copy;
}
private static boolean hasTimeInfo(byte[] data) {
return data != null
&& data.length >= timeInfoLen
&& data[0] == '_'
&& data[1] == '$'
&& data[12] == '$'
&& data[13] == '_';
}
private static void writeFileFromBytes(File file, byte[] bytes) {
FileChannel fc = null;
try {
fc = new FileOutputStream(file, false).getChannel();
fc.write(ByteBuffer.wrap(bytes));
fc.force(true);
} catch (IOException e) {
e.printStackTrace();
} finally {
CloseUtils.closeIO(fc);
}
}
private static byte[] readFile2Bytes(File file) {
FileChannel fc = null;
try {
fc = new RandomAccessFile(file, "r").getChannel();
int size = (int) fc.size();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, size).load();
byte[] data = new byte[size];
mbb.get(data, 0, size);
return data;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
CloseUtils.closeIO(fc);
}
}
private static byte[] string2Bytes(String string) {
if (string == null) return null;
return string.getBytes();
}
private static String bytes2String(byte[] bytes) {
if (bytes == null) return null;
return new String(bytes);
}
private static byte[] jsonObject2Bytes(JSONObject jsonObject) {
if (jsonObject == null) return null;
return jsonObject.toString().getBytes();
}
private static JSONObject bytes2JSONObject(byte[] bytes) {
if (bytes == null) return null;
try {
return new JSONObject(new String(bytes));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static byte[] jsonArray2Bytes(JSONArray jsonArray) {
if (jsonArray == null) return null;
return jsonArray.toString().getBytes();
}
private static JSONArray bytes2JSONArray(byte[] bytes) {
if (bytes == null) return null;
try {
return new JSONArray(new String(bytes));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static byte[] parcelable2Bytes(Parcelable parcelable) {
if (parcelable == null) return null;
Parcel parcel = Parcel.obtain();
parcelable.writeToParcel(parcel, 0);
byte[] bytes = parcel.marshall();
parcel.recycle();
return bytes;
}
private static <T> T bytes2Parcelable(byte[] bytes, Parcelable.Creator<T> creator) {
if (bytes == null) return null;
Parcel parcel = Parcel.obtain();
parcel.unmarshall(bytes, 0, bytes.length);
parcel.setDataPosition(0);
T result = creator.createFromParcel(parcel);
parcel.recycle();
return result;
}
private static byte[] serializable2Bytes(Serializable serializable) {
if (serializable == null) return null;
ByteArrayOutputStream baos;
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(baos = new ByteArrayOutputStream());
oos.writeObject(serializable);
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
CloseUtils.closeIO(oos);
}
}
private static Object bytes2Object(byte[] bytes) {
if (bytes == null) return null;
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
return ois.readObject();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
CloseUtils.closeIO(ois);
}
}
private static byte[] bitmap2Bytes(Bitmap bitmap) {
if (bitmap == null) return null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}
private static Bitmap bytes2Bitmap(byte[] bytes) {
return (bytes == null || bytes.length == 0) ? null : BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
private static byte[] drawable2Bytes(Drawable drawable) {
return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable));
}
private static Drawable bytes2Drawable(byte[] bytes) {
return bytes == null ? null : Bitmap2Drawable(bytes2Bitmap(bytes));
}
private static Bitmap drawable2Bitmap(Drawable drawable) {
if (drawable == null) return null;
if (drawable instanceof BitmapDrawable) {
BitmapDrawable BitmapDrawable = (BitmapDrawable) drawable;
if (BitmapDrawable.getBitmap() != null) {
return BitmapDrawable.getBitmap();
}
}
Bitmap bitmap;
if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
private static Drawable Bitmap2Drawable(Bitmap Bitmap) {
return Bitmap == null ? null : new BitmapDrawable(Utils.getContext().getResources(), Bitmap);
}
}
private static boolean isSpace(String s) {
if (s == null) return true;
for (int i = 0, len = s.length(); i < len; ++i) {
if (!Character.isWhitespace(s.charAt(i))) {
return false;
}
}
return true;
}
}
Conclusion
好了,終點站到了,如果對本次旅途滿意的話,請給五星好評哦,畢竟老司機(jī)犧牲了很多時間才換來這么一份工具類,如果該工具類依賴其他工具類,都可以在我的Android開發(fā)人員不得不收集的代碼(持續(xù)更新中)中找到。