`
请输入用户名
  • 浏览: 45893 次
  • 性别: Icon_minigender_1
  • 来自: martian
社区版块
存档分类
最新评论

java文件读取缓存类

 
阅读更多
流程图:
<pre>
  final 外部对象操作时:
  通过文件名 -- 在map中找到对应 -- 判断是否修改 --否 -- 返回缓存对象
                             |
                             是
                             |
          调用reload,根据传入的handler进行reload,更新缓存对象,更新操作时间
  </pre>

主要根据的是文件的修改时间,如果本次读取时的修改时间和缓存中的时间相同,则直接返回缓存,否则的话就重新加载文件,更新缓存和时间
重新加载文件的时候需要传入一个 ReloadHandler,以实现更大的灵活性(策略模式),返回一个新的对象并缓存
(待完善:自动清理功能
     方案1:FIFO 最简单,但是效率比较低
     方案2:访问次数多的留下,少的去掉
     方案3:记得大学里编译原理有个更好的方式,忘记了。
)暂时用FIFO

接口:
/**
 * 重新加载接口
 * @author qihuan
 *
 */
public interface ReloadHandler {
    /**
     * 分析文件
     * @return 要缓存的内容
     */
    Object processNewCache() throws Exception;
}

缓存类:
/**
 * <pre>
 * final 外部对象操作时: 
 * 通过文件名 -- 在map中找到对应 -- 判断是否修改 --否 -- 返回缓存对象
 * 					| 
 * 					是
 *  					|
 *   		调用reload,根据传入的handler进行reload,更新缓存对象,更新操作时间
 * </pre>
 * @author qihuan
 */
public class FileCache {
    /** 缓存map */
    private static Map<String, CacheElement> cacheMap = new HashMap<String, CacheElement>();
    private static FileCache fileCache;
    private static final int MAX_SIZE = 20;
    private Queue<String> fileQueue = new LinkedList<String>();
    
    /**
     * 单例,多线程一样自信
     * 
     * @return fileCache单例
     */
    public static FileCache getInstance(){
	if(null == fileCache){
	    fileCache = new FileCache();
	}
	return fileCache;
    }
    /**
     * 获取缓存对象
     * 获取缓存,如果文件被修改,则重新加载最近配置,内存中超过20个文件缓存,会自动清理
     * @param fileName
     * @return
     * @throws Exception 
     */
    public Object getCache(String fileName,ReloadHandler handler) throws Exception{
	fileName = fileName.trim();
	if(isModified(fileName)){
	    reLoad(fileName,handler);
	}
	return cacheMap.get(fileName).getCache();
    }
    
    /**
     * 重新加载
     * @param fileName 
     * @param handler
     * @throws Exception 
     */
    private void reLoad(String fileName, ReloadHandler handler) throws Exception {
	CacheElement ele = cacheMap.get(fileName);
	if(null == ele){
	    //文件没有加载过
	    ele = new CacheElement();
	    //设置File对象
	    ele.setFile(new File(fileName));
	    cacheMap.put(fileName, ele);
	    //添加新的缓存,记录到队列中
	    if(!fileQueue.contains(fileName)){
		//如果队列中没记录这个,则试图添加并进行清理
		cacheClean();
		fileQueue.add(fileName);
	    }
	}
	//更新缓存
	ele.setCache(handler.processNewCache());
	//更新修改时间
	ele.setLastEditTime(ele.getFile().lastModified());
	
    }
    /**
     * 判断是否已经修改
     * 
     * @param diXmlName
     * @return
     */
    private boolean isModified(String fileName) {

	CacheElement cacheElement = cacheMap.get(fileName);
	if (null == cacheElement) {
	    //配置文件没有被加载过
	    return true;
	}
	if (cacheElement.getFile().lastModified() != cacheElement.getLastEditTime()) {
	    //被修改
	    return true;
	}
	// 没有变化
	return false;
    }
    
    /**
     * FIFO 清理缓存,
     */
    private void cacheClean(){
	//缓存超过限制之后,进行清理
	if(fileQueue.size() >= MAX_SIZE ){
	    String fileName = fileQueue.poll();
	    cacheMap.put(fileName, null);
	    cacheMap.remove(fileName);
	}
    }
    
    //私有构造
    private FileCache(){}
    /**
     * 缓存元素
     * 
     * @author qihuan
     */
    class CacheElement {

	public long   lastEditTime;
	public File   file;
	public Object cache;

	public long getLastEditTime() {

	    return lastEditTime;
	}

	public void setLastEditTime(long lastEditTime) {

	    this.lastEditTime = lastEditTime;
	}

	//setters and getters...
    }
}



缓存一个文件的测试类:
测试类:
/**
* 每2秒去获取一次缓存日期,如果文件更新了,则会返回新的缓存日期
*/
public class CacheTest {

    @Test
    public void getFileContent() {

      int count = 10;
      while (count-- > 0) {
          try {
            getCache();
            TimeUnit.SECONDS.sleep(2);
          } catch (InterruptedException e) {
            e.printStackTrace();
          } catch (Exception e) {
            e.printStackTrace();
          }
      }
    }

    private void getCache() throws Exception {

      Date date = (Date)FileCache.getInstance().getCache("e:/1.txt", new ReloadHandler() {

          @Override
          public Object processNewCache() {
            System.out.print("find change  ");
            return new Date();
          }
      });
      System.out.println(date);
    }
}
output:
find change  Wed Dec 28 15:25:46 CST 2011 (初始化)
Wed Dec 28 15:25:46 CST 2011
Wed Dec 28 15:25:46 CST 2011
Wed Dec 28 15:25:46 CST 2011
Wed Dec 28 15:25:46 CST 2011
find change  Wed Dec 28 15:25:56 CST 2011
Wed Dec 28 15:25:56 CST 2011
Wed Dec 28 15:25:56 CST 2011
Wed Dec 28 15:25:56 CST 2011
Wed Dec 28 15:25:56 CST 2011



实际应用时代码片段
    /**
     * 获取配置
     * 
     * @param diXmlName
     *            接口配置文件名称
     * @param diXmlPath
     *            接口配置文件完整路径
     * @return
     * @throws DataConfigException
     */
    public DataInterfaceConfig getConfig(final String diXmlName) throws DataConfigException {
	DataInterfaceConfig config = null;
	final String diXmlPath = Constant.CONFIG_HOME + File.separator + "diConfig" + File.separator + diXmlName;
	try {
	    config = (DataInterfaceConfig) FileCache.getInstance().getCache(diXmlPath, new ReloadHandler() {
	        
	        @Override
	        public Object processNewCache() throws Exception {
	    
	            //重新加载配置文件
		    return DataInterfaceConfigParser.parser(diXmlPath);
	        }
	    });
	} catch (Exception e) {
	    throw new DataConfigException(e);
	}
	return config;
    }

    /**
     * 从缓存中 根据code  获取 接口配置
     * @param code
     * @return
     * @throws BizException 
     */
    public DataInterface getDataInterfaceByCode(String code) throws BizException{
	Map<String,DataInterface> dataInterface = null;
	//获取缓存
	    try {
		dataInterface = (Map<String,DataInterface>) FileCache.getInstance().getCache(Constant.CONFIG_HOME + File.separator + Constant.DIGROUP_CONFIG_XML, new ReloadHandler() {
		    
		    @Override
		    public Object processNewCache() throws Exception {
				return getAllConfigInGroup();
		    }
		});
	    } catch (Exception e) {
		throw new BizException(e);
	    }
	return dataInterface.get(code);
    }

分享到:
评论

相关推荐

    java 通过文件实现缓存

    java实现缓存可以通过读取本地文件的方式实现,改代码就是通过读取本地文件实现缓存的简单例子

    Java读取json文件,并转化为map取值

    Java读取json文件,并转化为map取值,并附上相关jar包

    JAVA NIO 按行读取大文件,支持 GB级别

    本类,是专门为了处理大文件,按行读取开发的类。 采用读文件的缓存 fbb 1024*5 行缓存 bb 256 字节 设计思想: 每次通过nio读取字节到 fbb中 然后对fbb自己中的内容进行行判断即 10 回车 13 行号 0 文件...

    JAVA NIO 按行读取大文件支持 GB级别-修正版

    本类,是专门为了处理大文件,按行读取开发的类。 采用读文件的缓存 fbb 1024*5 行缓存 bb 256 字节 设计思想: 每次通过nio读取字节到 fbb中 然后对fbb自己中的内容进行行判断即 10 回车 13 行号 0 文件结束 ...

    java实现读取word文件并且上传到数据库

    用java语言实现对word表格操作,实现自动批量往数据库中插入数据,节省插入数据时间。

    Java读存二进制大文件块

    Java读存大块二进制资料文件,java.io 包中提供了BufferedInputStream 和BufferedOutputStream 类来缓存的读写流。但是读写大块的数据文件时,使用这两个类的效果并不是很好。本例演示了如何自定义缓存区,并使用不...

    用JAVA实现缓冲多线程无阻塞读取远程文件.pdf

    用JAVA实现缓冲多线程无阻塞读取远程文件.pdf

    Java读取和写入二进制大文件的方法.rar

    Java读取和写入二进制大文件的方法,应该说是一个基于二进制的大文件块,演示了如何自定义缓存区,并使用不具有缓冲功能的DataInputStream 和DataOutputStream 类来读写二进制的大文件块数据,运行效果请参见如下...

    JAVA上百实例源码以及开源项目

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    利用缓存机制快速读取XML文件数据

    每次访问的时候先判断一下要访问的文件实体有没有被更新,如果没有被更新,就直接从缓存中将想要的数据读出来,当然如果文件被更新了,那只好老老实实的解析文件读出想要的数据。管理者对文件的修改次数毕竟是少数,...

    Java 实现AES之CBC/CFB模式的加密解密源码

    完整能运行的java AES源代码,需要官网手工下载local_policy.jar 和 US_export_policy.jar文件覆盖java安装目录的文件,才能使用CFB模式。下载地址为: ...

    Java整理的基础工具类项目

    Java整理的基础工具类项目 Spring+Redis实现无缝读写分离插入(com.shawntime.utils.rwdb) Redis操作封装(com.shawntime.utils.cache.redis) Redis分布式锁实现(com.shawntime.utils.lock) 读写锁控制强制读取...

    JAVA上百实例源码以及开源项目源代码

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    Java思维导图xmind文件+导出图片

    CDN静态文件访问 分布式存储 分布式搜索引擎 应用发布与监控 应用容灾及机房规划 系统动态扩容 分布式架构策略-分而治之 从简到难,从网络通信探究分布式通信原理 基于消息方式的系统间通信 理解通信协议...

    java开源包11

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包4

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包6

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包9

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

Global site tag (gtag.js) - Google Analytics