Java基于文件的对象存储
工作中经常需要处理对象的处理,有的时候还需要将对象保存到文件中做持久化。
特别是当不能使用数据库的时候就特别需要一个简单的对象集合的增删改查操作,
于是就有了下面这个文件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集合数据的存储操作了,同事只要对上述代码中的带修改为你自己的可序列化对象就可以实现你自己对象的文件数据库了,做增删改查也十分方便。
虽然实现了简单的线程安全处理,不过还没有做过线程安全的测试,如果在用的过程中有遇到任何问题,欢迎联系我!
Java基于文件的对象存储的更多相关文章
- 基于openshift+华为对象存储的CSI开发
目录 需求来源 环境准备 代码修改 镜像下载 镜像生成 修改部署文件 部署CSI插件 CSI原理 核心原理 生命周期: 组件介绍 FAQ 参考: 需求来源 项目上目前使用的是openshift 3.1 ...
- java常量池与对象存储
一 数据存储位置 我们先来谈谈数据的存储位置,有五个地方可以存储数据 (1)寄存器:这是最快的存储区,因为它位于不同于其他存储区的地方- ...
- 基于七牛云对象存储,搭建一个自己专属的极简Web图床应用(手摸手的注释讲解核心部分的实现原理)
一个极简的Web图床应用,支持复制粘贴与拖拽上传图片 1.开发缘由 日常使用Vs Code编写markdown笔记与博客文章时,在文章中插入图片时发现非常不便 使用本地文件编写相对路径---没法直接复 ...
- java操作文件流对象
所有流对象 InputStream 字节流 FileInputStream 字节流 专门读写非文本文件的 BufferedInputStream 高效流 OutPutS ...
- 【分布式技术专题】「OSS中间件系列」Minio的文件服务的存储模型及整合Java客户端访问的实战指南
Minio的元数据 数据存储 MinIO对象存储系统没有元数据数据库,所有的操作都是对象级别的粒度的,这种做法的优势是: 个别对象的失效,不会溢出为更大级别的系统失效. 便于实现"强一致性& ...
- 【Linux】【Basis】块存储,文件存储,对象存储
1. 块存储: 定义:这种接口通常以QEMU Driver或者Kernel Module的方式存在,这种接口需要实现Linux的Block Device的接口或者QEMU提供的Block Driver ...
- 【巨杉数据库Sequoiadb】巨杉⼯具系列之一 | ⼤对象存储⼯具sdblobtool
近期,巨杉数据库正式推出了完整的SequoiaDB 工具包,作为辅助工具,更好地帮助大家使用和运维管理分布式数据库.为此,巨杉技术社区还将持续推出工具系列文章,帮助大家了解巨杉数据库丰富的工具矩阵. ...
- Github 29K Star的开源对象存储方案——Minio入门宝典
对象存储不是什么新技术了,但是从来都没有被替代掉.为什么?在这个大数据发展迅速地时代,数据已经不单单是简单的文本数据了,每天有大量的图片,视频数据产生,在短视频火爆的今天,这个数量还在增加.有数据表明 ...
- swift对象存储
swift对象存储 简介 OpenStack Object Storage(Swift)是OpenStack开源云计算项目的子项目之一,被称为对象存储,提供了强大的扩展性.冗余和持久性.对象存储,用于 ...
随机推荐
- Javascript 页面刷新
Javascript 页面刷新的实现代码收藏 1 2 3 4 5 6 7 8 history.go(0) location.reload() location=location location.as ...
- NRF24L01无线通讯模块驱动
NRF24L01 无线模块,采用的芯片是 NRF24L01,该芯片的主要特点如下: )2.4G 全球开放的 ISM 频段,免许可证使用. )最高工作速率 2Mbps,高校的 GFSK 调制,抗干扰能力 ...
- SGU 194 Reactor Cooling ——网络流
[题目分析] 无源汇上下界可行流. 上下界网络流的问题可以参考这里.↓ http://www.cnblogs.com/kane0526/archive/2013/04/05/3001108.html ...
- jquery遍历二维数组
function eachTowArray() { var ar = [[1,2,3],[4,5,6],[7,8,9]]; var result=""; //结果存放变量 ...
- sgu194 Reactor Cooling【无源汇有上下界可行流】
这是模板题了吧,先建立附加源汇,然后保留每个点的in-out,如果这个值是正的,那么就从附加源先这个点连一个边权为in-out的边,否则从这个点向附加汇连一条相反数的边,剩下题目中的边就用上界-下界连 ...
- Recovering a WiredTiger collection from a corrupt MongoDB installation
Reference: http://www.alexbevi.com/blog/2016/02/10/recovering-a-wiredtiger-collection-from-a-corrupt ...
- UVa 10986 - Sending email
题目大意:网络中有n个SMTP服务器,有m条电缆将它们相连,每条电缆传输信息需要一定的时间.现在给出信息的起点和终点,计算所需的最小时间. 有权图上的单源最短路问题(Single-Source Sho ...
- gridview里item是textView、Button单击事件相应,以及按下效果的取去除
1.响应事件的区别: gridview的item是textView的时候,gridview的itemonclick事件可以正常相应,但是换了Button后不能,原因如下: public class B ...
- 包含中文字符的NSString 转换为NSURL
转包含中文字符的NSString 转换为NSURL NSString中如果包括中文字符的话转换为NSURL得到的值为nil,在网上搜了下,用stringByAddingPercentEscapesUs ...
- sae中thinkphp使用smarty
因为最近在学thinkphp跟着做一个小商城. 没有使用thinkphp自带的think引擎,使用的是smarty引擎. 在sea中使用的时候出现了问题.已经是前几天的事了,问题图片没保存下来. 在网 ...