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