窥视QTextStream

5

我想要查看QFile读取的QTextStream的下一个字符,以便创建高效的分词器。

然而,我没有找到任何令人满意的解决方案。

QFile f("test.txt");
f.open(QIODevice::WriteOnly);
f.write("Hello world\nHello universe\n");
f.close();

f.open(QIODevice::ReadOnly);
QTextStream s(&f);
int i = 0;
while (!s.atEnd()) {
  ++i;
  qDebug() << "Peek" << i << s.device()->peek(3);
  QString v;
  s >> v;
  qDebug() << "Word" << i << v;
}

给出以下输出:
Peek 1 "Hel" # it works only the first time
Word 1 "Hello" 
Peek 2 "" 
Word 2 "world" 
Peek 3 "" 
Word 3 "Hello" 
Peek 4 "" 
Word 4 "universe" 
Peek 5 "" 
Word 5 ""

我尝试了几种实现方式,包括使用QTextStream::pos()和QTextStream::seek()。这样做效果更好,但是pos()有缺陷(当文件太大时返回-1)。

有没有人有解决这个经常性问题的办法?提前感谢您。


s.device()->pos()s.device()->bytesAvailable()添加到日志中以检查设备读取的进度。这可能有助于定位问题。 - Marek R
在第一个QTextStream::operator>>之前:(pos = 0,bytesAvailable = 27)。在它之后直到结尾:(pos = 27,bytesAvailable = 0)。Qt的错误行为似乎确实与此有关。 - FabienRohrer
我已经检查了 QTextStream 代码。它似乎总是尽可能地缓存数据,并且没有办法禁用此行为。我原本期望它会在设备上使用 peek,但它只以贪婪的方式读取。底线是,在这种情况下无法使用 QTextStream - Marek R
是的。我也尝试过在构造函数中将QTextStream和QFile设置为无缓冲,但这也没有帮助。 - FabienRohrer
我的看法是,像QTextStream::peek(int size)这样的函数是缺失的。 - FabienRohrer
2个回答

3
你从QIODevice中使用了peek,但是你从QTextStream中读取,这就是为什么peek只能工作一次。尝试使用以下代码:
while (!s.atEnd()) {
      ++i;
      qDebug() << "Peek" << i << s.device()->peek(3);
      QByteArray v = s.device()->readLine ();
      qDebug() << "Word" << i << v;
}

很遗憾,QIODevice不支持读取单个词,所以您需要使用peek和read的组合来自己实现。


感谢您的关注。我写的例子非常简化。在我的具体例子中,我有兴趣密集使用QTextStream :: operator >>。 - FabienRohrer
问题确实在于QTextStream :: device()与QTextStream未同步。而且,QTextStream本身没有窥视函数。 - FabienRohrer
没错,但由于QIODevice没有读取单词的方法,而且pos()存在缺陷,我的建议是自己实现逐个单词读取QIODevice并使用它来代替QTextStream::operator>>。或者有什么原因必须使用这个运算符吗? - Anton Poznyakovskiy
是的,你说得完全正确。事实上,在讨论中,我选择了这个解决方案并实现了它 :-) 使用QTextStream编写简单而好看的代码非常方便。遗憾的是,这个类中没有peek函数,破坏了使用这个类编写真正的标记器的可能性(在解析模棱两可的语言时需要peek)。 - FabienRohrer
1
如果我没记错的话,QTextStream 要么成功读取要么不做任何改变。因此,尝试读取一个数字并失败后,可以尝试读取一个单词也没问题。@FabienRohrer - Kuba hasn't forgotten Monica

0

尝试使用disable QTextStream::autoDetectUnicode。这可能会提前读取设备以执行检测并导致您的问题。

为了保险起见,还要设置编解码器。

添加s.device()->pos()s.device()->bytesAvailable()到日志中以进行验证。


我已经检查了QTextStream code。看起来它总是尽可能地缓存数据,并且没有办法禁用此行为。我期望它将在设备上使用peek,但它只以贪婪的方式读取。底线是您不能同时使用QTextStream和peak device。


我尝试了所有QTextStream :: setAutoDetectUnicode(bool)与或没有QTextStream :: setCodec("UTF-8")的组合,问题仍然存在。 - FabienRohrer

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