【问题标题】:Eliminate default zeros while creating string from byte array从字节数组创建字符串时消除默认零
【发布时间】:2014-06-27 11:15:08
【问题描述】:

我从 IOStream 获取字节并将其转换为字符串。从该字符串中,我使用子字符串 api 提取序列。

ByteArray 的大小为 128 字节。如果流只包含 10 个字节并且剩余的用零填充[初始填充]。我通过传递给字符串构造函数 new String(byte[]) 并检查长度将字节数组转换为字符串。长度是128。为什么显示128?实际上它应该显示 10 字节的字符长度。 如何在转换为字符串时消除零。是否有任何 api 可以消除字节数组中的默认零。从构造的字符串创建子字符串时会产生问题。

    byte[] b = { 99, 116, 101, 100, 46, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0}
 System.out.println("byte length = " + b.length);
            String str;
            try {
                str = new String(b, "UTF-8");
                System.out.println("String length = " + str.length());
                System.out.println(str);
                System.out.println("  ## substring  =  " + str.substring(0));
                System.out.println(" substring length = "
                        + str.substring(0).length());
                System.out.println("Done......");
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }0, 0, 0 };

【问题讨论】:

  • 从数组后面循环,直到找到 first 非零 Byte。在other String ctor 中使用该索引。
  • @Boris 我无法预测它是哪个零。默认大小为零还是输入流中的零?
  • 如果您说要将其分块为128 字节段,那么对于每个段,您都知道填充从末尾开始。如果您向后工作,则填充在读取第一个非零 byte 时结束。
  • 这似乎是一个 XY 问题。您想从 InputStream 中读取数据作为文本。但是您发布的问题是关于您在尝试的解决方案中遇到的问题。 meta.stackexchange.com/a/66378

标签: java string


【解决方案1】:

要从字节数组的一部分创建字符串,请使用构造函数String(byte[] bytes, int offset, int length, String charsetName)。示例:

// uses the first 10 bytes of b
str = new String(b, 0, 10, "UTF-8");

另外,如果您正在为 Java 7 进行编译,您不妨使用StandardCharsets(来自java.nio.charset 包),并避免处理UnsupportedEncodingException。示例:

str = new String(b, 0, 10, StandardCharsets.UTF_8);

【讨论】:

  • +1 如果你只想转换 10 个字节,告诉它转换 10 个字节,你不需要将你没有读取的字节归零。
【解决方案2】:

当您从InputStream 发送read 时,它会告诉您读取了多少字节。 byte[] 本身的长度几乎无关紧要(除了定义可以在单个调用中读取的最大字节数之外)。以后不需要再去检查byte[] 来尝试确定有多少数据是相关的。注意read 的返回值,并在创建String 时使用它。

此外,如果您的所有数据都是文本,请考虑使用InputStreamReader,也许与BufferedReader 结合使用。

【讨论】:

    【解决方案3】:

    先解释一下。

    并非每个字节序列都是有效的 UTF-8。二进制字节 0 (0x00) 是有效的,并且不会像 C 中那样终止字符串。

    事实上,终止 \0 后来被 C 的 Kernighan 或 Ritchie 谴责为次优。

    为了防止出现问题,不仅 U+007F (0x7f) 以上的 Unicode 代码点是多字节编码的(设置了高位字节),Java's UTF-8, DataOutputSream 中的 U+0000 也是多字节编码的。

    byte[] bytes = get UTF-8 bytes from string
    

    现在字节对于代码点 0 可以有一个多字节序列。

    所以你要么清理字节,小循环,要么清理字符串:

    str = str.replace("\u0000", ""); // All bytes 0
    str = str.replaceFirst("\u0000+$", ""); // Only trailing bytes 0, regex
    

    【讨论】:

      【解决方案4】:

      你的代码应该是这样的

        byte[] b = { 99, 116, 101, 100, 46, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0};
      
              int nonZeroPos=0;
              for (int i = b.length-1; i >0; i--) {
                  if(b[i]!=0){
                      nonZeroPos=i;
                       break;
                  }
              }
      
      
              System.out.println("byte length = " + b.length);
              String str;
              try {
                   str = new String(b, 0, nonZeroPos, "UTF-8");
                  System.out.println("String length = " + str.length());
                  System.out.println(str);
                  System.out.println("  ## substring  =  " + str.substring(0));
                  System.out.println(" substring length = "
                          + str.substring(0).length());
                  System.out.println("Done......");
              } catch (UnsupportedEncodingException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              } 
      

      你也可以这样做 -

       String zerostring = new String(new byte[]{0});
       str=new String(b).replace(zerostring , "");
       System.out.println(str);
      

      但这样做的缺点是它会替换单词中的 0。

      【讨论】:

        猜你喜欢
        • 2014-01-04
        • 2020-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-31
        • 2016-03-10
        • 1970-01-01
        相关资源
        最近更新 更多