Конструирование QTextStream в цикле приводит к тому, что файл неправильно читает данные - PullRequest
0 голосов
/ 03 апреля 2019

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

К моему удивлению, это привело к неправильному сообщению QFile позиции файла, в результате чего QTextStream читает только одну строку или останавливается на кажущемся случайном номере строки в зависимости от файла.

Почему QTextStream ведет себя так?Я не смог найти никаких ссылок в документации по этому вопросу.Я что-то пропустил?

Пример кода

Это код ошибки, который я использовал (вырезанный из архитектуры и упрощенный)

QFile file;
QString line;
int interationCount = 0;
file.setFileName(fileName);

if(file.open(QIODevice::ReadOnly | QIODevice::Text))
{
    while(true)
    {
        QTextStream stream(&file);
        if(stream.readLineInto(&line) == false)
            break; //Or return

        std::count << "Line "<< interationCount << ": " << line << "\n";
        interationCount++;
    }
}

Ввод и вывод

При заданном файле чисел от 1 до 35, упорядоченном в каждой строке в текстовом формате, например:

1
2
3
...
35

Алгоритм считывает только одну строку вывода, в то время как ожидается чтение всех строк.

Вывод:

Line 0: 1

Ожидаемый вывод:

Line 0: 1
Line 1: 2
Line 2: 3
...
Line 34: 35

Ответы [ 2 ]

0 голосов
/ 03 апреля 2019

QTextStream не считывает данные из базового QIODevice байта за байтом, но имеет внутренний декодированный буфер, используемый как для того, чтобы избежать оплаты повторного виртуального вызова, так и для преобразования кодирования на больших кусках .

Это означает, что, как только вы начнете использовать его на QIODevice, он может прочитать с него больше, чем вы прочитали с QTextStream; это действительно объясняется в документации :

Так как текстовый поток использует буфер, вы не должны читать из потока, используя реализацию суперкласса. Например, если у вас есть QFile и вы читаете из него напрямую, используя QFile::readLine() вместо использования потока, внутренняя позиция текстового потока будет не синхронизирована с позицией файла.

Постоянно читая и уничтожая QTextStream, вы всегда получаете данные из файла в соответствии с размером буфера чтения, а затем отбрасываете все, что вы не читали из текстового потока.

0 голосов
/ 03 апреля 2019

Повторное построение из QTextStream по причинам, на которые ответил @MatteoItalia , вызывает эту ошибку.

Фиксированный код выглядит следующим образом:

QFile file;
QString line;
int interationCount = 0;

file.setFileName(fileName);

if(file.open(QIODevice::ReadOnly | QIODevice::Text))
{
    QTextStream stream(&file);
    while(stream.readLineInto(&line))
    {
        std::count << "Line "<< interationCount << ": " << line << "\n";
        interationCount++;
    }
}

И выдает ожидаемый результат:

Line 0: 1
Line 1: 2
Line 2: 3
...
Line 34: 35

Дополнительная информация

Эта ошибка может показаться очевидной.Конечно, повторное конструирование объекта внутри цикла - плохая практика (как с точки зрения производительности, так и из-за ошибок, подобных этой), но в некоторых архитектурах это может быть не так очевидно.

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

class FileFormat_Parrent
{
   public:
       QFile File;
       void* Buffer

   virtual bool ReadSingle() = 0;
   virtual bool WriteSingle() = 0;
};

class FileFormat_Txt : public FileFormat_Parrent
{
   virtual bool ReadSingle() {/*Possibly using QTextStream to do so*/}
   virtual bool WriteSingle() {...}
};

class FileFormat_BinArray : public FileFormat_Parrent
{
   ...
};

Затем при использовании этих классов будет создан класс FileFormat в соответствующем дочернем типе в зависимости от типа файла.

Эти созданные форматы файлов будут затем использоваться в цикле, повторяющемся между ReadSingle() и WriteSingle() до тех пор, пока один из них не вернет false.

Это приведет к появлению кода ошибки, поскольку QTextStream многократно создается внутри цикла.

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