Java 从字节数组创建字符串时消除默认零

Java 从字节数组创建字符串时消除默认零,java,string,Java,String,我正在从IOStream获取字节并将其转换为字符串。从该字符串中,我使用子字符串api提取一个序列 字节数组的大小为128字节。如果流仅包含10个字节,剩余的字节将填充为零[初始填充]。我通过向字符串构造函数传递新字符串(byte[])并检查长度,将字节数组转换为字符串。长度是128。为什么显示128?实际上,它应该显示10字节字符长度。 如何在转换为字符串时消除零。是否有任何api消除字节数组中的默认零。从构造的字符串创建子字符串时出现问题 byte[] b = { 99, 116,

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

字节数组的大小为128字节。如果流仅包含10个字节,剩余的字节将填充为零[初始填充]。我通过向字符串构造函数传递新字符串(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 };

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

// uses the first 10 bytes of b
str = new String(b, 0, 10, "UTF-8");
str = new String(b, 0, 10, StandardCharsets.UTF_8);
另外,如果您是为Java 7编译的,您还可以使用
StandardCharset
(来自
Java.nio.charset
包),并避免必须处理
不受支持的CodingException
。例如:

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

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

// uses the first 10 bytes of b
str = new String(b, 0, 10, "UTF-8");
str = new String(b, 0, 10, StandardCharsets.UTF_8);
另外,如果您是为Java 7编译的,您还可以使用
StandardCharset
(来自
Java.nio.charset
包),并避免必须处理
不受支持的CodingException
。例如:

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

你的代码应该是这样的

  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。

您的代码如下所示

  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。

首先解释一下

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

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

为了防止出现问题,不仅U+007F(0x7f)以上的Unicode代码点是多字节编码的(设置了字节的高位),而且U+0000也是多字节编码的

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

因此,您可以清理字节、小循环或清理字符串:

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

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

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

为了防止出现问题,不仅U+007F(0x7f)以上的Unicode代码点是多字节编码的(设置了字节的高位),而且U+0000也是多字节编码的

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

因此,您可以清理字节、小循环或清理字符串:

str = str.replace("\u0000", ""); // All bytes 0
str = str.replaceFirst("\u0000+$", ""); // Only trailing bytes 0, regex
当您从
输入流
读取数据时,它会告诉您读取了多少字节。
byte[]
本身的长度基本上是无关的(除了定义一次调用可以读取的最大字节数)。以后无需检查
字节[]
来确定有多少数据是相关的。注意返回值,并在创建
字符串时使用该值

另外,如果所有的数据都是文本,考虑使用AN,也许结合A.

当你从<代码>输入流< /代码>时,它会告诉你读了多少字节。

byte[]
本身的长度基本上是无关的(除了定义一次调用可以读取的最大字节数)。以后无需检查
字节[]
来确定有多少数据是相关的。注意返回值,并在创建
字符串时使用该值


另外,如果所有的数据都是文本,请考虑使用一个AN,或者结合数组后面的.< /p>循环,直到找到第一个非零<代码>字节< /> >。在中使用该索引。如果我使用子字符串(0,bytesRead),则可能会出现stringindexoutofboundsexception,因为在utf-8中,某些特殊字符的字符长度为两个字节。@Boris我无法预测它是哪个零。默认大小为零还是inputstream中的零?如果您说要将其分块为

128
字节段,然后,对于每个段,您知道填充从末尾开始。如果向后工作,则当读取第一个非零的
字节时,填充结束。这似乎有点XY问题。您希望以文本形式从InputStream读取数据。但是,您发布的问题是关于您在尝试解决方案时遇到的问题。从数组的后面循环,直到找到第一个非零的
字节。在中使用该索引。如果我使用子字符串(0,bytesRead),则可能会出现stringindexoutofboundsexception,因为在utf-8中,某些特殊字符的字符长度为两个字节。@Boris我无法预测它是哪个零。默认大小为零还是inputstream中的零?如果您说要将其分块为
128
字节段,然后,对于每个段,您知道填充从末尾开始。如果向后工作,则当读取第一个非零的
字节时,填充结束。这似乎有点XY问题。您希望以文本形式从InputStream读取数据。但是,您发布的问题是关于您在尝试解决方案时遇到的问题+1如果您只想转换10个字节,请告诉它转换10个字节,您不需要将未读取的字节归零。+1如果您只想转换10个字节,请告诉它转换10个字节,您不需要将未读取的字节归零。