快速Java二进制格式解析

时间:2016-03-12 11:38:49

标签: java performance parsing binary

我经常在Java EE应用程序套件中处理不同的二进制文件格式,即读入某些类结构并将其写回。我需要进行以下操作:

  • 读取单字节/短/ int / long,有时不同的字节序(小/大)
  • 读取标志中的单个位,即

    | uint16_t | 4 bits | 4 bits | uint16_t |
    

    应该变得像

    a = stream.readUint16();
    byte tmp = stream.readUint8();
    b = (tmp & 0xf0) >> 4;
    c = (tmp & 0xf)
    d = stream.readUint16();
    
  • 读取不同编码的字符串,有时是动态长度字符串,类似于\0结尾

  • 在文件中搜索(查找由某些偏移读取所指示的数据),知道当前位置,知道我在当前数据块中解析了多少
  • 最后,但并非最不重要的是,它应该很快;至少不比在C中声明typedef struct慢一个数量级,将其作为块读取并在内存中进行类型转换

到目前为止,我已经分析了我的选项并发现有:

  • RandomAccessFile - 标准Java中最好的一个,具有正确的搜索和位置方法,字符串读取等,但由于缺少缓冲等操作,有时难以忍受。也没有对流的位级访问权限,也没有不同的字节顺序支持
  • FileInputStream - 只能读取单个字节,必须手工重建原始数据类型;没有寻求
  • *Reader相互作用 - 基本上,只能读取字节和字节数组,可以跳过,标记和重置,但如果多次搜索reset(); skip(seekAmount);
  • ,它们往往会泄漏内存
  • https://github.com/raydac/java-binary-block-parser - 几乎正是我正在寻找的 - 即格式的声明性规范然后,瞧,我有类,但它本质上是一个解释器,因此有两个主要问题:( a)在高要求的环境中速度很慢,(b)运行时生成的反射式风格存在多种类型安全问题
  • http://preon.codehaus.org/ - 有很多很棒的评论,但似乎不再开发,网站已关闭:(

我搜索了Google,我搜索过StackOverflow。这个问题 - How to parse/encode binary message formats? - 解决了同样的问题,但是我没有非奇怪的非对齐位要求。

所以,问题是 - 我是否忽略了某些问题,并且有更好的解决方案可以解决所有我提到过的问题?

2 个答案:

答案 0 :(得分:6)

ByteBuffer拥有您需要的一切 它也可能是纯Java中最快的选择(不包括JNI,sun.misc.Unsafe等)。

答案 1 :(得分:0)

我讨厌建议这个解决方案,但鉴于您似乎对如何在C中执行此操作有一些了解,您可以在C中构建一个适当函数的库,然后用JNI包装它并在您的应用程序中使用它

也许这只是极少数情况下“适合原生”的情况适合您的用例?