Нежелательные символы, записанные из java REST-API в HadoopDFS с использованием FSDataOutputStream

Мы создали java REST-API для получения данных о событиях (например, при нажатии на кнопку покупки) и записи этих данных в HDFS. По сути, мы открываем потоки для каждого хоста, который отправляет данные (в формате JSON), или используем существующие, обогащаем данные отметкой времени, именем события и именем хоста и записываем их в (FS)DataOutputStream:

1 public synchronized void writeToFile(String filename, String hostname, String content) throws IOException {
2    FSDataOutputStream stream = registry.getStream(filename, hostname);
3    stream.writeBytes(content);
4    stream.hflush();
5  }

Во-первых, мы использовали stream.writeChars(content) в строке 3, что привело к таким файлам, как: .{.".m.e.s.s.a.g.e.".:.".h.e.l.l.o.".} Глядя на реализацию DataOutputStream.writeChars(String s), вы видите 8-битный сдвиг вправо и добавление начального x00 для каждого символа по причинам i не понимаю.

Затем я попробовал stream.writeUTF(content) в строке 3, файлы выглядели намного лучше: .W{"message":"hello"} Но все же, несколько байт на много. Глядя на код, writeUTF(String s) сначала отправляет количество байтов в s, а затем саму строку. Таким образом, .W представляет количество байтов в данных события, подтвержденное изменением длины данных события, которое показало разные начальные символы в файле.

Так что мое последнее средство, stream.writeBytes(content). Здесь все выглядело нормально: {"message":"hello"}, пока не вступили в действие специальные символы: {"message":"hallöchen"} стало {"message":"hall.chen"}. writeBytes вырезает первые 8 бит символа перед его записью. Я думаю, что мне нужна некоторая функциональность UTF-8, чтобы правильно писать эти символы.

Итак, теперь я немного потерян. Как я могу это решить?


person Alex    schedule 30.10.2013    source источник


Ответы (2)


Когда я прочитал это: Почему добавляет ли DataOutputStream.writeUTF() дополнительные 2 байта в начале? я чувствовал, что упомянутые методы FSDataOutputStream не будут работать для этого. Быстрое (и, возможно, грязное) решение таково:

3 byte[] contentAsBytes = content.getBytes("UTF-8");
4 for (byte singleByte : contentAsBytes) {
5   stream.writeByte(singleByte);
6 }

Более чистым способом было бы не использовать FSDataOutputStream, но я не смог найти альтернативу. Любой намек по-прежнему приветствуется.

person Alex    schedule 31.10.2013
comment
stream.write(contentAsBytes, 0, contentAsBytes.length); может заменить ваш цикл for. - person Nico; 02.05.2018

Вы пытались обернуть FSDataOutputStream в java.io.PrintStream и использовать его методы печати. Это долгий путь, но дайте мне знать, если это сработает для вас.

person Arvind    schedule 12.03.2015