将整个文件读入到QString中

31

我想读取文件夹中的所有文件,通过 entryList() 将它们存储在 fileList 中,然后对于该文件夹中的每个文件,打开并将其内容读入到 QString 中。我认为这应该很容易,但我无法弄清楚我做错了什么。现在我得到的错误是:

no matching function for call to 'QTextStream::QTextStream(QFile*, QIODevice::OpenModeFlag)'

我知道这与我声明 QTextStream 的方式有关,但问题在于我找到的示例似乎都这样做,那么我为什么不能呢?

此外,我注意到如果我添加测试以检查文件打开是否成功,我会收到“拒绝访问”的警告,即使我只是在读取。虽然我可以读取文件夹的内容,并使用这些文件填充 QListWidget 没有任何问题。

这些是 *.JSON 文件不应该有影响,对吗?

我已经看过这里这里这里 的示例,但无法弄清楚我做错了什么。感谢任何帮助。

这是我的代码:

foreach(QString fileName, fileList){

    QFile file(fileName);
    file.open(QIODevice::ReadOnly);
    QString s;

    QTextStream s1(&file, QIODevice::ReadOnly);
    s.append(s1.readAll());

    qDebug() << "string content:" << s; // empty!!!

}

更新 根据cmannett85的建议进行修改后,我不再遇到错误,但出于某些原因,最终字符串s仍为空。 关于文件夹中的读/写权限,我现在注意到如果我测试

if(!file.open(QIODevice::ReadWrite))
        {
            QMessageBox::information(0,"error",file.errorString());
        }

当我运行循环时,出现了两个警告 - 我怀疑是由 ... 引起的。以前会产生32个警告,但是文件夹里只有30个文件。

无论如何,我试图读取的文件是 *.JSON 文件,并且根据 Windows 7 中的属性对话框,它们既不是只读也不是隐藏。我可以在相同的文件夹中使用相同的程序编写文件。

有一件事让我想知道是否可能是原因:文件名在扩展名之前包含.,即ID.file.16.json

更新2 这与文件名中有.无关。测试了不同的文件,结果是一样的。

此外,这两个警告确实与...有关。使用QDir::Filters解决了这个问题。然而,有趣的是,如果应用QDir::Files过滤器,一切都很好;但是如果使用QDir::NoDotAndDotDot过滤器,则根本无法检测到任何文件,这与Qt助手的说明相反,后者说只有这两个元素在使用此过滤器时被忽略。

更新3

遵循ddriver的建议,但仍然无法工作。包括检索文件夹中的文件在内的当前代码如下:

QDir assetsFolder = QDir("C:/Users/THB7OI/Desktop/app/qt-book/chap08/items");

QStringList files = assetsFolder.entryList(QDir::Files);

    // for each file in the folder,
    foreach (QString file, files) {
        QFile f(file);
        if (!f.open(QFile::ReadOnly | QFile::Text)) break;
        QTextStream in(&f);
        qDebug() << f.size() << in.readAll();

        f.close();

    }

你有包含#include <QTextStream>吗? - Andreas Fester
1
“access denied”在Open()中不是警告,而是错误。文件夹读取权限与文件读取权限不同。如果您的打开操作真的失败了,那么它会立即停止。文件IO不是忽略返回值的地方。 - darron
@darron 但是我使用了另一个我创建的程序来“写入”现在正在尝试读取的文件,这还有可能吗? - Joum
@ddriver 谢谢,但我认为问题出在其他地方。最终字符串为空,并且 file.size() 返回0... 你有什么想法吗? - Joum
@Joum - 请查看我的回答以获取更多信息。 - dtech
显示剩余3条评论
4个回答

42

如所指出,QTextStream 没有这样的构造函数。

我快速地输入了这几行代码以验证它确实正常工作:

foreach (QString file, files) {
    QFile f(file);
    if (!f.open(QFile::ReadOnly | QFile::Text)) break;
    QTextStream in(&f);
    qDebug() << f.size() << in.readAll();
}

我得到了预期的输出-每个文件的大小和内容。尝试使用该代码检查您是否输错了什么。

此时,我相当确定问题出在您的fileList上-您没有检查QFile ::open()是否成功并继续进行。具有讽刺意味的是,如果open()失败并且您的代码继续运行,您将获得文件大小的精确值为0,而readAll()的结果将完全为空字符串。因此,问题在于您的文件名。下次请检查open()是否成功-不这样做是非常不好的实践。

您的文件无法打开的另一个可能的原因是它们被其他进程打开以供写入。重新启动系统并直接运行代码以确保文件访问未被锁定。

如果这也没有帮助,请前往Qt项目网站发布问题,并在必要时提交错误报告。


在 qDebug 中,对于文件夹中的每个文件,我都会得到一个 0 "",所以这也没有起作用。我在启动计算机后立即看到了您的答案并尝试了它。我觉得这是一个错误很奇怪,因为这是一个相当标准的操作,我相信其他人也已经成功地完成了这个操作... - Joum
@Joum 0 "" 可能意味着代码没有找到文件。请确保文件 file 存在。例如:创建一个带有一些文本的文件 /tmp/test.txt,然后使用 QFile f("/tmp/test.txt"),它应该可以工作。如果你仍然得到 0 "" 的结果,那么就意味着文件是空的,或者其他原因导致无法读取文件。(我刚刚也遇到了和你一样的结果,但是它是由于文件名中的拼写错误造成的 :-) 希望这可以帮助你!) - Wim
@Wim,老兄,这个答案已经被标记为正确答案3年了... 真是什么鬼? - Joum
@Joum 抱歉又翻出老帖子了 :-) 我在寻找类似问题的解决方案时,遇到了你在评论中提到的同样问题。以防将来有人遇到这个问题,我希望他们能通过这种方式找到解决方案。但你是对的,我不应该把它个人化,我道歉了。 - Wim
这对我也有效,但如果文件太大,你的内存会受到影响。 - Jorge Luis

5
你提供的示例中没有按照正确方式创建 QTextStream。QTextStream::QTextStream(QFile*,QIODevice::OpenModeFlag) 不存在,请使用 QTextStream s1(&file),因为你已经在 QFile 中设置了打开模式。
另外,我注意到如果我添加了检查文件是否打开成功的测试,即使我只是进行读取操作,也会收到“访问被拒绝”的警告。虽然我可以读取文件夹内容,甚至将这些文件填充到 QListWidget 中,但并不意味着你可以读取文件内容。如果你具有读取权限并且它们是纯文本文件,则应该能够在文本编辑器中打开它们。你能试试吗?

1
+1 - 注意 QTextStream::QTextStream(File*, QIODevice::OpenModeFlag)(使用普通的 File 指针)确实存在,这可能是混淆的原因。 - Andreas Fester
你的建议已经成功消除了错误,但变量 s 仍然是空的... 有什么想法吗?这些文件不仅可以在文本编辑器中打开/编辑/保存,我的程序的另一部分还创建了我现在正在尝试读取的文件... - Joum
1
@Joum 当打开 QFile 时,你应该使用 QIODevice::TextQIODevice::ReadOnly。另外,尝试调用 file.size() 来查看 Qt 是否认为其中有任何数据。 - cmannett85
在我将其传递给QTextStream之前立即处理。 - Joum
@Joum 有没有可能文件已经在其他地方打开了? - cmannett85
显示剩余4条评论

2

从你的例子中无法工作,因为你获取的是文件列表(文件名),而不是带路径的文件;

QStringList filters;
filters << "*.json";

QDir assetsFolder = QDir("C:/Users/THB7OI/Desktop/app/qt-book/chap08/items");
assetsFolder.setNameFilters(filters);
assetsFolder.setFilter(QDir::Files);

QFileInfoList files = assetsFolder.entryInfoList();
foreach (QFileInfo fi, files) {

    QFile file(fi.absoluteFilePath());

    if (!f.open(QFile::ReadOnly | QFile::Text)) continue;

    QTextStream in(&f);

    qDebug() << "string content:" << in.readAll(); // will not be empty!!!
}

1
在一个非常头疼的情况下,我发现一个非常基本和简单的错误导致了这个问题——应用程序路径。
在我添加到问题部分的最后一段代码中,我添加了:
assetsFolder.setCurrent("C:/Users/THB7OI/Desktop/app/qt-book/chap08/items");

foreach循环之前,一切都正常工作。

尽管这最终成为了确定的答案,是由最先回复的人的贡献得出的,但这不是我最初提出的问题,因此我+1了其他两个答案,因为它们特别回答了我最初提出的问题。

另外,由于ddriver的答案特别针对fileList问题,并让我考虑应用程序路径,所以我将其标记为正确答案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接