2013-02-28 5 views
0

Вот что я пытаюсь сделать. У меня есть байт [], который мне нужно сохранить в Redis с ключом (скажем key1). Redis сохранит его как String. Мне нужно восстановить байт [] при получении значения через key1byte [] to String to 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] < <

Что я делаю неправильно? Есть ли лучшее решение для этого?

ответ

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

+0

Найден правильный метод: String storeStr = Base64.encodeBase64String (bArr); – scs075

+0

Зачем останавливаться на B64? Redis является двоичным, поэтому он может обрабатывать любые непечатаемые символы ASCII. Итак, зачем использовать 64 возможных состояния на символ, если вы можете использовать 256? Используйте 1/4 пространства. –

1

Я не знаю, что base64 кодера вы используете, но результат использования base64 кодирования массива байт должен уже быть String ... и также, когда вы расшифровать, он должен преобразовать String в a byte[]. К сожалению, некоторые base64 API, которые не очень хорошо разработаны на этом фронте -

Я предлагаю вам взглянуть на эту public domain library, который имеет более разумный API:

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

// Send encoded to Redis... 

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

Вы можете создать строку из байт [] с помощью конструктора:

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

Затем запишите его с помощью:

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

Помните, что база 64 называется так потому, что она имеет радиус 64 (64 возможных значения). Это означает, что каждый символ равен 2^6 или 6 бит. Redis поддерживает двоичные безопасные строки, поэтому он может принимать даже непечатаемые символы. Нет никаких оснований ограничивать себя 64 довольно печатными, символами websafe (почему люди используют B64).

Другой проблемой является ASCII 0-127, но байт -128 to 127, поэтому мы не можем отображать напрямую, мы теряем половину диапазона (2^8 против 2^7).Если мы используем UTF-8, мы получаем все эти биты, так что 2^8 или radix 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'. –

0

Используйте эти 2 функций для преобразования и обратного преобразования

Convert.ToBase64String(en) 

Convert.FromBase64String(input) 

Это мост связи между байтом и строкой. и убедитесь, что никакие данные не добавляются или не теряются. Это специальная строка.

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