如何在java中将二进制文件转换为对象

时间:2014-06-04 10:59:25

标签: java object binaryfiles

我有一个二进制格式文件,我希望将其转换为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,即使我猜的功能名称使它显而易见它正在做什么。

谷歌搜索到目前为止没有帮助,但可能是我不知道要搜索的正确词语:)

非常感谢任何帮助,

干杯

艾伦

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[]
  • 使用NIO 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();
  }

因此,无论何时你必须阅读简短的内容,你都可以使用这个函数而只需要抛出索引。