2013-06-27 68 views
78

这是一个正确的做法,以字节缓冲区转换为字符串以这种方式,的Java字节缓冲区为String

String k = "abcd"; 
ByteBuffer b = ByteBuffer.wrap(k.getBytes()); 
String v = new String(b.array()); 

if(k.equals(v)) 
    System.out.println("it worked"); 
else 
    System.out.println("did not work"); 

的原因,我问的是,是这看起来太简单了,而其他的方法,如Java: Converting String to and from ByteBuffer and associated problems看起来更加复杂。

+2

那么,你试过吗? – Doorknob

+5

是的,我做了,它的工作。但我看到其他更复杂的实现,如http://stackoverflow.com/questions/1252468/java-converting-string-to-and-from-bytebuffer-and-associated-problems –

+1

@ Doorknob et。人。他缺少编码,他的例子(当语法被纠正时)会起作用,但他的方法仍然不正确。 – Gus

回答

58

你的做法是合理的。在你的例子中,这是真的,因为k.getBytes()返回平台的默认字符集中的字节。

更频繁地,您需要指定编码。但是,有一个比你连接的问题更简单的方法。字符串API提供了以特定编码方式在字符串和byte []数组之间进行转换的方法。当需要对解码[编码]过程进行更多控制时,这些方法建议使用CharsetEncoder/CharsetDecoder “。

import java.nio.charset.Charset; 

为了得到一个字符串的字节在一个特定的编码,您可以用兄弟姐妹的getBytes()方法:

byte[] bytes = k.getBytes(Charset.forName("UTF-8")); 

为了把字节与特定的编码方式转化为字符串,可以使用不同的字符串构造函数:

String v = new String(bytes, Charset.forName("UTF-8")); 

请注意,ByteBuffer.array()是一个可选操作。如果你用数组构造了你的ByteBuffer,你可以直接使用该数组。否则,如果您想安全起见,请使用ByteBuffer.get(byte[] dst, int offset, int length)将缓冲区中的字节转换为字节数组。

编辑

作为一个方面的问题,在示例代码中调用Charset.forName("UTF-8")以上,因为1.4所有Java版本应该工作。

如果您使用的是Java 7或更高版本,则可改为使用java.nio.charset.StandardCharsets.UTF_8(由BenKirby在下面他的注释中提到。)

如果您使用番石榴,您可以改用com.google.common.base.Charsets.UTF_8(注意下面的评论中的spacecamel。)

+0

和'ByteBuffer.get'函数中,输入又是一个字节数组,我怎样才能得到它?再次说出k.getbytes没有任何意义,是吗? –

+0

@WilliamKinaan - 您有输入到ByteBuffer.get(byte [] dst,int offset,int length)的byte []。您可以使用String()构造函数'String(byte [] bytes,int offset,int length,Charset charset)构建一个String。这两个呼叫可以使用相同的偏移和长度值。 –

+0

java.nio.ByteBuffer中没有k.getBytes()方法(可能不在我正在使用的版本中)。所以我用k.array()方法返回byte []。 –

13

试试这个:

new String(bytebuffer.array(), "ASCII"); 

NB。你不能正确地将字节数组转换为字符串而不知道其编码。

我希望这可以帮助,如果你知道的字节是在平台的默认字符集

+9

UTF-8可能比ASCII更好的默认猜测? – Gus

+3

鉴于OP使用k.getBytes(),它使用平台的默认字符集,因此都不应该指定。 –

+5

并非所有的缓冲区都由数组支持,所以'.array()'可能会抛出异常。 –

12

只是想指出,假设ByteBuffer.array()将始终工作并不安全。

byte[] bytes; 
if(buffer.hasArray()) { 
    bytes = buffer.array(); 
} else { 
    bytes = new byte[buffer.remaining()]; 
    buffer.get(bytes); 
} 
String v = new String(bytes, charset); 

通常,根据您的使用情况,buffer.hasArray()将始终为true或false。在实践中,除非您真的希望它在任何情况下都能正常工作,否则优化您不需要的分支是安全的。但其余的答案可能不适用于通过ByteBuffer创建的ByteBuffer。allocateDirect()。

+0

如果缓冲区是通过ByteBuffer创建的。wrap(bytes,offset,size)'factory'.array()'将返回整个'bytes'数组。更好地使用表单xinyong Cheng建议 –

+0

Charset上的.decode()是一个更好的解决方案,同意。我确实认为我的答案的背景是有用的信息,但现在要少得多。 – Fuwjax

0

注意(除了编码问题),一些更复杂的代码链接会遇到问题(例如通过使用位置和限制)获得ByteBuffer的“活动”部分的麻烦,而不是简单的编码整个支持数组中的所有字节(如这些答案中的许多示例所做的那样)。

3

提到简单调用array()的答案并不完全正确:当缓冲区已被部分消耗,或者指的是数组的一部分时(您可以在给定偏移量处获得一个数组,但不一定从头开始) ,我们必须在我们的计算中说明这一点。这是在所有情况下的缓冲区的工作(不包括编码)的通解:

if (myByteBuffer.hasArray()) { 
    return new String(myByteBuffer.array(), 
     myByteBuffer.arrayOffset() + myByteBuffer.position(), 
     myByteBuffer.remaining()); 
} else { 
    final byte[] b = new byte[myByteBuffer.remaining()]; 
    myByteBuffer.duplicate().get(b); 
    return new String(b); 
} 

对于与编码的关注,看到安迪·托马斯的回答。

1

使用将字符串转换为字节缓冲区,然后从字节缓冲区返回字符串的Java:

import java.nio.charset.Charset; 
import java.nio.*; 

String babel = "obufscate thdé alphebat and yolo!!"; 
System.out.println(babel); 
//Convert string to ByteBuffer: 
ByteBuffer babb = Charset.forName("UTF-8").encode(babel); 
try{ 
    //Convert ByteBuffer to String 
    System.out.println(new String(babb.array(), "UTF-8")); 
} 
catch(Exception e){ 
    e.printStackTrace(); 
} 

哪个首先打印印刷裸串,然后将字节缓冲区浇铸阵列():

obufscate thdé alphebat and yolo!! 
obufscate thdé alphebat and yolo!! 

另外这对我很有帮助,将字符串还原为原始字节可以帮助检查发生了什么事情:

String text = "こんにちは"; 
//convert utf8 text to a byte array 
byte[] array = text.getBytes("UTF-8"); 
//convert the byte array back to a string as UTF-8 
String s = new String(array, Charset.forName("UTF-8")); 
System.out.println(s); 
//forcing strings encoded as UTF-8 as an incorrect encoding like 
//say ISO-8859-1 causes strange and undefined behavior 
String sISO = new String(array, Charset.forName("ISO-8859-1")); 
System.out.println(sISO); 

打印你的字符串解释为UTF-8,然后再为ISO-8859-1:

こんにちは 
ããã«ã¡ã¯ 
31

有没有更简单的安迪·托马斯提到的任何问题,到ByteBufferString解码方法。

String s = StandardCharsets.UTF_8.decode(byteBuffer).toString(); 
+1

请注意,UTF-8可能不是用于将字节转换为字符串的最佳charset,反之亦然。对于字节到字符的1对1映射更好地使用ISO-8859-1,请参阅https://stackoverflow.com/questions/9098022/problems-converting-byte-array-to-string-and-back-to字节阵列。 – asmaier