Piszę aplikację, w której dzwonię do metody QFile::size() wiele razy. Działa we wszystkich oprócz miejsca. Pokażę to miejsce i taki, który działa na porównania.

, który nie działa:

while(!in.atEnd())
{
    if (fileOut.size() != 0) //This "if" isn't executed. (if I change != to == it always returns 0)
    {
      out<<endl;
      qDebug() << "Size of fileOut: " << fileOut.size(); 
    }

    QString temp;
    temp = in.readLine();
    out<<temp;
}

, który działa:

if(fileOut.size() != 0) 
{
  out<<endl;
}

QString temp = in.readLine();
out<<temp<<endl;

temp = in.readLine();
out<<temp;

while(temp[temp.length()-1] != ']')
{
    temp = in.readLine();
    out<<temp;
}

Szukałem rozwiązania, ale próbowałem wszystkich tych sposobów na rozwiązanie tego.

Edytuj / Rozwiązany: Ze względu na przejrzystość wszystko obraca się wokół bufora, jednak po niewielkiej analizie dokumentacji, mogę wyjaśnić, dlaczego tylko ten element kodu nie zwrócił prawidłowej wartości QFile::size() i nie wszystko (żadne z nich nie dotarł do rozmiaru, w którym bufor zostanie automatycznie zwolniony do danych). We wszystkich tych miejscach, endl został użyty i jako dokumentacja mówi: pisze "n" do strumienia i spłukuje strumieniem. , więc teraz wszystko jest jasne . We wszystkich innych miejscach nazywa się metoda flush(), ale nie wiedziałem o tym. Taka krótka korekta. Problem jest rozwiązany, wszystko, co musisz zrobić, to zadzwoń do spłukiwania ().

1
Michał 3 czerwiec 2018, 20:46

3 odpowiedzi

Najlepsza odpowiedź

Zakładam, że używasz niektórych streamerów, aby napisać plik. Problem polega na tym, że strumieniowo buforuje dane, nie napisano natychmiast do pliku (zwykle czeka, aż bufor dotrze do pewnego rozmiaru, aby go napisać).

QFile::pos może nie odzwierciedlać prawidłowego rozmiaru ani Ponieważ nie uwzględnia danych w buforze, ale nie przepłukany do pliku.

Jeśli ty {x0}} Twój streamer będziesz miał Prawidłowa pozycja rozmiaru i kursora:

#include <qdebug.h>
#include <qfile.h>
#include <qtextstream.h>

int main(int argc, char* argv[])
{
  QFile f("example.txt");
  qDebug() << "f.size() before opening =" << f.size(); // correct

  if (!f.open(QFile::WriteOnly)) {
    qDebug() << "Error: not opened!";
    return 1;
  }    

  QTextStream out(&f);
  qDebug() << "f.size() before writing =" << f.size(); // 0: file was overwritten

  out << "Hello world!\n";
  qDebug() << "f.size() after writing =" << f.size(); // may be incorrect
  qDebug() << "f.pos() after writing =" << f.pos(); // may be incorrect

  out.flush();
  qDebug() << "f.size() after flushing =" << f.size(); // correct

  f.close();
  qDebug() << "f.size() after closing =" << f.size(); // correct

  return 0;
}

Następny przykład pokazuje jeszcze gorszą sytuację, gdy możesz mieć rozmiar niezerowy, ale to nie odzwierciedla poprawnego:

#include <qdebug.h>
#include <qfile.h>
#include <qtextstream.h>

int main(int argc, char* argv[])
{
  QFile f("example.txt");

  if (!f.open(QFile::WriteOnly)) return 1;

  QTextStream out(&f);

  for (int i = 0; i < 10000; ++i) { // 10000 works for me, may be you have to increase it to see the partial write
    out << "Hello world!\n";
  }
  qDebug() << "f.size() after writing =" << f.size(); // may be incorrect
  qDebug() << "f.pos() after writing =" << f.pos(); // may be incorrect

  out.flush();
  qDebug() << "f.size() after flushing =" << f.size(); // correct

  f.close();

  return 0;
}

Wynika to z powyższego faktu: bufor został przepłukany w pewnym momencie, ale istnieje kilka danych, które należy napisać.

Ponownie, aby mieć pewność, przepłukać strumień przed sprawdzeniem rozmiaru.


Aktualizacja: Kod dostępny w https://github.com/cbuchart/stackoverflow/blob/master/50669271-qt-qfilesize-always-Returns-0/main.cpp

3
cbuchart 19 lipiec 2018, 21:59

Nie jest przenośny, aby założyć, że rozmiar pliku jest poprawny na otwartych plikach, które zostały zmodyfikowane po otwarciu. Nawet jeśli możesz "dostać go do pracy", nadal jest to złe rzeczy do zrobienia. Po otwarciu pliku możesz sprawdzić, jak duży jest, a następnie twój własny kod musi śledzić, jak zmienił rozmiar. Możesz oczywiście zrobić Patch QT, aby wykonać to śledzenie dla Ciebie, ale działało tylko tak długo, jak można uzyskać dostęp do pliku za pomocą QFileDevice (I. QFile lub QSaveFile).

2
Reinstate Monica 4 czerwiec 2018, 16:42

W moim przypadku problem był w flagi. QIODevice::readOnly nie zawsze zwrócił prawidłowy rozmiar (zawsze 0). Zmiana do QIODevice::readOnly rozwiązała problem.

1
Derek C. 17 maj 2020, 04:17