Лучший способ использовать InputStream в отношении персистентности и XML - PullRequest
3 голосов
/ 12 марта 2009

У меня есть веб-сервис REST, который прослушивает POST-запросы и захватывает полезную нагрузку XML от клиента и изначально сохраняет ее как InputStream, т.е. *

Я хочу использовать XML, хранящийся во InputStream, и я начинаю думать, что было бы разумно сохранить его, поэтому я могу запрашивать данные несколько раз - так как после прочтения его объект становится нулевым. Поэтому я подумал о преобразовании InputStream в строку. Это не очень хорошая идея, так как DocumentBuilder.parse () из библиотеки javax.xml.parsers позволяет только передавать:

  • InputStreams
  • Файлы
  • 1012 * URL-адресов *
  • SAX InputSources

не строки.

Что мне действительно следует делать здесь с InputStreams в отношении анализа XML из него? Имея в виду, я хочу повторно запросить этот XML в будущих процессах с помощью кода.

Ответы [ 6 ]

2 голосов
/ 12 марта 2009

Если у вас есть InputStream и вы хотите использовать его в качестве XML-документа, то почему вы просто не анализируете его и не передаете объект Document? Если вы хотите сохранить этот объект, используйте сериализаторы, чтобы записать его обратно в виде текста.

Как я отметил в своем комментарии к Тому Хоутину, кодирование очень важно при работе с XML. Вместо того, чтобы писать длинную публикацию здесь, которая может пропустить вашу конкретную ситуацию, вот статья , которую я написал.

Редактировать: на самом деле, поскольку в моей статье конкретно не говорится о веб-сервисах, я должен немного углубиться в это здесь. Кодировка содержимого может быть указана в двух местах: в прологе XML или в заголовке ответа Content-Type . Согласно спецификации XML, первое, что вы хотите использовать, и то, что будет использовать анализатор. В большинстве случаев это не имеет значения: веб-сервис, созданный человеком, который не знает спецификацию, обычно использует текст / xml без спецификации набора символов (что неверно, но, вероятно, не причинит вреда). Если они все делают правильно, они укажут application / xml с кодировкой utf-8. Однако вы должны проверить, что вы получаете, чтобы у вас не получилось странного кодирования, которое парсер не может обработать.

1 голос
/ 12 марта 2009

Я бы посоветовал использовать библиотеку Apache Commons IO . Класс IOUtils содержит много удобных методов для преобразования InputStreams в String и наоборот.

1 голос
/ 12 марта 2009

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

Если вы просто говорите о том, чтобы держать его в памяти (что звучит как то, что вы спрашиваете), то вы можете выделить байтовый массив и прочитать все это в байтовом массиве. Вы можете использовать ByteArrayInputStream для чтения и перечитывания этого потока.

Стоимость с этим в два раза. Во-первых, вы держите копию в памяти, и вам необходимо сопоставить ее с требованиями масштабируемости. Во-вторых, синтаксический анализ XML стоит довольно дорого, поэтому лучше разбирать его только один раз, если это возможно, и сохранять результат в объекте.

Edit:

Чтобы выделить и прочитать байтовый массив, вы часто (но не всегда) можете полагаться на метод InputStream available (), чтобы сообщить вам, сколько выделить. и оберните InputStream с DataInputStream, чтобы вы могли вызвать readFully (), чтобы засосать все это в байтовый массив одним вызовом.

Редактировать снова:

Прочитайте комментарий Стин ниже. Он прав, что в этом случае использовать available () - плохая идея.

0 голосов
/ 12 марта 2009

Если вы хотите использовать XML несколько раз, почему бы не проанализировать его один раз из InputStream (что является тяжелой работой), а затем удержать возвращенный документ?

0 голосов
/ 12 марта 2009

Я думаю, вы должны рассмотреть некоторые структуры, лучше подходящие для сохранения кодировок (то есть, более независимые от кодирования). Для низкоуровневых структур рассмотрите byte[] (но будьте осторожны с освобождением памяти!), Или вы можете попытаться спроектировать тип данных, который соответствует вашим потребностям.

Вы можете прочитать InputStream в ByteArrayOutputStream (используя один из методов read()) и извлечь byte[] из есть .

0 голосов
/ 12 марта 2009

java.io.StringReader позволит вам использовать InputSource.

Возможно, вы захотите сохранить данные в byte[] и затем прочитать с помощью ByteArrayInputStream. Если оно особенно большое, вы можете рассмотреть возможность сжатия. Это можно прочитать с GzipInputStream, который часто следует заключать в BufferedInputStream.

...