工作中经常需要处理对象的处理,有的时候还需要将对象保存到文件中做持久化。
特别是当不能使用数据库的时候就特别需要一个简单的对象集合的增删改查操作,
于是就有了下面这个文件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集合数据的存储操作了,同事只要对上述代码中的带修改为你自己的可序列化对象就可以实现你自己对象的文件数据库了,做增删改查也十分方便。
虽然实现了简单的线程安全处理,不过还没有做过线程安全的测试,如果在用的过程中有遇到任何问题,欢迎联系我!