我正在尝试用Java实现特定资源归档文件格式的处理器。格式有一个Header
,由三个char
描述,一个虚拟字节和一个表示文件数的字节组成。
然后每个文件都有一个由虚拟字节组成的条目,一个描述文件名的十二 - char
字符串,一个虚拟字节和一个以三字节数组声明的偏移量。
阅读这种结构的适当课程是什么?我尝试了RandomAccessFile
但它不允许读取数据数组,例如我只能通过调用char
三次来阅读三个readChar()
,等等。
当然我可以扩展RandomAccessFile
来做我想要的但是必须有一个合适的开箱即用的类来做这种处理不是吗?
这是我在C#中的标题读者:
protected override void ReadHeader()
{
Header = new string(this.BinaryReader.ReadChars(3));
byte dummy = this.BinaryReader.ReadByte();
NFiles = this.BinaryReader.ReadByte();
}
答案 0 :(得分:0)
我会选择MappedByteBuffer
。这将允许您任意搜索,但也将有效和透明地处理太大而无法轻松放入RAM的大文件。
在我看来,这是从文件中读取结构化二进制数据的最佳方式。
然后,您可以在此基础上构建自己的数据结构,以处理特定的文件格式。
答案 1 :(得分:0)
我认为你的C#代码很幸运,因为它依赖于在其他地方设置的字符编码,如果它不匹配文件中每个字符的字节数,你的代码可能会有失败。
在Java中最安全的方法是严格读取字节并自行转换为字符。如果你需要寻求能力,那么确实RandomAccessFile
将是你最简单的解决方案,但应该指出InputStream
允许跳过,所以如果你不需要实际的随机访问,只需跳过一些文件,你当然可以使用它。
在任何一种情况下,您都应该根据文件规范从文件中读取字节,然后根据已知编码将它们转换为字符。您永远不应该信任Java程序未编写的文件以包含byte
以外的任何Java数据类型,即使它是由Java编写的,它也可能在写入时转换为原始字节。 / p>
所以你的代码应该是:
String header = "";
int nFiles = 0;
RandomAccessFile raFile = new RandomAccessFile( "filename", "r" );
byte[] buffer = new byte[3];
int numRead = raFile.read( buffer );
header = new String( buffer, StandardCharsets.US_ASCII.name() );
int numSkipped = raFile.skipBytes(1);
nFiles = raFile.read(); // The byte is read as an integer between 0 and 255
完整性检查(检查实际读取的3个字节,跳过1个字节,nFiles
不是-1),为简洁起见,已跳过异常处理。
如果您使用InputStream
,它或多或少相同。