我经常在Java EE应用程序套件中处理不同的二进制文件格式,即读入某些类结构并将其写回。我需要进行以下操作:
读取标志中的单个位,即
| 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
结尾
typedef struct
慢一个数量级,将其作为块读取并在内存中进行类型转换到目前为止,我已经分析了我的选项并发现有:
RandomAccessFile
- 标准Java中最好的一个,具有正确的搜索和位置方法,字符串读取等,但由于缺少缓冲等操作,有时难以忍受。也没有对流的位级访问权限,也没有不同的字节顺序支持FileInputStream
- 只能读取单个字节,必须手工重建原始数据类型;没有寻求*Reader
相互作用 - 基本上,只能读取字节和字节数组,可以跳过,标记和重置,但如果多次搜索reset(); skip(seekAmount);
我搜索了Google,我搜索过StackOverflow。这个问题 - How to parse/encode binary message formats? - 解决了同样的问题,但是我没有非奇怪的非对齐位要求。
所以,问题是 - 我是否忽略了某些问题,并且有更好的解决方案可以解决所有我提到过的问题?
答案 0 :(得分:6)
ByteBuffer拥有您需要的一切 它也可能是纯Java中最快的选择(不包括JNI,sun.misc.Unsafe等)。
get
,getShort
,getInt
等,以读取所有基本类型和字节数组; order
在BIG_ENDIAN和LITTLE_ENDIAN之间切换; position
寻求; CharsetEncoder
,CharsetDecoder
可以直接在ByteBuffer中编码/解码字符串; FileChannel.map
创建映射到文件的ByteBuffer; 答案 1 :(得分:0)
我讨厌建议这个解决方案,但鉴于您似乎对如何在C中执行此操作有一些了解,您可以在C中构建一个适当函数的库,然后用JNI包装它并在您的应用程序中使用它
也许这只是极少数情况下“适合原生”的情况适合您的用例?