2015-12-22 2 views
0

У меня есть довольно интересная тема - по крайней мере, для меня. Учитывая ByteArrayOutputStream с байтами, например, в UTF-8, мне нужна функция, которая может «переводить» эти байты в другой - новый - ByteArrayOutputStream, например, в UTF-16 или ASCII, или вы называете это. Моим наивным подходом было бы использовать InputStreamReader и указать желаемую кодировку, но это не сработало, потому что это будет читать в char [], и я могу писать только байт [] в новый BAOS.Преобразование массива байтов из кодирования A в кодирование B

public byte[] convertStream(Charset encoding) { 
    ByteArrayInputStream original = new ByteArrayInputStream(raw.toByteArray()); 
    InputStreamReader contentReader = new InputStreamReader(original, encoding); 
    ByteArrayOutputStream converted = new ByteArrayOutputStream(); 

    int readCount; 
    char[] buffer = new char[4096]; 
    while ((readCount = contentReader.read(buffer, 0, buffer.length)) != -1) 
     converted.write(buffer, 0, readCount); 

    return converted.toByteArray(); 
} 

Теперь это, очевидно, не работает, и я ищу способ сделать этот сценарий возможным, без создания строки из байта [].

@Edit: Поскольку кажется очевидным, что трудно читать очевидные вещи. 1) raw: ByteArrayOutputStream, содержащий байты объекта BINARY, отправленные нам от клиентов. Байты обычно входят в UTF-8 как часть HTTP-сообщения. 2) Цель состоит в том, чтобы отправить данные BINARY вперед во внутреннюю Систему, которая не является гибкой - хорошо это внутренняя Система - и она принимает такие вложения в UTF-16. Я не знаю, почему даже не спрашиваю, так оно и есть.

Итак, чтобы обосновать мой вопрос: есть ли способ преобразования массива байтов из Charset A в Charset B или кодирования вашего выбора. Снова Строка Строка НЕ ​​является тем, что мне нужно.

Благодарим вас и надеемся, что прояснит сомнительные детали :).

+0

Что такое «сырой»? Вы только предоставили нам часть информации. Я ожидал бы просто преобразовать байты в строку, а затем преобразовать обратно из строки в массив байтов. Нет необходимости использовать потоки вообще. –

+0

Ну, raw - это, очевидно, ByteArrayOutputStream, содержащий байты в любой кодировке, которая была использована нашим клиентом двоичных данных. Мы должны перенести эти данные в нашу Систему в формате utf-8, поэтому нам нужно преобразовать все, что угодно, в utf-8 или что-то еще. Я надеюсь, что это очистит. Прямо сейчас, строя строку. –

+2

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Если самый очевидный подход неуместен, вам нужно объяснить * почему * это так. И преимущество короткого, но полного примера заключается в том, что то, что вы считаете «очевидным», указано в коде. Слишком часто я делал предположения, которые кажутся мне «очевидными», но оказываются не такими ... и когда вы теперь добавляете ограничения относительно того, что возможно, а что нет, это добавляет путаницы. –

ответ

7

Как уже упоминалось в комментариях, я просто преобразовать в строку:

String text = new String(raw.toByteArray(), encoding); 
byte[] utf8 = text.getBytes(StandardCharsets.UTF_8); 

Однако, если это не представляется возможным (по какой-то причине неустановленный ...), что у вас есть сейчас почти там - Вам просто нужно добавить OutputStreamWriter в смесь:

// Nothing here should throw IOException in reality - work out what you want to do. 
public byte[] convertStream(Charset encoding) throws IOException {  
    ByteArrayInputStream original = new ByteArrayInputStream(raw.toByteArray()); 
    InputStreamReader contentReader = new InputStreamReader(original, encoding); 

    int readCount; 
    char[] buffer = new char[4096]; 
    try (ByteArrayOutputStream converted = new ByteArrayOutputStream()) { 
     try (Writer writer = new OutputStreamWriter(converted, StandardCharsets.UTF_8)) { 
      while ((readCount = contentReader.read(buffer, 0, buffer.length)) != -1) { 
       writer.write(buffer, 0, readCount); 
      } 
     } 
     return converted.toByteArray(); 
    } 
} 

Обратите внимание, что вы по-прежнему создает дополнительную временную копию данных в памяти, правда, в UTF-8, а не UTF-16 ... но принципиально это вряд ли более эффективно, чем создание строки.

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

+0

Perfect OutputStreamWriter был ответом! Этого было бы достаточно для меня! –

Смежные вопросы