我试图使用Preon来解析二进制文件,它们被构造为一系列可变长度记录。对于每条记录,都有一个指定记录长度的数字(以字节为单位)。解析Preon中的变量记录长度
这里是什么,我试图做一个简化版本:
package test.preon;
import nl.flotsam.preon.annotation.BoundList;
import nl.flotsam.preon.annotation.BoundNumber;
import java.util.List;
public class BinFile {
@BoundNumber(size="16") int numberOfRecords;
@BoundList(type=Record.class, size="numberOfRecords") List<Record> records;
public int getNumberOfRecords() {
return numberOfRecords;
}
public List<Record> getRecords() {
return records;
}
public class Record {
@BoundNumber(size="16") int recordLength;
@BoundList(size="recordLength") byte[] data;
public int getRecordLength() {
return recordLength;
}
public byte[] getData() {
return data;
}
}
}
所以,numberOfRecords指定文件中的记录数和RECORDLENGTH指定每个记录的长度。问题是Preon无法解决Record中的recordLength问题,尽管在BinFile中numberOfRecords可以正常工作。
这里是例外,我得到:
nl.flotsam.limbo.BindingException: Failed to resolve recordLength on class test.preon.BinFile
at nl.flotsam.preon.codec.BindingsContext$BindingsResolver.get(BindingsContext.java:412)
at nl.flotsam.preon.codec.BindingsContext$BindingReference.resolve(BindingsContext.java:247)
at nl.flotsam.preon.codec.BindingsContext$BindingReference.resolve(BindingsContext.java:189)
at nl.flotsam.limbo.ast.ReferenceNode.eval(ReferenceNode.java:57)
at nl.flotsam.limbo.ast.ArithmeticNode$Operator$5.eval(ArithmeticNode.java:109)
at nl.flotsam.limbo.ast.ArithmeticNode.eval(ArithmeticNode.java:250)
at nl.flotsam.limbo.ast.ArithmeticNode.eval(ArithmeticNode.java:33)
at nl.flotsam.limbo.ast.ArithmeticNode$Operator$3.eval(ArithmeticNode.java:83)
at nl.flotsam.limbo.ast.ArithmeticNode.eval(ArithmeticNode.java:250)
at nl.flotsam.limbo.ast.ArithmeticNode.eval(ArithmeticNode.java:33)
at nl.flotsam.limbo.ast.ArithmeticNode$Operator$5.eval(ArithmeticNode.java:109)
at nl.flotsam.limbo.ast.ArithmeticNode.eval(ArithmeticNode.java:250)
at nl.flotsam.limbo.ast.ArithmeticNode.eval(ArithmeticNode.java:33)
at nl.flotsam.preon.codec.ListCodecFactory$SwitchingListCodec.decode(ListCodecFactory.java:458)
at nl.flotsam.preon.codec.ListCodecFactory$SwitchingListCodec.decode(ListCodecFactory.java:443)
at nl.flotsam.preon.binding.StandardBindingFactory$FieldBinding.load(StandardBindingFactory.java:128)
at nl.flotsam.preon.codec.ObjectCodecFactory$ObjectCodec.decode(ObjectCodecFactory.java:251)
at nl.flotsam.preon.DefaultCodecFactory$DefaultCodec.decode(DefaultCodecFactory.java:173)
at nl.flotsam.preon.Codecs.decode(Codecs.java:218)
at nl.flotsam.preon.Codecs.decode(Codecs.java:199)
...
如果我改变大小= “RECORDLENGTH” 为一个常数,例如大小=“42”,我没有得到例外(但当然,那么记录长度总是必须相同)。
有没有其他的方式让我做记录长度变量,或者我应该组织的东西不同?
如果任何人的兴趣,这里的JUnit测试我使用:
package test.preon;
import org.junit.Test;
import static org.junit.Assert.*;
import nl.flotsam.preon.Codecs;
import nl.flotsam.preon.Codec;
import nl.flotsam.preon.DecodingException;
import test.preon.BinFile;
import test.preon.BinFile.Record;
import java.util.List;
public class BinFileTest {
@Test
public void parseBinFile() throws DecodingException {
Codec<BinFile> codec = Codecs.create(BinFile.class);
byte[] buffer = new byte[] {
2, 0,
3, 0,
'a', 'b', 'c',
4, 0,
'1', '2', '3', '4'
};
BinFile b = Codecs.decode(codec, buffer);
assertEquals(b.getNumberOfRecords(), 2);
List<Record> rL = b.getRecords();
assertEquals(rL.size(), 2);
Record r0 = rL.get(0);
assertEquals(r0.getRecordLength(), 3);
assertEquals(new String(r0.getData()), "abc");
Record r1 = rL.get(1);
assertEquals(r1.getRecordLength(), 4);
assertEquals(new String(r1.getData()), "1234");
}
}
创造了在这里的bug报告:附加一个补丁,这个问题http://kenai.com/jira/browse/PREON-9 – 2010-03-04 06:33:20
。 – 2010-03-04 06:41:02
太棒了!谢谢。 – skoob 2010-03-04 07:19:23