1 如果直接编译的tokyocabinet java版的时候,./configure都不通过,因为缺少了编译时共享.h头文件,或者说,没有正确安装C语言版的tokyocabinet了.[如图]
2 其实,首先可以从官方网站http://tokyocabinet.sourceforge.net/下载C语言的包,如何已经安装了C语言版,则只需要 cp -r tc*.h /usr/loca/include .然后就能编译安装java版的tokyocabinet了,因为java版只是一个对C语言调用的桥接,真正实现的还是C语言的程序,当然,我这里用默认的安装,亦可以指定目录安装,不过一定要让它们处于系统的环境变量中,否则,编译可以通过但是运行的时候就报.so文件连接出错了...
3 安装编译完后,在java版的解压目录下会有一个example目录,那都是测试文件,大家
同时还提供了一个makeFile文件,大家直接在此目录下make就可以生成测试的类文件了.
OK,上面就简单说过了,以下是说一下关于java版本的原生API是不支持存取java的对象,所以这里需要做一些扩展.
主扩展类:
package com.kernaling.ext; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.HashMap; import tokyocabinet.HDB; /** * * @author kernaling.wong * @date 2009-09-07 * * 此类显示对tokyocabinet的一个应用与扩展,主要是支持多索引读取 * */ public class TokyoCache { private static volatile HashMaphMap = new HashMap (); private HDB hdb = new HDB(); private int MODE = HDB.OWRITER | HDB.OCREAT; private String path = ""; private TokyoCache(String path,int MODE){ this.path = path; if(!hdb.open(path, MODE)){ int ecode = hdb.ecode(); System.err.println("error code:" + ecode); } } public synchronized static TokyoCache getInstance(String path){ return getInstance(path, HDB.OWRITER | HDB.OCREAT); } public synchronized static TokyoCache getInstance(String path,int MODE){ if(path == null | path.trim().equals("")){ return null; } TokyoCache tc = hMap.get(path); if(tc == null){ tc = new TokyoCache(path,MODE); hMap.put(path, tc); } return tc; } /** * * @param key * @param value * @return 原生的API支持直接保存字符串 */ public boolean storeString(String key,String value){ if(key != null && !key.trim().equals("")){ return hdb.put(key , value); }else{ return false; } } /** * * @param key * @return 原生API支持直接读取字符串 */ public String getString(String key){ if(key != null && !key.trim().equals("")){ return hdb.get(key); }else{ return null; } } /** * * @param key * 移走key的记录 */ public void remove(String key){ if(key != null){ hdb.out(key); hdb.sync(); } } /** * * @param keys * @return 根据byte[]的key得到共value对象.原API并不支持,这里作了扩展 */ public Object getObject(byte keys[]){ if(keys == null){ return null; } byte valus[] = hdb.get(keys); if(valus == null){ return null; } ByteArrayInputStream bais = null; ObjectInputStream ois = null; try{ bais = new ByteArrayInputStream(valus); ois = new ObjectInputStream(bais); return ois.readObject(); }catch(Exception ex){ ex.printStackTrace(); }finally{ try{ if(bais != null){ bais.close(); } if(ois != null){ ois.close(); } }catch(Exception e){ e.printStackTrace(); } } return null; } /** * * @param keys * @param value * @return 原生API并不支持直接保存对象,这里作了扩展 */ public boolean storeObject(byte keys[],Object value){ if(keys == null || value == null ){ return false; } ByteArrayOutputStream baos = null; ObjectOutputStream oos = null; try{ baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(value); oos.flush(); return hdb.put(keys,baos.toByteArray()); }catch(Exception ex){ ex.printStackTrace(); }finally{ try{ if(baos != null){ baos.close(); } if(oos != null){ oos.close(); } }catch(Exception e){ e.printStackTrace(); } } return false; } /** * * @param key * 移走一个 key 的对象的value */ public void remove(byte key[]){ if(key != null){ hdb.out(key); hdb.sync(); } } /** * 关闭对应的路径的tokyocabinet的对象 */ public void close(){ TokyoCache tc = hMap.remove(path); if(tc != null){ tc.hdb.close(); } } /** * 清除所有的对象 */ public void clearAll(){ hdb.vanish(); hdb.sync(); } }
测试类:
package com.kernaling.test; import com.kernaling.ext.TokyoCache; public class Test { public static void main(String[] args) { TokyoCache tc = TokyoCache.getInstance("./Cache/test.tch"); //以下的构造方法中需要说明的是,open的模式中增加了HDB.ONOLCK 这个参数, //表示同一份索引文件可以有多个程序同时读取(默认多个不同程序读取同一份索引是会阻塞的) // HDB.ONOLCK 参考官方API文档,这个 参数表示 open without blocking ...... // TokyoCache tc = TokyoCache.getInstance("./Cache/test.tch",HDB.ONOLCK | HDB.OWRITER | HDB.OCREAT); /** * 以下演示了存取字符串 */ System.out.println("========example of store and get String=========="); tc.storeString("hello", "kernaling.wong"); System.out.println("before key:"+"hello"+"\tvalue:"+"kernaling.wong"+"\t"+" has benn stored"); String value = tc.getString("hello"); System.out.print("after key:"+"hello"+"\tvalue:" + value); System.out.println(); System.out.println(); /** * 以下演示了存取java对象 */ System.out.println("========example of store and get Object=========="); StoreObject so = new StoreObject("kernaling.wong"); System.out.println("befor key:" +so.getKey()+"\tvalues:" + so.prinrfInfo()); tc.storeObject(so.getKey().getBytes() , so); System.out.println("storing key:" + so.getKey()+" ..... "); StoreObject tSo = (StoreObject)tc.getObject(so.getKey().getBytes()); System.out.println("after key :" + tSo.getKey() +"\tvalues:" + tSo.prinrfInfo()); System.out.println(); System.out.println(); System.out.println("=============other operation below==================="); tc.remove("hello"); String tValue = tc.getString("hello"); System.out.println("key:"+"hello "+ "\tvalue:"+tValue); System.out.println("key:" + "hello" +" has been remove"); tc.remove(so.getKey().getBytes()); System.out.println("key:"+"hello "+ "\tvalue:"+tValue); System.out.println("key:" + "hello" +" has been remove"); System.out.println("Tc will be empty...."); tc.clearAll(); System.out.println("Tc will be closed"); tc.close(); } }
运行以上的测试类的程序应该显示如下:
保存的测试对象:
package com.kernaling.test; import java.io.Serializable; /** * * @author kernaling.wong * 保存的对象一定需要implements 序列化接口 */ public class StoreObject implements Serializable{ private String name = ""; public StoreObject(String name){ this.name = name; } public String getKey(){ return name; } public String prinrfInfo(){ return "java object values:" + name ; } }
后记:
这是对tokyocabinet的一个小扩展,当然很多功能都并未加上去,如:历遍,统计缓存里的个数等还未实现,有兴趣的朋友可以为其添加,同时这里的tokyocabinet暂时只是对key-value模式作一个扩展,table模式还未增加.我还提供了配置tokyocabinet运行环境的一个shell脚本,其他都是差不多根据官方文档来做的,测试环境 redhat 5.3 no xwindow jdk 1.6
欢迎转载,请注册出处与作者 kernaling.wong http://kernaling-wong.iteye.com/blog/464421