package com.bocai.net; import android.content.Context; import android.util.Log; import java.io.*; import java.util.Comparator; import java.util.PriorityQueue; public class FileCache { private static final long CACHE_CHECK_INTERVAL = 120000L; public static final String CACHE_ROOT = "cache"; private static final String LOG_TAG = "FileCache"; private static final long MAX_CACHE_SIZE = 5242880L; static final int READ_BUFFER_SIZE = 3072; private static File cacheRootDir = null; private static long cacheSize = 65535L; private static FileCache instance = new FileCache(); private static long lastCacheCheckTime = 65535L; private static LastModTimeComparator lastModTimeComp = new LastModTimeComparator(); private static class LastModTimeComparator implements Comparator<File> { public int compare(File file, File file1) { long l = file.lastModified(); long l1 = file1.lastModified(); return (int)(l - l1); } private LastModTimeComparator() { } } private static class FileSizeFilter implements FileFilter { public boolean accept(File file) { if(file.isFile()) { totalSize = totalSize + file.length(); } else { file.listFiles(this); } return false; } long totalSize; private FileSizeFilter() { totalSize = 0L; } } private FileCache() { } public static String absolutePath(String fileName) { File file = cacheRootDir; return (new File(file, fileName)).getAbsolutePath(); } public static long cacheSize() { return cacheSize; } public static void checkCache(boolean flag) { long l = System.currentTimeMillis(); if(!flag) { long l1 = lastCacheCheckTime + CACHE_CHECK_INTERVAL; if(l < l1) return; } Thread thread = new Thread(cacheChecker); thread.start(); if(!flag) return; try { thread.join(); } catch (InterruptedException e) { Log.w(LOG_TAG, e.getMessage()); } return; } public static boolean delete(File f) { if (f.exists() && f.isDirectory()) { if (f.listFiles().length == 0) { f.delete(); } else { File delFile[] = f.listFiles(); int i = f.listFiles().length; for (int j = 0; j < i; j++) { if (delFile[j].isDirectory()) { delete(delFile[j]); } delFile[j].delete(); } } } return true; } public static boolean fileExists(String fileName) { boolean flag; if(fileName == null) { flag = false; } else { File file = cacheRootDir; flag = (new File(file, fileName)).exists(); } return flag; } public static File getFile(String fileName) { String path,name; File answer; if(fileName == null){ return null; } int index = fileName.lastIndexOf('/'); if(index != -1){ path = fileName.substring(0,index); name = fileName.substring(index + 1); if(path == null){ answer = new File(cacheRootDir,name); }else{ File dir = new File(cacheRootDir,path); if(!dir.exists()){ dir.mkdir(); } answer = new File(dir,name); } }else{ answer = new File(cacheRootDir,fileName); } return answer; } public static FileCache getInstance() { return instance; } public static File getURL(String fileName) { return getFile(urlToFilePath(fileName)); } public static File putFile(String fileName, InputStream inputStream, int length) { File file = getFile(fileName);; FileOutputStream fileOutputStream = null; if(!file.exists()) { file.getParentFile().mkdirs(); try { file.createNewFile(); } catch (IOException e) { Log.w(LOG_TAG, e.getMessage()); } } try { fileOutputStream = new FileOutputStream(file); } catch (FileNotFoundException e) { Log.w(LOG_TAG,e.getMessage(),e); } int bufferSize = 3072; //3kb int byteRead = -1; byte data[] = new byte[bufferSize]; try{ do{ byteRead = inputStream.read(data); if(byteRead == -1){ break; } fileOutputStream.write(data, 0, byteRead); }while(true); inputStream.close(); fileOutputStream.flush(); fileOutputStream.close(); }catch(Exception e){ Log.w(LOG_TAG, e.getMessage(),e); } return file; } public static File putURL(String fileName, InputStream inputStream, int length) { return putFile(urlToFilePath(fileName), inputStream, length); } public static long sizeOfDirectory(File file) { FileSizeFilter fileSizeFilter = new FileSizeFilter(); file.listFiles(fileSizeFilter); return fileSizeFilter.totalSize; } public static boolean urlExists(String url) { return fileExists(urlToFilePath(url)); } public static String urlToFilePath(String url) { String filePath; if(url == null) { filePath = null; } else { int i = 0; if(url.startsWith("http://")) i = 7; int j = url.indexOf('/', i); if(j != -1) i = j; filePath = url.substring(i); } return filePath; } public void clear() { try { if(delete(cacheRootDir)) { return; } else { Log.w("FileCache", "Error deleting cache root directory!"); return; } } catch(Exception exception) { Log.e("FileCache", "Error clearing cache:", exception); } } public void finalize() { if(cacheRootDir != null) { clear(); } cacheRootDir = null; } public void initialize(Context context) { if(cacheRootDir == null) { cacheRootDir = context.getFileStreamPath("cache"); if(!cacheRootDir.exists()) cacheRootDir.mkdirs(); } } private static final Runnable cacheChecker = new Runnable() { PriorityQueue<File> agedFiles = null; private long visitFile(File paramFile, long paramLong) { if (paramFile.isDirectory()) { File[] arrayOfFile = paramFile.listFiles(); if(arrayOfFile.length == 0){ return paramLong; } for (int j = 0; j < arrayOfFile.length; j++) { File localFile = arrayOfFile[j]; if (localFile.isFile()) { this.agedFiles.add(localFile); long length = localFile.length(); paramLong += length; } else { paramLong = visitFile(localFile, paramLong); } } } else { this.agedFiles.add(paramFile); long length = paramFile.length(); paramLong += length; } return paramLong; } @Override public void run(){ if(agedFiles == null){ agedFiles = new PriorityQueue<File>(100,FileCache.lastModTimeComp); } FileCache.setCacheSize(visitFile(FileCache.cacheRootDir,0L)); String rate = FileCache.cacheSize + " / " + MAX_CACHE_SIZE; Log.i("FileCache", rate); if(FileCache.cacheSize <= MAX_CACHE_SIZE) { FileCache.setLastCacheCheckTime(System.currentTimeMillis()); this.agedFiles.clear(); } while((this.agedFiles.size() > 0) && (FileCache.cacheSize > 2621440L)){ File file = agedFiles.remove(); long length = file.length(); if(file.delete()){ FileCache.subSize(length); }else{ StringBuilder sb = new StringBuilder().append("Unable to delete cache file: "); sb.append(file.getAbsolutePath()); Log.w(LOG_TAG, sb.toString()); } } long lengthAfterTrim = visitFile(FileCache.cacheRootDir, 0L); FileCache.setLastCacheCheckTime(System.currentTimeMillis()); this.agedFiles.clear(); rate = lengthAfterTrim + " / " + MAX_CACHE_SIZE; Log.i(LOG_TAG, rate); } }; static long setCacheSize(long size){ cacheSize = size; return cacheSize; } static long subSize(long size){ cacheSize = cacheSize - size; return cacheSize; } static long setLastCacheCheckTime(long time){ lastCacheCheckTime = time; return lastCacheCheckTime; } }