工作中經常需要處理對象的處理,有的時候還需要將對象保存到文件中做持久化。
特別是當不能使用數據庫的時候就特別需要一個簡單的對象集合的增刪改查操作,
於是就有了下面這個文件DB的工具類
package com.cc.fileDb; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /**單例模式的文件數據庫工具類*/ public class FileDb { private static final Logger log = LoggerFactory.getLogger(FileDb.class); private static FileDb single=null; private static Map<String,List<HashMap<String,String>>> cashs = new HashMap<String,List<HashMap<String,String>>>(); private String baseDir ; private FileDb(String baseDir){ this.baseDir = baseDir; File f = new File(baseDir); if (!f.exists()) { f.mkdirs(); } } /*初始化文件數據庫的工作目錄*/ public static synchronized FileDb getInstance(String baseDir) { if (single == null) { single = new FileDb(baseDir); } return single; } /*將文件對象初始化到內存*/ public synchronized List<HashMap<String,String>> getDataList(String dbName) throws Exception{ List<HashMap<String,String>> res = new ArrayList<HashMap<String,String>>(); if(single == null) throw new Exception("init db first!"); if(cashs.containsKey(dbName))return cashs.get(dbName); ObjectInputStream in = null; File f = new File(baseDir+dbName); try{ if(!f.exists())f.createNewFile(); in = new ObjectInputStream(new FileInputStream(baseDir+dbName)); while(f.length()>0){ Object o = in.readObject(); if(!(o instanceof HashMap))continue; HashMap<String, String> map = (HashMap<String,String>) o; res.add(map); } }catch(EOFException ex){ }catch(Exception e){ e.printStackTrace(); log.error(e.getLocalizedMessage()); }finally{ try { cashs.put(dbName, res); if(in!=null)in.close(); } catch (IOException e) { log.error(e.getLocalizedMessage()); } } return res; } /*添加map對象到數據庫*/ public synchronized boolean add(String dbName,HashMap<String,String> data) throws Exception{ if(!cashs.containsKey(dbName))cashs.put(dbName, getDataList(dbName)); cashs.get(dbName).add(data); return true; } /*根據條件查找符合的第一個map對象*/ public synchronized HashMap<String,String> getFirst(String dbName,HashMap<String,String> param) throws Exception{ if(!cashs.containsKey(dbName))cashs.put(dbName, getDataList(dbName)); if(cashs.get(dbName).size()==0)return null; boolean fit = true; for(HashMap<String,String> item : cashs.get(dbName)){ for(String key : param.keySet()){ if(!param.get(key).equals(item.get(key))){ fit = false; break; } } if(fit)return item; fit= true; } return null; } /*根據條件獲得全部符合的map對象*/ public synchronized List<HashMap<String,String>> getFits(String dbName,HashMap<String,String> param) throws Exception{ if(!cashs.containsKey(dbName))cashs.put(dbName, getDataList(dbName)); if(cashs.get(dbName).size()==0)return null; List<HashMap<String,String>> ls = new ArrayList<HashMap<String,String>>(); boolean fit = true; for(HashMap<String,String> item : cashs.get(dbName)){ if(param!=null&& !param.keySet().isEmpty())for(String key : param.keySet()){ if(!param.get(key).equals(item.get(key))){ fit = false; break; } } if(fit)ls.add(item); fit = true; } return ls; } /*update更新或保存對象*/ public synchronized boolean save(String dbName,HashMap<String,String> param,HashMap<String,String> data) throws Exception{ if(!cashs.containsKey(dbName))cashs.put(dbName, getDataList(dbName)); if(cashs.get(dbName).size()==0){ cashs.get(dbName).add(data); }else{ boolean fit = true; for(HashMap<String,String> item : cashs.get(dbName)){ if(param!=null&& !param.keySet().isEmpty()) for(String key : param.keySet()){ if(!param.get(key).equals(item.get(key))){ fit = false; break; } } if(fit){ if(data!=null&& !data.keySet().isEmpty()) for(String key : data.keySet()){ item.put(key, data.get(key)); } } fit = true; } } return true; } /*根據條件刪除map信息*/ public synchronized boolean delete(String dbName,HashMap<String,String> param) throws Exception{ if(!cashs.containsKey(dbName))cashs.put(dbName, getDataList(dbName)); if(cashs.get(dbName).size()==0){ return false; }else{ boolean fit = true; List<Integer> dels = new ArrayList<Integer>(); int i = 0; for(HashMap<String,String> item : cashs.get(dbName)){ if(param!=null&& !param.keySet().isEmpty()) for(String key : param.keySet()){ if(!param.get(key).equals(item.get(key))){ fit = false; break; } } if(fit){ dels.add(i); } fit = true; i++; } Iterator<Integer> mm = dels.iterator(); int j = 0; while(mm.hasNext()){ int k = mm.next() ; k -= j; cashs.get(dbName).remove(k); j++; } } return true; } /*將map數組信息刷入到文件中*/ public synchronized boolean commit(String dbName) throws Exception{ if(!cashs.containsKey(dbName))return false; File file = new File(baseDir+dbName); ObjectOutputStream out = null; log.info("commit"+dbName+".size="+cashs.get(dbName).size()); if(cashs.get(dbName)!=null&&cashs.get(dbName).size()>0){ FileOutputStream fos = new FileOutputStream(file, false); out = new ObjectOutputStream(fos); for(HashMap<String,String> o: cashs.get(dbName)){ out.writeObject(o); } fos.close(); if(out!=null)out.close(); }else{ log.info("commit["+baseDir+dbName+"].size="+cashs.get(dbName).size()+file.delete()); } return true; } /*清空內存中的文件數據庫對象*/ public synchronized boolean clear(String dbName) throws Exception{ if(!cashs.containsKey(dbName)){ log.info("uninit "+dbName); return false; } cashs.put(dbName, new ArrayList<HashMap<String,String>>()); return true; } } class MyObjectOutputStream extends ObjectOutputStream{ public MyObjectOutputStream() throws IOException { super(); } public MyObjectOutputStream(OutputStream out) throws IOException { super(out); } @Override protected void writeStreamHeader() throws IOException { return; } /** * 對象轉數組 * @param obj * @return */ public static byte[] toByteArray (Object obj) { byte[] bytes = null; ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(obj); oos.flush(); bytes = bos.toByteArray (); oos.close(); bos.close(); } catch (IOException ex) { ex.printStackTrace(); } return bytes; } /** * 數組轉對象 * @param bytes * @return */ public static Object toObject (byte[] bytes) { Object obj = null; try { ByteArrayInputStream bis = new ByteArrayInputStream (bytes); ObjectInputStream ois = new ObjectInputStream (bis); obj = ois.readObject(); ois.close(); bis.close(); } catch (IOException ex) { ex.printStackTrace(); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } return obj; } }
實現了簡單的文件的操作和對象處理的增刪改查,下面是測試用例
package com.cc.fileDb; import java.util.HashMap; import java.util.List; /** * Hello world! * */ public class App { public static void main( String[] args ) { FileDb fd = FileDb.getInstance("D:\\"); try { // for(HashMap<String,String> map : fd.getDataList("test.db")){ // System.out.println(map.get("index")+"==>"+map.get("name")); // } // fd.getDataList("test.db");//初始化數據 // fd.clear("test.db");//清空數據 for(int i =0;i<10;i++){ HashMap<String, String> data = new HashMap<String, String>() ; data.put("name", "AA:"+System.currentTimeMillis()); data.put("index", "I:"+i); fd.add("test.db", data ); } fd.commit("test.db");//將數據刷入文件 Thread.sleep(1000); // for(HashMap<String,String> map : fd.getDataList("test.db")){ // System.out.println(map.get("index")+"==>"+map.get("name")); // } HashMap<String, String> param = new HashMap<String, String>() ; param.put("index", "I:"+4); //修改內容 HashMap<String, String> data = new HashMap<String, String>(); data.put("index", "I:"+4); data.put("name", "hello world!"); data.put("ext", "201702091111"); fd.save("test.db", param, data); //查找內容 HashMap<String, String> map0 = fd.getFirst("test.db", param ); System.out.println(map0 .get("index")+"==>"+map0.get("name")); param.put("index", "I:"+5); //刪除內容 fd.delete("test.db", param); for(HashMap<String,String> map : fd.getDataList("test.db")){ System.out.println(map.get("index")+"==>"+map.get("name")); } param.put("index", "I:"+6); //獲取全部符合的內容 List<HashMap<String, String>> maps = fd.getFits("test.db", param ); for(HashMap<String, String> map : maps) System.out.println(map.get("name") ); fd.commit("test.db"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
好了,以后就可以將文件作為map集合數據的存儲操作了,同事只要對上述代碼中的帶修改為你自己的可序列化對象就可以實現你自己對象的文件數據庫了,做增刪改查也十分方便。
雖然實現了簡單的線程安全處理,不過還沒有做過線程安全的測試,如果在用的過程中有遇到任何問題,歡迎聯系我!