Неполные данные из потока

Я читаю данные из потока процесса. По сути, я запускаю процесс с помощью API Runtime.exec и получаю входной поток процесса.

Runtime rt = Runtime.getRuntime();
process = rt.exec("C:/cygwin/home/grec.exe");
InputStream is = process.getInputStream();

Затем я собираю выходные данные процесса как --

            BufferedReader in = new BufferedReader(is);         
            char[] ls = new char[s.available()];
            ls.read(ls);
            String output = new String(ls);

Однако, когда я печатаю вывод строки, я получаю --

  break [loc]     Add a breakpoint at [file:]line or template
  callflow [val]  Enable call flow tracing
  next            Execute the over instruction, stepping over calls
  over            Execute the current instruction hierarchy

Но фактический результат -

  break [loc]     Add a breakpoint at [file:]line or template
  callflow [val]  Enable call flow tracing 
  next            Execute the over instruction, stepping over calls
  over            Execute the current instruction hierarchy
  print <xpath>   Print the value of an XPath expression
 profile [val]   Turn profiler on or off
 reload          Reload the script contents
 run             Restart the script
 step            Execute the next instruction, stepping into calls
 verbose         Turn on verbose (-v) output logging
 where           Show the backtrace of template calls
 quit            Quit debugger

То есть часть вывода усекается, но код не выдает никаких исключений. Я попытался увеличить размер BufferedReader, а также увеличить размер массива ls. Я не могу найти причину такого поведения. Любые подсказки или указатели на то, что может быть причиной этого, будут высоко оценены.


person user496934    schedule 16.01.2012    source источник
comment
Что такое s в вашем примере кода? И может я что-то проглядел, но как насчет OutputStream out = process.getOutputStream(); BufferedReader bufferedOut = new BufferedReader(out);   -  person bpgergo    schedule 16.01.2012
comment
На самом деле я делаю то же самое. И это то, что я делаю--   -  person user496934    schedule 16.01.2012
comment
Здесь на самом деле s означает InputStream. То есть --InputStream s = process.getInputStream();   -  person user496934    schedule 16.01.2012
comment
Почему бы не использовать in.readline()? Почему вы создаете массив символов?   -  person artbristol    schedule 16.01.2012


Ответы (2)


Используйте цикл для обработки всей информации и чтения до конца потока.

Inputstream. available() не делает того, что вы ожидали:

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

http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#available%28%29

person Ishtar    schedule 16.01.2012

Вы совершаете ошибку, предполагая, что available() говорит вам, сколько байтов/символов действительно доступно. На самом деле, он говорит вам, что доступно как минимум столько-то... и это может быть неверным, потому что это оценка.

Затем вы усугубляете проблему, обращаясь к InputStream после того, как завернули его в BufferedReader. Таким образом, вместо получения количества символов, которые можно прочитать из устройства чтения, вы получаете количество доступных байтов, которые еще не были прочитаны в буфер.


Вам, вероятно, лучше просто читать из BufferedReader строки за раз, используя readLine().

person Stephen C    schedule 16.01.2012
comment
Здравствуйте, Степан, спасибо за разъяснения. Теперь я понимаю ошибку в моем коде. Я попытался использовать API BufferedReader.readLine в своем коде. Однако здесь я столкнулся с другой проблемой. Мой вывод процесса -- sdb: Отладчик SLAX (версия 0.9.6) Введите 'help' для справки (sdb) - person user496934; 16.01.2012
comment
Последняя строка — ‹sdb›. В этом случае вызов readLine просто зависает, не выдавая никаких исключений. - person user496934; 16.01.2012
comment
Выходные данные процесса всегда содержат ‹sdb› в качестве окончательного вывода. Он получает все строки правильно, но всегда зависает на последней строке и не возвращается с последнего вызова readLine. - person user496934; 16.01.2012
comment
Причина в том, что в последней строке нет новой строки (пока). Если вы хотите справиться с этим, вам нужно будет использовать персонажа за раз и правильно обрабатывать подсказку. - person Stephen C; 16.01.2012
comment
Спасибо за ваш вклад .. очень ценю. Но не могли бы вы объяснить это немного подробнее, с помощью кода. Как мне обработать последнюю строку, не вызывая зависания readLine. Кроме того, процесс вывода может варьироваться в зависимости от количества строк. Итак, как мне справиться с этим в общем виде - - person user496934; 16.01.2012
comment
Я использую этот код: BufferedReader in = new BufferedReader(isr); while ((line = in.readLine()) != null) { System.out.println(Thread this +line); вывод=выход+\n+строка; //System.out.println(in.ready()); } - person user496934; 16.01.2012
comment
@ user496934 - если вам приходится иметь дело с неполными строками, вы не можете использовать readLine(). Вы должны читать (и обрабатывать) по одному символу за раз, используя read(). - person Stephen C; 16.01.2012
comment
Спасибо, Стивен .. Очень ценю вашу помощь в этом. И теперь мне удалось решить эту проблему, немного подправив код. Но теперь я столкнулся с другой проблемой. В одном сценарии процесс выдает некоторый xml в качестве вывода, например: - person user496934; 16.01.2012
comment
‹?xml version=1.0?› Источник‹junos-output› безопасность { зоны {адрес зоны безопасности } } ‹/junos-output›‹local-variabl $destAdd = ; $добавитьИмя = ; $ipAdd = 172.168.1.2; $serviceN = junos-ftp; $зона = Доверие; $destAddress = безопасная_зона; $разрешение = разрешение; $ источник = источник; $количество = количество; $log = сессия-инициализация; $вал = ; ‹/local-variables› Скрипт завершился нормально. (сдб) - person user496934; 16.01.2012
comment
В этом случае я вижу, что readLine не может получить никакого вывода. Фактически, первый вызов readLine просто зависает на неопределенный срок. - person user496934; 16.01.2012