golang bufio.Read или bufio.ReadByte, чтобы определить, находится ли файл в EOF - PullRequest
1 голос
/ 28 марта 2019

Я хочу подтвердить, что больше нет байтов для чтения из буферизованного считывателя (ни из внутреннего буфера, ни из базового файлового объекта), пытаясь прочитать еще один байт (и перехватывая EOF).

Подходит ли для этой цели bufio.Read или bufio.ReadByte?

Из bufio.Read документации не ясно, может ли возвращаемое целое число быть нулевым, если неДела EOF.А именно, является ли 0, nil допустимым возвращаемым значением, если len(p) > 0?

func (b *Reader) Read(p []byte) (n int, err error)

Чтение считывает данные в p.Возвращает количество байтов, считанных в p.Байты берутся не более чем из одного чтения базового считывателя, следовательно, n может быть меньше len (p).Чтобы прочитать точно len (p) байтов, используйте io.ReadFull (b, p).В EOF количество будет равно нулю, а err будет равно io.EOF.

Точно так же документация bufio.ReadByte не очень хорошо отделяет случаи ошибок от случаев EOF и не совсем точно определяет, что означает "доступно" (т.е. доступно во внутреннем буфере,или доступно в базовом файле)?

func (b *Reader) ReadByte() (byte, error)

ReadByte считывает и возвращает один байт.Если байт недоступен, возвращает ошибку.

1 Ответ

3 голосов
/ 28 марта 2019

Передача буфера длиной от 1 до bufio.Read, , когда для считывателя поддерживается базовый os.File , действительно вернет n==0, io.EOF, если файл находится в EOF.

Документация немного неточна, потому что некоторые действия зависят от основного читателя, который вы передаете читателю bufio.Код для bufio.Read() рисует более точную картину.Я обрисую логику.

bufio.Read: Выдает Read только базовому считывателю, если все байты во внутреннем буфере исчерпаны.Итак, по-видимому, если вы уже прочитали столько байтов из буферизованного считывателя, сколько байтов в базовом файле, этот внутренний буфер должен быть исчерпан при последнем вызове bufio.Read(buf[0:1]) для проверки EOF.

Когда внутренний буфер исчерпан, и вы запрашиваете у читателя bufio больше, bufio.Read выполнит не более один вызов основного читателя.Тип ошибки, которую вы получите, будет зависеть от вашего основного читателя.

Запрос на чтение n > 0 байтов из os.File, когда указатель чтения уже находится в EOF, должен вернуть 0, io.EOF (в соответствии сДокумент о os.File File.Read).Но если ваш базовый читатель был чем-то другим, возможно, пользовательским типом, специфичным для вашего приложения, предназначенным для возврата 0, nil в EOF, тогда bufio.Read вернет это вместо этого.

bufio.ReadByte: Логика bufio.ReadByte немного отличается, но результат должен быть таким же, как bufio.Read в тех случаях, когда основной читатель - os.File.Основное отличие от bufio.Read состоит в том, что bufio.ReadByte может сделать несколько попыток пополнить внутренний буфер.Если во время повторного заполнения обнаружена ошибка (которая будет иметь место для считывателя os.File в EOF), она возвращается после первой ошибочной попытки чтения.Итак, если ваш базовый Reader является os.File читателем, то вы получите 0, io.EOF тогда и только тогда, когда ваш базовый файл находится в EOF.Если ваш базовый считыватель был пользовательским типом считывателя, который вернул 0, nil только в EOF, то bufio.ReadByte в конечном итоге выдаст ошибку «NoProgress».Я не уверен, почему логика повторения используется только в bufio.ReadByte, но хорошая новость заключается в том, что любой из вариантов можно использовать, если ваш базовый файл ведет себя как os.File.

Другая информация:

Это не относится напрямую к golang, но вам может быть интересен следующий поток: Может читать (2), возвращать ноль байтов, когда не в EOF .Его тема - семантика системного вызова read () (POSIX).Чтение неблокирующих сокетов / файлов, даже когда данные не готовы, должно возвращать -1, а не 0, и устанавливать errno EAGAIN (или EINTR при прерывании).Неблокирующие сокеты / файлы на самом деле не являются родной концепцией (насколько я знаю), и модуль bufio, в частности, будет panic() всякий раз, когда основной читатель возвращает отрицательные числа, поэтому у вас нетбеспокоиться об этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...