【问题标题】:Parsing byte array containg fields of unknown length解析包含未知长度字段的字节数组
【发布时间】:2011-02-24 15:13:34
【问题描述】:

我正在用 Java 解析具有以下规范的字节数组:

Trace data format:
    - 4 bytes containing the Id.
    - 4 bytes containing the address.
    - N bytes containing the first name, where 0 < N < 32
    - N bytes containing the last name, where 0 < N < 32
    - 4 bytes containing the Minimum
    - 4 bytes containing the Maximum 
    - 4 bytes containing the Resource Default Level

今天我没有看到任何解决方案来解析这个数组以获得 7 个具有正确类型的变量。你确认还是我错过了Java中允许在字节数组中找到字符串“限制”的东西(我看不出最小值如何与其关联的ASCII字符区分开来)。

关于两个字符串之间的特殊字符是否有任何“约定”?

【问题讨论】:

  • 读完全名怎么知道?
  • 它们可以是空终止的字符串吗?
  • 您能为您的问题提供一个更好的标题吗?当前的一个可以应用于大多数关于 SO 的问题。
  • 请将标题更改为“Parsing string or array in java”或类似内容。
  • Null 终止的字符串是以 '\0' 字符结尾的字符串。它们是 C/C++ 系统中常见的标准字符串格式。

标签: java string parsing


【解决方案1】:

嗯,你知道名字从第 9 字节开始,而姓氏在字节(长度为 13)结束。不确定的是如何找到名字的结束位置和姓氏的开始位置。我看到了一些可能的解决方案:

  • 如果格式是由 C 程序员定义的,则两个名称字段很可能以空字节终止,因为这是 C 对字符串的约定。
  • 如果是Java程序员定义的,可能是writeUTF()写的,也就是说字节数的规定很可能是错误的。但是,这至少指定了编码,否则这是一个悬而未决的问题。
  • 如果由 COBOL 程序员定义,则这两个字段可以是固定长度并用零或空格填充,格式规范列出有效负载长度而不是字段长度。
  • 如果它是由一个非常不称职的程序员定义的(不管是什么语言),它包含两个名称,没有分隔符或计数,所以不可能将它们真正分开(如果你没有信息,就没有“魔法”在 Java 或其他地方可以凭空变出它的函数)。我想您可能希望姓氏始终以大写字母开头,并且没有人使用双重名称或全部大写。

【讨论】:

    【解决方案2】:

    关于两个字符串之间的特殊字符是否有任何“约定”?

    c-strings 通常是空终止的 \0

    如果没有这样的字符我会说不可能解析结构。

    【讨论】:

      【解决方案3】:

      假设名字和姓氏都以 null 结尾,你会这样做:

      int firstNameLength = 0;
      while(firstNameLength<32) {
          if(theArray[firstNameLength]=='0') break;
          firstNameLength++;
      }
      int lastNameLength = 0;
      while(lastNameLength<32) {
          if(theArray[8+firstNameLength+1+lastNameLength]=='0') break;
          i++;
      }
      String firstName = new String(theArray).substring(8,8+firstNameLength);
      String lastName = new String(theArray).substring(8+firstNameLength+1,8+firstNameLength+1+lastNameLength);
      

      【讨论】:

        【解决方案4】:

        如果你想读取 N 个 ASCII 字节并将它们转换为字符串。

        public static String readString(DataInputStream dis, int num) throws IOException {
            byte[] bytes = new byte[num];
            dis.readFully(bytes);
            return new String(bytes, 0);
        }
        

        对于其余的值,您可以使用

        dis.readInt();
        

        如果您询问是否有任何方法可以知道字符串的长度,我认为您无法从提供的信息中确定这一点。字符串可能以“0”字节终止或长度为第一个字节。也许如果您查看文件中的字节,您会看到格式是什么。

        od -xc my-format.bin
        

        【讨论】:

        • 他需要做更多的调查才能解决这个问题。他在原始问题中没有足够的信息。
        【解决方案5】:

        只是为迈克尔的回答添加另一种可能性。

        假设N对于两个字段是相同的,并且由于使用了相同的字母,我猜想是这种情况,字段位置是这样的:

        int len = array.length;
        int varLen = len - 5*4;
        int fieldPos[] = new int[7];
        fieldPos[0] = 0;
        fieldPos[1] = 4;
        fieldPos[2] = 8;
        fieldPos[3] = 8 + varLen;
        fieldPos[4] = 8 + 2*varLen;
        fieldPos[5] = 8 + 2*varLen + 4;
        fieldPos[6] = 8 + 2*varLen + 8;
        

        【讨论】:

          猜你喜欢
          • 2010-10-14
          • 2016-09-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-28
          • 2019-08-13
          相关资源
          最近更新 更多