我有一个二进制格式文件,我希望将其转换为Java对象,然后最终将其输出为CSV格式。
我开始沿着一条路走下去,虽然我知道会工作,但似乎不正确。
有人可以告诉我这是 这样做的方式,或建议替代方案。
以下示例代码:
public class Baf5014Converter
{
//private recordSize
public Baf5014 convertBytesToObject(byte[] bafRecordInBytes) {
Baf5014 record = new Baf5014();
record.setSize(getRecordSize(bafRecordInBytes));
return record;
}
private int getRecordSize(byte[] bafRecordInBytes)
{
byte[] recordSizeInBytes = Arrays.copyOfRange(bafRecordInBytes,0,2);
return ByteBuffer.wrap(recordSizeInBytes).getShort();
}
}
我的想法是在浏览文件时创建许多不同的getFoo函数。 我不太喜欢的是上面的魔术数字0,2,即使我猜的功能名称使它显而易见它正在做什么。
谷歌搜索到目前为止没有帮助,但可能是我不知道要搜索的正确词语:)
非常感谢任何帮助,
干杯
艾伦
答案 0 :(得分:2)
对此没有“一个真正的”方法,你的就可以了。 “魔术数字”没有任何问题 - 它们只对应于您正在阅读的文件格式中的魔术数字。为了便于阅读,制作幻数常量可能是一个好主意。
您可能采用的一种方法是将一个带有InputStream的类作为构造函数parm。
public MyObj(InputStream binaryStream) {
Scanner scanner = new Scanner(binaryStream);
this.recordSize = scanner.nextShort();
...
}
然后创建对象:
FileInputStream fis = new FileInputStream(file);
MyObj obj = new MyObj(fis);
为什么不将File作为构造函数arg?好吧,因为编写提供ByteArrayInputStream的单元测试要比在单元测试中创建文件要容易得多。
Scanner
是一个可以帮助您将字节流转换为更高级别类型的类。 DataInputStream
是另一个 - 看哪一个适合您的需求。
您采取的方法将以数据格式为指导。最简单的格式可以通过流式传输读取 - 只需通过流处理每个部分来处理它。有些格式很尴尬,因为在启动之前需要的一些关键属性存储在文件的末尾。在这种情况下,您必须:
byte[]
FileChannel.map()
打开一个映射文件,以便随意读取任意位置的字节。另一种方法是使用Java的Serializable接口,并定义自己的writeObject和readObject方法以使用您喜欢的二进制格式。
答案 1 :(得分:1)
你的方法对我来说似乎没问题。您必须遵守文件的数据结构,因此不可避免地会出现幻数。
您可以通过向上移动一级来避免在辅助函数中使用这些数字。
我的意思是实现基元的get方法,例如而不是getRecordSize
你可以使用:
private int getShort(byte[] input, int index)
{
byte[] shortBytes= Arrays.copyOfRange(input,index,2);
return ByteBuffer.wrap(shortBytes).getShort();
}
因此,无论何时你必须阅读简短的内容,你都可以使用这个函数而只需要抛出索引。