Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > запись/чтение в один поток


Автор: Leos239 15.2.2009, 23:56
Добрый день!

Я новичок в Java и у меня следующая проблема:
работает некоторая программа и пишет xml-подобный файл, например:

<calcalation name="calc1" energy="239.1" iternum="7" />
<calcalation name="calc2" energy="239.0" iternum="109" />
<calcalation name="calc3" energy="239.14" iternum="34" />
...........................................................................................

мне надо прочитать и обработать этот файл другой программой, однако, если поступать так:
Код

DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = fact.newDocumentBuilder();
Document doc = builder.parse(fileName);


то вылетает исключение "The markup in the document following the root element must be well-formed"
что вполне правомочно, ибо корневого элемента нет;

Как я понимаю, следут передавать правильный xml-файл или поток с xml для метода builder.parse(), т.е. 

<calculations>
<calcalation name="calc1" energy="239.1" iternum="7" />
<calcalation name="calc2" energy="239.0" iternum="109" />
<calcalation name="calc3" energy="239.14" iternum="34" />
...........................................................................................
</calculations>

если бы я писал программу на Delphi, то я бы сделал бы примерно так: создал объект класса TMemomyStream, записал бы туда "<calculations>" + содержимое файла + "</calculations>"
и передал бы этот поток для парсинга;
в метод builder.parse() надо обязательно передать потомка класса InputStream, но я не могу записать в InputStream строчки для корня "<calculations>" и "</calculations>" (и вообще ничего не могу туда записать);
Можно, конечно, создать временный файл вместо потока в памяти, но может быть есть более нормальное решение?
может есть какой-нибудь стандартный класс, который реализует интерфейсы InputStream и OuputStream?

Автор: v2v 16.2.2009, 00:30
я так понимаю тебе постоянно надо добавлять по одной строчке... вычитывать , парсить и заново записывать действительно не совсем экономично.
В Ява есть класс http://java.sun.com/j2se/1.5.0/docs/api/java/io/RandomAccessFile.html позволяет писать, читать из указаного места в файле. Попробуй воспользоваться им. 

Автор: Kangaroo 16.2.2009, 01:25
Цитата(Leos239 @  15.2.2009,  23:56 Найти цитируемый пост)
создал объект класса TMemomyStream, записал бы туда "<calculations>" + содержимое файла + "</calculations>"

Сделай наследника от инпутстрима, который будет вставлять calculations вначале и вконце. Хотя способ v2v легче.

Автор: math64 16.2.2009, 10:23
Самый простой способ - использовать StringReader и StringWriter - аналоги TMemoryStream из Delphi. Но правильнее создать наследика InputStream или Reader, как советует Kangaroo. А что советует делать v2v, а не понимаю.

Автор: Leos239 16.2.2009, 16:11
Цитата(v2v @  16.2.2009,  00:30 Найти цитируемый пост)
я так понимаю тебе постоянно надо добавлять по одной строчке...

нет, мне надо читать этот "xml-файл" редко и пол секунды на его распарсивание можно пережить;

Цитата(Kangaroo @  16.2.2009,  01:25 Найти цитируемый пост)
Сделай наследника от инпутстрима, который будет вставлять calculations вначале и вконце

так в этом и вопрос как сделать такого наследника:
этот наследник должен быть наследником InputStream (чтобы его можно было передать в builder.parse) и OutputStream (чтобы в него можно было записывать);
как сказал, я новичок в Java и не до конца понимаю как написать такой класс; может есть готовое решение??

Цитата(math64 @  16.2.2009,  10:23 Найти цитируемый пост)
Самый простой способ - использовать StringReader и StringWriter - аналоги TMemoryStream из Delphi

в том-то и дело, что не аналоги - каждый из них умеет либо только читать либо только писать, и TMemoryStream может и то и то;
тем более что StringReader не является потомком от InputStream, поэтому его нельзя использовать в builder.parse()

Автор: math64 16.2.2009, 16:43
StringWriter записывает, после записи получаешь String, передаёшь её конструктору StringReader, который передаёшь парсеру.
Можно использовать SequenceInputStream:
Код

Vector v = new Vector(3);
v.addElement(new StringBufferInputStream("<calculations>"));
v.addElement(new FileInputStream(filename));
v.addElement(new StringBufferInputStream("<calculations>"));
SequenceInputStream is = new SequenceInputStream(v.elements());

Автор: Leos239 16.2.2009, 19:36
math64, спасибо!
SequenceInputStream работает!
а через StringReader нельзя, т.к. для builder.parse() нужет потомок InputStream, а StringReader потомок от Reader;


Автор: v2v 16.2.2009, 23:07
Цитата(Leos239 @  16.2.2009,  16:11 Найти цитируемый пост)

нет, мне надо читать этот "xml-файл" редко и пол секунды на его распарсивание можно пережить;

нет, вопрос в том как часто ты его пишешь?...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)