byte数组转为char数组

您所在的位置:网站首页 byte转成char byte数组转为char数组

byte数组转为char数组

#byte数组转为char数组| 来源: 网络整理| 查看: 265

我正在寻找将Java char数组转换为字节数组而不创建中间String的方法,因为char数组包含密码。 我查看了几种方法,但是它们似乎都失败了:

char[] password ="password".toCharArray();

byte[] passwordBytes1 = new byte[password.length*2];

ByteBuffer.wrap(passwordBytes1).asCharBuffer().put(password);

byte[] passwordBytes2 = new byte[password.length*2];

for(int i=0; i

passwordBytes2[2*i] = (byte) ((password[i]&0xFF00)>>8);

passwordBytes2[2*i+1] = (byte) (password[i]&0x00FF);

}

String passwordAsString = new String(password);

String passwordBytes1AsString = new String(passwordBytes1);

String passwordBytes2AsString = new String(passwordBytes2);

System.out.println(passwordAsString);

System.out.println(passwordBytes1AsString);

System.out.println(passwordBytes2AsString);

assertTrue(passwordAsString.equals(passwordBytes1) || passwordAsString.equals(passwordBytes2));

断言总是失败的(并且,至关重要的是,当在生产中使用该代码时,密码被拒绝),但是print语句会打印出三次密码。 为什么passwordBytes1AsString和passwordBytes2AsString与passwordAsString不同,却显得相同? 我是否错过了空终止符之类的东西? 我怎样做才能使转换和未转换工作?

为什么要避免创建中间字符串?

Sun建议将它作为最佳实践:download.oracle.com/javase/1.5.0/docs/guide/security/jce/字符串是不可变的,因此不能像char数组一样清零-相反,您的密码在内存中徘徊, 不确定的时间。

char和byte之间的转换是字符集的编码和解码。我更喜欢在代码中尽可能地使其清晰。这实际上并不意味着额外的代码量:

Charset latin1Charset = Charset.forName("ISO-8859-1");

charBuffer = latin1Charset.decode(ByteBuffer.wrap(byteArray)); // also decode to String

byteBuffer = latin1Charset.encode(charBuffer);                 // also decode from String

在旁边:

java.nio类和java.io Reader / Writer类使用ByteBuffer和CharBuffer(它们使用byte []和char []作为后备数组)。因此,通常最好直接使用这些类。但是,您始终可以执行以下操作:

byteArray = ByteBuffer.array();  byteBuffer = ByteBuffer.wrap(byteArray);

byteBuffer.get(byteArray);       charBuffer.put(charArray);

charArray = CharBuffer.array();  charBuffer = ByteBuffer.wrap(charArray);

charBuffer.get(charArray);       charBuffer.put(charArray);

问题是您使用String(byte[])构造函数,该构造函数使用平台默认编码。这几乎从来都不是您应该做的-如果您通过" UTF-16"作为字符编码正常工作,则测试可能会通过。目前,我怀疑passwordBytes1AsString和passwordBytes2AsString的长度均为16个字符,其他每个字符均为U + 0000。

我只是尝试了(即String passwordBytes1AsString = new String(passwordBytes1,"UTF-16");)而没有任何变化。我还尝试检查字符串的长度-String.length()返回8。它将计算U + 0000个字符吗?

@Scott:尝试打印出字符串的长度以及各个字符(作为int值)。 Thatll向您显示差异之处。

原始版本和转换版本都为112,97,115,115,119,111,114,100。

@斯科特:在那种情况下,断言现在应该过去了...

刚刚注意到我在断言中对equals()使用了错误的参数。 * facepalm *您最初的假设确实是正确的。非常感谢。

原始答案

public byte[] charsToBytes(char[] chars){

Charset charset = Charset.forName("UTF-8");

ByteBuffer byteBuffer = charset.encode(CharBuffer.wrap(chars));

return Arrays.copyOf(byteBuffer.array(), byteBuffer.limit());

}

public char[] bytesToChars(byte[] bytes){

Charset charset = Charset.forName("UTF-8");

CharBuffer charBuffer = charset.decode(ByteBuffer.wrap(bytes));

return Arrays.copyOf(charBuffer.array(), charBuffer.limit());

}

编辑以使用StandardCharsets

public byte[] charsToBytes(char[] chars)

{

final ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(CharBuffer.wrap(chars));

return Arrays.copyOf(byteBuffer.array(), byteBuffer.limit());

}

public char[] bytesToChars(byte[] bytes)

{

final CharBuffer charBuffer = StandardCharsets.UTF_8.decode(ByteBuffer.wrap(bytes));

return Arrays.copyOf(charBuffer.array(), charBuffer.limit());

}

这是StandardCharsets的JavaDoc页面。

在JavaDoc页面上注意这一点:

These charsets are guaranteed to be available on every implementation of the Java platform.

很好地使用ByteBuffer。但是,如果没有另外说明,密码是Unicode,因此StandardCharset.UTF_8优于通过将数据简化为ASCII来破坏数据。

您可以使用所需的任何字符集

我的观点是,ASCII通常是错误的。

我编辑了从US-ASCII更改为UTF-8的帖子。你是对的。想法是保持相同的编码。例如,US-ASCII的字符数不及UTF-8的字符数-没有带重音符号的字母,如果使用的是第一个UTF-8,然后使用US-ASCII,则会丢失一些信息。

将敏感数据存储在char []或byte []中后,您需要清除敏感数据,如Andrii在此处说明的用法一样stackoverflow.com/a/9670279/1582089

很好的例子。但就我而言,它可以与Charset charset = Charset.forName(" ISO-8859-1");一起使用。

我要做的是使用一个循环将其转换为字节,然后将另一个转换为char。

char[] chars ="password".toCharArray();

byte[] bytes = new byte[chars.length*2];

for(int i=0;i

bytes[i*2] = (byte) (chars[i] >> 8);

bytes[i*2+1] = (byte) chars[i];

}

char[] chars2 = new char[bytes.length/2];

for(int i=0;i

chars2[i] = (char) ((bytes[i*2]

int length = chars.length;

byte[] result = new byte[length*2+2];

int i = 0;

for(int j = 0 ;j

result[i++] = (byte)( (chars[j] & 0xFF00) >> 8 );

result[i++] = (byte)((chars[j] & 0x00FF)) ;

}

return result;

}

用途:

String sample ="abc";

//First get the chars of the String,each char has two bytes(Java).

Char[] sample_chars = sample.toCharArray();

//Get the bytes

byte[] result = charArray2ByteArray(sample_chars).

//Back to String.

//Make sure we use UTF_16BE. Because we read the memory of Unicode of

//the String from Left to right. That's the same reading

//sequece of  UTF-16BE.

String sample_back= new String(result , StandardCharsets.UTF_16BE);

这个问题没有提到getBytes,所以这并没有真正的意义。您是否要评论其他答案之一?

只想声明String的getBytes函数的用法。并且在使用new String(Byte [])时应该注意什么。希望能帮助到你。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3