2013-02-28 180 views
0

這是我正在嘗試做的。我有一個字節[],我需要在Redis中使用key存儲(比如key1),Redis會將其存儲爲String。我需要在經由KEY1字節[]再次字符串到字節[]

//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] < <

我在做什麼錯?有沒有更好的解決方案?

回答

5

Arrays.toString()並不能把一個字節數組轉換爲一個字符串。它給出了一個字節數組的字符串表示,用於調試目的,正如List<Byte>.toString()所做的那樣。

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

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

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

謝謝,它解決了這個問題。 – scs075 2013-03-01 18:01:43

+0

找到正確的方法:String storeStr = Base64.encodeBase64String(bArr); – scs075 2013-03-14 20:18:54

+0

爲什麼停在B64? Redis是二進制安全的,因此它可以處理任何非打印的ASCII字符。那麼,爲什麼在使用256時爲每個字符使用64個可能的狀態呢?使用1/4的空間。 – 2015-03-25 15:25:33

1

我不知道你使用的是什麼的base64編碼器,但使用Base64編碼的字節數組的結果應該已經String ......同樣地,當你進行解碼,它應該在String轉換爲一個byte[]。不幸的是一些的base64 API是不是非常很好的設計在這一方面 -

我建議你看一下這個public domain library其中有一個更明智的API:

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

// Send encoded to Redis... 

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

您可以從使用構造一個byte []的字符串:

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

然後寫回:

byte[] bytes = string.getBytes(); 
1

請記住,基數64被稱爲是因爲它的基數爲64(64個可能的值)。這意味着每個字符是2^6或6位。 Redis支持二進制安全字符串,所以它甚至可以使用非打印字符。沒有理由將自己侷限於64個漂亮的打印,網頁安全字符(爲什麼人們使用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字符串:字符

UTF8字符串:(!節省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在內存中,並且內存很珍貴,所以您可能需要切換h二進制數據轉換爲UTF-8編碼,一旦你的應用程序開始填滿一些快速節省空間。缺點是它不如B64那樣可讀。

+0

謝謝你介紹'二進制安全字符串',但可能你的'新字符串(字節,「UTF-8」)'不正確。並非所有字節序列都可以正確解析爲UTF-8字節而不會丟失數據。改用'iso-8859-1'。 – 2015-06-19 16:16:51

0

使用這2個功能轉換和轉換回

Convert.ToBase64String(en) 

Convert.FromBase64String(input) 

它填補字節和字符串之間的聯繫。並確保沒有數據添加或丟失。 這是一個特殊的字符串。

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