快速Java二进制格式解析

Yol*_*ore 5 java binary performance parsing

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

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

    | uint16_t | 4 bits | 4 bits | uint16_t |
    
    Run Code Online (Sandbox Code Playgroud)

    应该变得像

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

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

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

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

我搜索过谷歌,我搜索过StackOverflow.这个问题 - 如何解析/编码二进制消息格式? - 解决相同的问题,但有一些我没有的奇怪的非对齐位要求.

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

apa*_*gin 6

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


Gav*_*vin 0

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

也许这只是“本地化”适合您的用例的罕见情况之一?