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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Почему System.in не буферизуется между строками? 
V
    Опции темы
Dims
Дата 18.9.2009, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Почему вот такой код:

Код

BufferedReader inReader = new BufferedReader(new InputStreamReader(System.in));
String phrase = inReader.readLine();
System.out.println("\nYou said: " + phrase);


выдаёт первую же введённую короткую строку сразу после ENTER? Ведь по умолчанию длина буфера BufferedReader составляет 8192 символов, почему же она их не буферизует?

Это сообщение отредактировал(а) Dims - 19.9.2009, 08:26
PM MAIL   Вверх
LSD
Дата 19.9.2009, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



А если ты у BufferedReader-а вызовешь метод чтения одного символа, он что по твоему должен вернуть?

BufferedReader работает следующим образом: он читает из нижележащего Reader-а в свой внутренний буфер. При чтении из BufferedReader-а он вначале выдает данные из своего внутреннего буфера, а когда они там заканчиваются снова читает данные из нижележащего Reader-а в свой внутренний буфер. При этом количество данных которые вернет BufferedReader не зависит от размера его внутреннего буфера, оно зависит только от того какой метод ты вызвал и сколько данных есть в нижележащем Reader-е.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Dims
Дата 19.9.2009, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(LSD @  19.9.2009,  16:08 Найти цитируемый пост)
При чтении из BufferedReader-а он вначале выдает данные из своего внутреннего буфера, а когда они там заканчиваются снова читает данные из нижележащего Reader-а в свой внутренний буфер.


Если буфер пуст, то сколько данных BufferedReader считывает из нижележащего Reader-а?

Добавлено через 3 минуты и 37 секунд
Цитата(LSD @  19.9.2009,  16:08 Найти цитируемый пост)
А если ты у BufferedReader-а вызовешь метод чтения одного символа, он что по твоему должен вернуть?


Ты не понял. Вопрос не в том, что он должен вернуть. А в том, что он должен взять. Возвращают все методы то, что написано в мануале. Если 1 символ, то 1 символ, а если 1 строку, то 1 строку. 

Но при этом иногда он из нижележащего ридера читает много строк, а иногда одну. Вот в этом и вопрос.

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


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(Dims @  19.9.2009,  16:11 Найти цитируемый пост)
Если буфер пуст, то сколько данных BufferedReader считывает из нижележащего Reader-а?

Пытается полностью заполнить внутренний буфер, но сколько реально будет прочитано данных зависит от нижележащего Reader-а.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Dims
Дата 19.9.2009, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Я написал вот такой класс:

Код

public class PseudoInputStream extends InputStream {

    private List<Character> buffer = new Vector<Character>();

    @Override
    public int read() throws IOException {
        while( buffer.size() == 0  ) {
            buffer.add('H');
            buffer.add('e');
            buffer.add('l');
            buffer.add('l');
            buffer.add('o');
            buffer.add('!');
            buffer.add('\n');
            buffer.add('\r');

            
            System.out.println("Line added in read");
        }
        char ans = buffer.remove(0);
        return ans;
    }



и при той же самой программе:

Код

try {
            //BufferedReader inReader = new BufferedReader(new InputStreamReader(System.in));
            BufferedReader inReader = new BufferedReader(new InputStreamReader(new PseudoInputStream()));
            //BufferedReader inReader = new BufferedReader(new InputStreamReader(new PseudoInputStream2()));
            String phrase = inReader.readLine();
            System.out.println("\nYou said: " + phrase);
        } catch (Exception ex) {
            ex.printStackTrace();
        }


получил вот такую выдачу:

Код

Line added in read
Line added in read
...
...
...
Line added in read

You said: Hello!


То есть, здесь видно, что программа сперва прочитала много строк в буфер, а потом только вернулась из readLine.

Добавлено через 46 секунд
Цитата(LSD @  19.9.2009,  16:17 Найти цитируемый пост)
Пытается полностью заполнить внутренний буфер, но сколько реально будет прочитано данных зависит от нижележащего Reader-а. 


Каким образом зависит? Как нижестоящий Ридер может повлиять на это?
PM MAIL   Вверх
LSD
Дата 19.9.2009, 16:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(Dims @  19.9.2009,  16:18 Найти цитируемый пост)
Каким образом зависит? Как нижестоящий Ридер может повлиять на это?

Метод 
Код

public int read(char[] cbuf, int off, int len)

возвращает число символов которое было реально прочитано. Сколько байт будет прочитано предсказать заранее нельзя. Данные могут просто закончится, могут еще не придти (если идет чтение по сети) и т.д., все зависит от реализации Reader-а и того откуда он берет данные.


В твоем примере реализация метода read(byte[], int, int) из класса InputStream будет вызывать твой read() до тех пор пока не будет прочитанно нужное количество байт или пока метод не вернет -1 (что означает конец потока).


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Dims
Дата 19.9.2009, 19:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(LSD @  19.9.2009,  16:38 Найти цитируемый пост)
В твоем примере реализация метода read(byte[], int, int) из класса InputStream будет вызывать твой read() до тех пор пока не будет прочитанно нужное количество байт или пока метод не вернет -1 (что означает конец потока). 


Как ты приходишь к такому выводу? Почему в случае с System.in работает не так?

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


Эксперт
***


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

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



Разобрался.
PM MAIL   Вверх
LSD
Дата 22.9.2009, 11:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(Dims @  19.9.2009,  19:11 Найти цитируемый пост)
Как ты приходишь к такому выводу?

Открываю исходники JDK и смотрю код smile 


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Dims
Дата 22.9.2009, 12:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Да, пришлось читать исходники. Интересно, что в данном случае из документации почерпнуть правильную информацию затруднительно.
PM MAIL   Вверх
LSD
Дата 22.9.2009, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(Dims @  22.9.2009,  12:28 Найти цитируемый пост)
Интересно, что в данном случае из документации почерпнуть правильную информацию затруднительно. 

Вся необходимая информация в документации есть, просто надо читать внимательней.
Цитата
public int read(byte[] b,
                int off,
                int len)
         throws IOException

Reads up to len bytes of data from the input stream into an array of bytes. An attempt is made to read as many as len bytes, but a smaller number may be read. The number of bytes actually read is returned as an integer. 
This method blocks until input data is available, end of file is detected, or an exception is thrown. 

If len is zero, then no bytes are read and 0 is returned; otherwise, there is an attempt to read at least one byte. If no byte is available because the stream is at end of file, the value -1 is returned; otherwise, at least one byte is read and stored into b. 

The first byte read is stored into element b[off], the next one into b[off+1], and so on. The number of bytes read is, at most, equal to len. Let k be the number of bytes actually read; these bytes will be stored in elements b[off] through b[off+k-1], leaving elements b[off+k] through b[off+len-1] unaffected. 

In every case, elements b[0] through b[off] and elements b[off+len] through b[b.length-1] are unaffected. 

The read(b, off, len) method for class InputStream simply calls the method read() repeatedly. If the first such call results in an IOException, that exception is returned from the call to the read(b, off, len) method. If any subsequent call to read() results in a IOException, the exception is caught and treated as if it were end of file; the bytes read up to that point are stored into b and the number of bytes read before the exception occurred is returned. The default implementation of this method blocks until the requested amount of input data len has been read, end of file is detected, or an exception is thrown. Subclasses are encouraged to provide a more efficient implementation of this method.



--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Dims
Дата 22.9.2009, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Ну если достаточно внимательно читать документацию, зачем же тогда ты сам залез в исходники почитать код? ;)
PM MAIL   Вверх
LSD
Дата 22.9.2009, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Я делаю то, что проще/быстрее в данный момент.

Конечно исходники дадут больше информации, как все устроенно внутри и как оно работает. Но утверждать что в документации недостаточно информации для реализации своего InputStream - нельзя. Тем более что, читать документацию нужно обязательно дабы знать контракт.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Dims
Дата 22.9.2009, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Это теория. В данном случае в контракте не написано, КАК именно я должен реализовывать read(массивы). "Эффективно" -- это слишком общий термин. 

На мой взгляд, неполно составлен контракт BufferedReader в т.ч. readLine. Там должно было быть написано, что сперва для заполнения буфера используется read(массивы).
PM MAIL   Вверх
LSD
Дата 23.9.2009, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(Dims @  22.9.2009,  21:36 Найти цитируемый пост)
Это теория. В данном случае в контракте не написано, КАК именно я должен реализовывать read(массивы). "Эффективно" -- это слишком общий термин. 

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



Цитата(Dims @  22.9.2009,  21:36 Найти цитируемый пост)
На мой взгляд, неполно составлен контракт BufferedReader в т.ч. readLine. Там должно было быть написано, что сперва для заполнения буфера используется read(массивы). 

1. Да все там нормально, если почитать описание класса BufferedReader, то его поведение становится очевидным.
2. То что какой-то аспект не описан, значит он не является частью контракта и implementation specific. Ты прицепился к своему примеру и не хочешь взглянуть на проблему шире, тот же readLine() может обращаться к нижележащему потоку неограниченное количество раз (если строка длинная а данные приходят малыми порциями). Для нормальной работы с BufferedReader эта информация - не нужна.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

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

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


 




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


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

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