【问题标题】:JAVA JDBC Driver PostgreSQL: Parse numbers encoded as BYTEA objectJAVA JDBC Driver PostgreSQL:解析编码为 BYTEA 对象的数字
【发布时间】:2017-10-28 20:40:30
【问题描述】:

我有关系,每条记录都有 BYTEA 列 (UTF-8) 按以下顺序编码 3 个数字:

字节 0-1:数字 1

字节 2-3:数字 2

字节 4-6:数字 3

如何将二进制数据解析为可读数字?

目前我有这个,不知道如何继续:

Class.forName(dbDriver);
Connection connection = DriverManager.getConnection(dbUrl, dbUser, dbPass);
Statement st = connection.createStatement();
String query = "SELECT ...";
ResultSet rs = st.executeQuery(query);
while (rs.next()) {
    byte[] data = rs.getBytes(1);
    //TODO Parse
}

谢谢,

【问题讨论】:

  • 您似乎使用了两次字节 4。我认为这是一个错字,数字 3 来自字节 5-6,而不是 4-6,即 2 个字节长,与数字 1 和 2 相同。
  • @Andreas 嗨,我的错。我编辑了。前2个是2个字节,第三个是3个字节,可以是负数。
  • 如果只有第三个数字可以是负数,那么你确实需要更好地定义数字格式。例如。数字是以二进制存储的吗?如果是,签名号码是否存储在two's complement 中?还是符号本身存储为一个字节?如果不是二进制,数字是否存储为文本?或BCD(打包或解包)?还是别的什么?
  • @Andreas 不幸的是,我在规范中没有所有这些信息。这里有一个常见的做法吗?
  • 不带3字节数字,不,没有通用的做法。我建议您获取一些 byte[7] 值的示例,然后查看字节。如果示例还显示了它们代表的 3 个数字,则会有所帮助。

标签: java postgresql jdbc blob bytea


【解决方案1】:

这取决于数字的存储方式。
它们是二进制的吗?
他们是signed吗?
他们是大还是小endian

假设前两个是,您可以使用位操作,例如

// Little-endian
short num1 = (short) ((data[0] & 0xFF) | (data[1] & 0xFF) << 8);

// Big-endian
short num1 = (short) ((data[0] & 0xFF) << 8 | (data[1] & 0xFF));

但使用ByteBuffer 可能更容易:

ByteBuffer buf = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
short num1 = buf.getShort();
short num2 = buf.getShort();
short num3 = buf.getShort();

ByteBuffer 默认为BIG_ENDIAN

【讨论】:

  • 使用 ByteBuffer,我指定前 2 个数字由 2 个字节组成,第三个由 3 个字节组成?另外,数字可能是负数,这有关系吗?
  • ByteBuffer 没有获取 3 个字节作为数字的方法。它可以做 1 (get())、2 (getShort())、4 (getInt()) 或 8 (getLong()),都解码为带符号的二进制补码 ("signed" 表示值可以是负数)。如果您需要一个 3 字节的数字,请使用位操作,但我怀疑您这样做(请参阅 my comment)。
【解决方案2】:

你可以试试这个吗:

对于字符串:

    String tatto = "my tatto"; //for example
    byte[] array = tatto.getBytes(); // Or any bytes
    String s = new String(array);
    System.out.println(s);

对于字节[]:

    byte[] data = new byte[]{ 1, 16, 84, 2, 101, 110, 83, 111};
    long val = 0;
    for (int i = 0; i < data.length; i++)
    {
       val = (val << 8) + (data[i] & 0xff);
    }
    System.out.println(val);

【讨论】:

  • 嗨,我得到 java.lang.NumberFormatException.forInputString
  • byte[] 上调用toString() 会产生类似[B@15db9742 的结果。
  • 没错,你会从 db 中获取 byte[],但我们不知道存储之前的数据类型。
  • 更新的答案与从 byte[6] 数组中获取 3 个数字(每个数字存储为 2 个字节)有什么关系?
  • "For byte[] :" 部分从byte[8] 数组中获取 一个 数字与获取 三个 有什么关系byte[6] 数组中的数字?
猜你喜欢
  • 1970-01-01
  • 2019-05-08
  • 2012-05-17
  • 1970-01-01
  • 2019-10-02
  • 1970-01-01
  • 2014-09-13
  • 2012-10-28
  • 1970-01-01
相关资源
最近更新 更多