我有一个可以调用的qt-app:
cat bla.bin | myapp
在Win,Mac和Linux上读取整个输入(stdin)到QByteArray的最简单方法是什么?
我厌倦了几件事,但似乎没有一件事(在Windows上):
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QByteArray content;
//---Test 1: hangs forever, reads 0
while(!std::cin.eof()) {
char arr[1024];
int s = std::cin.readsome(arr,sizeof(arr));
content.append(arr,s);
}
//---Test 2: Runs into timeout
QFile in;
if(!in.open(stdin,QFile::ReadOnly|QFile::Unbuffered)) {
qDebug() << in.errorString();
}
while (in.waitForReadyRead(1000)) {
content+=in.readAll();
}
in.close();
return app.exec();
}
我遇到事件循环问题还是不应该没有?
答案 0 :(得分:2)
实际从stdin
阅读的主要问题源于使用readsome
。 readsome
通常不用于读取文件(包括stdin)。 Readsome
通常用于异步源上的二进制数据。从技术上讲,eof
未设置readsome
。 read
在这方面有所不同,因为它会相应地设置eof
。有一个可能感兴趣的SO问题/答案here。如果您支持Linux和Windows并阅读stdin,则必须注意在Windows上stdin
未以二进制模式打开(stdout
也不是)。在Windows上,您必须在_setmode
上使用stdin
。一种方法是#ifdef
使用Q_OS_WIN32
。使用QFile无法解决此问题。
在您尝试创建它的代码中,您似乎对实际拥有事件循环感兴趣。您仍然可以在没有事件循环的情况下使用QByteArray等QT对象。在您的代码中,您从stdin(cin
)读取数据,然后执行return app.exec();
,将您的控制台应用程序置于循环中等待事件。您没有在app.exec();
之前向QT事件队列添加任何事件,因此您唯一能做的就是使用control-c结束您的应用程序。如果不需要事件循环那么这样的代码就足够了:
#include <QCoreApplication>
#include <iostream>
#ifdef Q_OS_WIN32
#include <fcntl.h>
#include <io.h>
#endif
int main()
{
QByteArray content;
#ifdef Q_OS_WIN32
_setmode(_fileno(stdin), _O_BINARY);
#endif
while(!std::cin.eof()) {
char arr[1024];
std::cin.read(arr,sizeof(arr));
int s = std::cin.gcount();
content.append(arr,s);
}
}
注意我们如何使用QByteArray
但没有QCoreApplication app(argc, argv);
并且调用app.exec();