Понимание дизайна std :: istream :: read - PullRequest
5 голосов
/ 07 октября 2010

std::istream имеет прототип istream& read (char* s, streamsize n) фактическое число прочитанных байтов должно быть получено путем вызова istream::gcount(), также действительность istream может быть известна из ios::good.

Я обсуждал реализацию другого потокового класса, которую пытался написать с моим коллегой, где я говорил, что могу следовать этой схеме;но он сказал, что вместо того, чтобы пользователь каждый раз вызывал gcount , можно было бы прочитать прототип, подобный этому istream& read (char* s, streamsize n, size_t &bytes_read), чтобы он закончился за один вызов, а первый неуклюже.Я не смог защитить выбор дизайна std.Каково реальное обоснование istream::read?

Ответы [ 4 ]

4 голосов
/ 07 октября 2010

Я предполагаю, что это потому, что C ++ обычно не вызывает интерфейс, который может понадобиться не всем.Если вам требуется read для принятия параметра, который не имеет значения для некоторых людей, то это вызывает дополнительную работу по кодированию (объявление дополнительного int для передачи в качестве параметра).Он также всегда сохраняет прочитанные байты независимо от того, заботится клиент или нет (некоторые клиенты могут просто заботиться о том, что чтение не удалось, как указано битами eof / fail).

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

2 голосов
/ 11 октября 2010

Вместо этого попробуйте команду readsome,

streamsize readsome ( char* buf, streamsize num );

buf - это ваш буфер, а num - это количество байтов, которые вы хотите прочитать, конечно, самое большее количество байтов, доступных в вашем буфере.*

Возвращаемое значение - это количество фактически прочитанных байтов.

Чтобы прочитать файл до конца, вы можете выполнить цикл:

char buf[BUF_SIZE]
streamsize bytesRead;
do
{
   bytesRead = instr.readsome( buf, BUF_SIZE );
   // do stuff with the bytes you read, if any
} while ( bytesRead == BUF_SIZE );
0 голосов
/ 20 мая 2011

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

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

Конечно, правильным решением будет завершить цикл while, когда установлен флаг EOF,В настоящий момент я не уверен, что лучший ответ, когда установлен badbit, но вам, вероятно, следует также разобраться с этим случаем.

Я бы согласился, что readsome - достойная альтернатива чтению.

Редактировать: иногда readsome недоступен (некоторые версии VC ++).В этом случае чтение не является непригодным.

0 голосов
/ 10 октября 2010

std::istream имеет прототип istream& read (char* s, streamsize n) фактическое число прочитанных байтов должно быть получено путем вызова istream::gcount(), также действительность istream может быть известна из ios::good.

istream::read(char* s, streamsize n) считывает неформатированный блок данных (без завершения NULL) размером n в массив в s.Даже если s является указателем на char, вы можете использовать istream::read для чтения двоичных данных.Например, у вас может быть istream, который содержит значения массива значений типа double (при условии, что порядковый номер указан правильно):

unsigned int count;
input.read(reinterpret_cast<char*>(&count), sizeof(count));
double* data = new double[count];

for (unsigned int i = 0; i < count; ++i)
    input.read(reinterpret_cast<char*>(data[i]), sizeof(double));

istream::gcount() возвращает количество байтов, прочитанных в последнем istream::read звонок.В этом случае мы видим, что размер count, вероятно, отличается от размера double, поэтому мы не сможем использовать istream::gcount(), чтобы указать размер первого элемента в массиве data.

...