Java - 读取结构化二进制文件

时间:2014-11-20 13:46:27

标签: java

我是Java新手,我需要读取二进制文件并显示其内容转换为整数。该文件具有以下结构:

{client#, position 1, size 32 | 
category, position 33, size 10 | 
type, position 43, size 10 | 
creditlimit, position 53, size 20}

我只需要一个关于使用什么类和转换示例的指南,我们将非常感谢。

3 个答案:

答案 0 :(得分:1)

如果我理解你的问题是正确的,你应该使用NIO Package 使用byteBuffer类中的asIntBuffer(),您可以获得IntBuffer的{​​{1}}视图。通过调用ByteBuffer,您可以将其转换为整数。

使用get(int[] dst)可以获得初始ByteBuffer

答案 1 :(得分:1)

我假设位置1实际上是0;第一个字节。 此外,文件格式似乎是固定大小记录,可能是字节中的ASCII。 为了检查数据,我首先从字符串中取字段。将它们转换为long / int可能会丢失有关实际内容的信息。

以下使用顺序二进制文件。更快的是内存映射文件,但这是可以接受的并且很短。

保留客户数据:

class Client {
    String clientno;
    String category; 
    String type;
    String position;
    String creditlimit;

    @Override
    public String toString() {
        return String.format("Client# %s, categ %s, type %s, pos %s, creditlimit %s%n",
            clientno, category, type, position, creditlimit);
    }
}

阅读文件:

// Field sizes:
final int CLIENT_NO = 32;
final int CATEGORY = 10;
final int TYPE = 10;
final int CREDIT_LIMIT = 20;
final int RECORD_SIZE = CLIENT_NO + CATEGORY + TYPE + CREDIT_LIMIT;

byte[] record = new byte[RECORD_SIZE];
try (BufferedInputStream in = new BufferedInputStream(
    new FileInputStream(file))) {

    for (;;) {
         int nread = in.read(record);
         if (nread < RECORD_SIZE) {
             break;
         }
         Client client = new Client();
         int offset = 0;
         int offset2 = offset + CLIENT_NO;
         client.clientno = recordField(record, offset, offset2 - offset);
         offset = offset2;
         int offset2 = offset + CATEGORY;
         client.category = recordField(record, offset, offset2 - offset);
         offset = offset2;
         int offset2 = offset + TYPE;
         client.type = recordField(record, offset, offset2 - offset);
         offset = offset2;
         int offset2 = offset + CREDITLIMIT;
         client.creditlimit = recordField(record, offset, offset2 - offset);

         System.out.println(client);
    }

} // Closes in.

使用字段提取:

private static String recordField(byte[] record, int offset, int length) {
    String field = new String(record, offset, length, StandardCharsets.ISO_8859_1);

    // Use ASCII NUL as string terminator:
    int pos = field.indexOf('\u0000');
    if (pos != -1) {
        field = field.substring(0, pos);
    }

    return field.trim(); // Trim also spaces for fixed fields.
}

答案 2 :(得分:0)

如果您使用二进制数据,可能JBBP将是您的舒适方式,使用框架解析和打印数据结构非常容易(如果我正确理解任务并使用字节字段),该示例解析整个输入流,然后将解析后的数据打印到控制台

@Bin class Record {byte [] client; byte [] category;  byte [] type; byte [] creditlimit;};
@Bin class Records {Record [] records;};
Records parsed = JBBPParser.prepare("records [_] {byte [32] client; byte [10] category; byte [10] type; byte [20] creditlimit;}").parse(THE_INPUT_STREAM).mapTo(Records.class);
System.out.println(new JBBPTextWriter().Bin(parsed).toString());