簡體   English   中英

從byte []到字符串再到byte []

[英]byte[] to String to byte[] again

這是我想要做的。 我有一個字節[],需要用鍵(例如key1)存儲在Redis中。Redis會將其存儲為字符串。 我需要通過key1檢索值時重建byte []

    //here is a byte array
    byte[] bArr = new byte[] {83, 71, 86, 115, 98, 71, 56, 103, 84, 88, 73, 117, 73, 69, 104, 118, 100, 121, 66, 107, 98, 121, 66, 53, 98, 51, 85, 103, 90, 71, 56, 47}; //"Hello World"; 

    // I will have to store this as a byte string into redis
    //Base64 encoding
    bArr = Base64.encodeBase64(bArr);
    String storeStr = Arrays.toString(bArr) ;
    // storeStr is what gets stored in redis
    System.out.println("storeStr>>" + storeStr+ "<<");
    // I will get this string back from redis
    // now trying to reconstruct the byte[]
    byte[] aArr = Base64.decodeBase64(storeStr); 
    System.out.println("readStr>>" + Arrays.toString(aArr)+ "<<");  

但是我得到以下輸出:

storeStr >> [85,48,100,87,99,50,74,72,79,71,100,85,87,69,108,49,83,85,86,111,100,109,82, 53,81,109,116,105,101,85,73,49,89,106,78,86,90,49,112,72,79,67,56,61] << readStr >> [-13 ,-98,60,-41,77,60,-17,-33,121,-45,-66,59,-37,-65,123,-41,93,52,-13,-97, 59,-21,-35、116,-13,-113、124,-33,-50、124,-21、93、117,-41、77、53,-45,-33、54,-25 ,127、53,-41、79、117,-41,-83、116,-25、93、53,-13,-98,-9,-29,-33、61,-41、78,- 69,-13,-50,-67,-45,-113、117,-41、110,-10,-17,-34,-69,-25,-82,-75] <<

我究竟做錯了什么? 有什么更好的解決方案嗎?

Arrays.toString()不會將字節數組轉換為String。 出於調試目的,它提供了字節數組的String表示形式,就像List<Byte>.toString()那樣。

Base64.encode()應該將字節數組轉換為String。 並且Base64.decode()應該將base64字符串轉換為相應的字節數組。 我見過的所有Base64庫都內置了這種方法。 您的也可能有一個。 如果不是,Base64包含ASCII字符,則可以簡單地使用

String storeStr = new String(base64Array, "ASCII");

byte[] bytes = storeStr.getBytes("ASCII");

我不知道您使用的是哪種base64編碼器,但是使用base64編碼字節數組的結果應該已經String ...,同樣,當您解碼時,它應該將String轉換為byte[] 不幸的是,某些base64 API在這方面設計得並不好-

我建議您看一下這個公共域庫 ,它具有更明智的API:

byte[] binary = ...;
String encoded = Base64.encodeBytes(binary);

// Send encoded to Redis...

byte[] decoded = Base64.decode(encoded);

您可以使用構造函數從byte []創建字符串:

//assuming you have a byte[] bytes
String string = new String(bytes);

然后寫回:

byte[] bytes = string.getBytes();

請記住,以64為基數是因為它的基數為64(可能為64)。 這意味着每個字符為2 ^ 6或6位。 Redis支持二進制安全字符串 ,因此它甚至可以接受非打印字符。 沒有理由將自己限制為64個漂亮的可打印Web安全字符(為什么人們使用B64)。

另一個問題是ASCII是0-127 ,但是字節是-128 to 127 ,所以我們不能直接映射,我們損失了一半的范圍(2 ^ 8 vs 2 ^ 7)。 如果我們使用UTF-8,則會得到所有這些位,即2 ^ 8或基數256。結果是我們可以將一個字節填充為1.25個B64字符,或單個UTF-8字符。 因此,UTF-8編碼將使用〜75%的空間作為B64編碼數據。 下面,由於B64使用了所有額外的填充=字符,因此我們得到了更好的結果。

示例,編碼19個字節:

B64字符串: 28個字符

UTF8字符串: 19個字符(節省32%!)

// setup
byte[] bytes = new byte[]{-10, 1, 3, 85, 48, 100, 87, 99, 050, 74, 79, 71, 100, 85, 87, -120, 108, -128, 30};

// full UTF-8 range
String outFullRange = new String(bytes, "UTF-8");
System.out.println(outFullRange); // prints �U0dWc(JOGdUW�l�

// just Base64
String outB64 = Base64.encode(bytes);
System.out.println(outB64);// 9gEDVTBkV2MoSk9HZFVXiGyAHg==

請記住,由於Redis在內存中,並且內存非常寶貴,因此您可能希望在應用開始填充二進制數據后將其轉換為UTF-8編碼,以節省一些空間。 缺點是它不像B64那樣易於人讀。

使用這2個函數進行轉換並轉換回

Convert.ToBase64String(en)

Convert.FromBase64String(input)

它橋接字節和字符串之間的鏈接。 並且確保沒有數據增加或丟失。 這是一個特殊的字符串。

https://zh.wikipedia.org/wiki/Base64

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM