std :: istream заканчивается неожиданно - PullRequest
0 голосов
/ 19 февраля 2019

Я пытаюсь прочитать двоичный файл кусками.Файл составляет около 11 кБ.Следующий код читает файл только один раз, а функция gcount() сообщает, что было прочитано только 1015 символов (байтов), а поток «исчерпан» и цикл while не продолжается (хотя буфер заполнен правильно до buffer[4095]):

std::array<int64_t, 256>  HuffmanTree::get_frequencies(std::istream & stream) const
{
    const size_t buffer_size = 4096;
    unsigned char buffer[buffer_size];
    std::array<int64_t, 256> frequencies;
    frequencies.fill(0);

    while (stream)
    {
        stream.read((char *)buffer, buffer_size);
        std::streamsize bytes_read = stream.gcount();

        for (std::streamsize i = 0; i < bytes_read; i++)
        {
            frequencies[buffer[i]]++;
        }
    }

    return frequencies;
}

Что вызывает это поведение и как я могу это исправить?

Редактировать: stream.read(...) вызывается только ОДИН РАЗ, а gcount() возвращает 1015. Но буфер содержитпервые 4096 байт файла (также я работаю на Windows - VS 2017)

1 Ответ

0 голосов
/ 19 февраля 2019

Я полагаю, что ваша проблема возникает, когда у вас меньше 4096 байт для чтения, и вы вызываете stream.read()

Я использую следующую функцию, которая ПРОБЫВАЕТ прочитать 4096, но исправляет при сбое -может быть, это полезно?

// Tries to read num bytes from inRaw into buffer (space previously allocated).  When num bytes does not take
// us off the end of the file, then this does the simple obvious thing and returns true.  When num bytes takes
// us over the edge, but things are still sane (they wanted 100 bytes, only 60 bytes to go), then this fills
// as much as possible and leaves things in a nice clean state.  When there are zero bytes to go, this
// return false.
bool safeRead(
    std::ifstream& inRaw,
    char* buffer,
    uint16_t num
)
{
    auto before = inRaw.tellg();
    if (inRaw.read(buffer, num) && inRaw.good() && !inRaw.eof())
    {
        return true;
    }
    else
    {
        if (inRaw.gcount())
        {
            inRaw.clear();
            auto pos = before + std::streamoff(inRaw.gcount());
            inRaw.seekg(pos);
            return true;
        }
        else
        {
            return false;
        }
    }
}
...