我经常在我们的Java EE应用程序套件中处理不同的二进制文件格式,即将它们读入到某些类结构中并将其写回。我需要进行以下操作:
- read single byte / short / int / long, sometimes different endianness (little/big)
read single bits in flags, i.e.
| uint16_t | 4 bits | 4 bits | uint16_t |
should become something like
a = stream.readUint16(); byte tmp = stream.readUint8(); b = (tmp & 0xf0) >> 4; c = (tmp & 0xf) d = stream.readUint16();
read strings in different encodings, sometimes dynamic length strings with something like a
\0
ending- seeking in a file (to find data dictated by some offsets read), knowing current position, knowing how much have I left to parse in current data block
- last, but not least, it should be fast; at least not an order of magnitude slower than declaring a
typedef struct
in C, reading it as a block and typecasting it in memory
- `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? - 解决了相同的问题,但有奇怪的非对齐位要求,而我没有这个要求。
所以,问题是 - 我是否忽略了什么,有没有更好的解决方案来解决我提到的所有问题?