Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как правильно extends InputStream? 
V
    Опции темы
Dims
Дата 18.9.2009, 19:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 4
Всего: 11



У меня есть одна готовая программа, которая принимает текстовые данные в виде InputStream. Я смотрел код -- внутри она от этого InputStream in формирует new BufferedReader(new InputStreamReader(in)) и потом для получившегося вызывает readLine.

У меня есть вторая программа, которая выдаёттекстовые данные в виде строк String.

Мне надо подать выход второй программы на вход первой.

Я подумал, что смогу завернуть вторую программу в класс extends InputStream (реализовав метод read) и всё получится. 

Написал так:

Код

public int read() throws IOException {
        while( buffer.length() == 0  ) {
            // .... добавление строки ....
            buffer.append("\n");
        }
        char ans = buffer.charAt(0);
        buffer.deleteCharAt(0);
        return ans;
    }


Я думал, что встретив символ новой строки, обёртки потока прекратят чтение до следующего вызова readLine. Но не тут-то было. Судя по отладчику, после того, как этот метод возвращает символ новой строки, он вызывается снова и снова, а возврата из метода readLine не происходит.

Судя по всему, какой-то промежуточный слой занимается буферизацией, то есть, где-то считывает, скажем, 1024 символа и уж потом собирается вернуть первую строку.

Вопрос -- как этого избежать? Как сделать, чтобы readLine возвращал строки в той же разбивке, в которой я их формирую?

Добавлено через 10 минут и 56 секунд
P.S. Забыл сказать, что переменная buffer определена так:

private StringBuilder buffer = new StringBuilder();

(это член класса, в который я заворачиваю выдающую программу)

Это сообщение отредактировал(а) Dims - 18.9.2009, 19:27
PM MAIL   Вверх
ivg
Дата 18.9.2009, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 33
Всего: 81



Код, который принимает вывод у второй программы и запихивает в буфер?
Вобщем решение такое: в топку буфер, первая программа сразу читает вывод второй, т. к. read() - блокирующий вызов. Все нюансы такого чтения в этом самом наследнике InputStream.
?
PM MAIL   Вверх
Dims
Дата 18.9.2009, 20:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 4
Всего: 11



Полностью код выглядит так:


Код

@Override
    public int read() throws IOException {
        while( buffer.length() == 0  ) {
            Result result = recognizer.recognize();
            if (result != null) {
                buffer.append( result.getBestFinalResultNoFiller() );
            }
            buffer.append("\n");
        }
        char ans = buffer.charAt(0);
        buffer.deleteCharAt(0);
        return ans;
    }


Здесь видно, что для получения строки, я должен сделать сначала

Result result = recognizer.recognize()

а потом

result.getBestFinalResultNoFiller()

И я получу строку. Как мне это направить на вход?
PM MAIL   Вверх
ivg
Дата 18.9.2009, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 33
Всего: 81



Цитата(Dims @  18.9.2009,  22:01 Найти цитируемый пост)
ак мне это направить на вход? 

Да по всякому можно.
Код

private StringReader currentString;
...
@Override
    public int read() throws IOException {
        char ch = this.currentString.read();
        if (ch < 0) {
            Result result = recognizer.recognize();
            if (result != null) {
                this.currentString = new StringReader(result.getBestFinalResultNoFiller() + "\n");
                ch = this.currentString.read();
            }
        }
        return ch;
    }

Как то так. Надо ещё определится с концом вывода второй программы.
PM MAIL   Вверх
Dims
Дата 18.9.2009, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 4
Всего: 11



Чем это принципиально отличается от того, что у меня? Наверняка то же самое будет происходить.
PM MAIL   Вверх
ivg
Дата 18.9.2009, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 33
Всего: 81



Цитата(Dims @  18.9.2009,  22:54 Найти цитируемый пост)
Чем это принципиально отличается от того, что у меня? Наверняка то же самое будет происходить. 

Я предполагал, что вывод второй программы существует в виде InputStream. Во вторых не надо содержимое буфера сдвигать каждый раз. В третьих - если метод recognizer.recognize(); не блокирующий - то код выше тоже в топку и искать способы синхронизации в выводом второй программы.
PM MAIL   Вверх
Dims
Дата 18.9.2009, 23:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 4
Всего: 11



Цитата(ivg @  18.9.2009,  21:38 Найти цитируемый пост)
Во вторых не надо содержимое буфера сдвигать каждый раз. 

Скорее всего, внутри StringBuilder находится двусвязный список и на сдвиг затрат не происходит.

Цитата(ivg @  18.9.2009,  21:38 Найти цитируемый пост)
В третьих - если метод recognizer.recognize(); не блокирующий

А что это означает?

PM MAIL   Вверх
ivg
Дата 19.9.2009, 06:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 33
Всего: 81



Цитата(Dims @  19.9.2009,  01:10 Найти цитируемый пост)
Скорее всего, внутри StringBuilder находится двусвязный список и на сдвиг затрат не происходит.

Я то, убедился, прежде чем написал. smile
Цитата(Dims @  19.9.2009,  01:10 Найти цитируемый пост)
А что это означает?

Поток, в котором произошел вызов метода, блокируется (выполнение приостанавливается) до получения результата.
PM MAIL   Вверх
Dims
Дата 19.9.2009, 08:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 4
Всего: 11



Цитата(ivg @  19.9.2009,  06:20 Найти цитируемый пост)
Поток, в котором произошел вызов метода, блокируется (выполнение приостанавливается) до получения результата. 

Не понимаю, какую это может иметь роль? Функция возвращает строку -- работай с этой строкой. Почему работа происходит неправильно?

Я переписал метод вот так (пока фиг с ним со StringBuilder):

Код

@Override
    public int read() throws IOException {
        while( buffer.length() == 0  ) {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException ex) {
                
            }
            buffer.append( "Hello World!" );
            System.out.println("line added in read");
            buffer.append("\n");
        }
        char ans = buffer.charAt(0);
        buffer.deleteCharAt(0);
        return ans;
    }



а вызов происходит вот так

Код

while (true) {
            try {
                phrase = inReader.readLine();
                System.out.println("\nYou said: " + inReader.readLine());
            } catch (IOException ex) {
                ex.printStackTrace();
                System.exit(1);
            }
        }


и я вижу, что сперва выводится куча раз

line added in read

и только потом начинает выводиться

Hello World!

Как от этого избавиться?
PM MAIL   Вверх
Akeem
Дата 19.9.2009, 09:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 381
Регистрация: 14.7.2006
Где: Киев/Украина

Репутация: нет
Всего: 3



А не проще ли будет сделать как советует сан?

Код

String str = "hello world";
InputStream. iostream = new ByteArrayInputStream.(str.getBytes());



и дальше передавать его. 


Ну если уж очень сильно хочется, то есть класс StringBufferInputStream  -- но он после 1.4.2 обьявлен Deprecated

Код

String str = "Hello world";
        
        StringBufferInputStream striostream = new StringBufferInputStream(str);
        
        if (striostream instanceof InputStream)
        {
            System.out.println(true); //При проверке попадал сюда
        }




Это сообщение отредактировал(а) Akeem - 19.9.2009, 09:50


--------------------
Мир огромен и мы только муравьи в нём! (С) formicha

PM MAIL WWW ICQ   Вверх
Dims
Дата 19.9.2009, 15:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 4
Всего: 11



Может и проще, но мне теперь уже непонятна логика происходящего и хочется разобраться. 

Если я в качестве потока использую System.in, то всё работает как надо, то есть, readLine читает из потока только одну строку и сразу же её возвращает, как только встретился символ новой строки. Если же я в качестве входного потока даю свой поток, то почему-то readLine не останавливается на первом символе НС, а продолжает читать дальше, пока не заполнит буфер.

Естественно, возвращает он в обоих случаях только одну первую строку, но считывает в разных случаях разное. Мне непонятно, почему. И как я могу воспроизвести поведение System.in в своём классе.
PM MAIL   Вверх
Dims
Дата 19.9.2009, 23:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 4
Всего: 11



Разобрался.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0546 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.