2013-06-27 71 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