使用 Qt,如何检查 stdin 是否为空?

With Qt, how to check if stdin is empty?

我有一个像这样处理标准输入数据的 Qt 程序:

QTextStream qtin(stdin);
QString stdindata = qtin.readAll();
QByteArray ba;
ba = stdindata.toUtf8();
QJsonDocument exJSONDoc(QJsonDocument::fromJson(ba));
QJsonObject extRoot;
extRoot = exJSONDoc.object();
QStringList keys;
keys = extRoot.keys();
for (int n=0; n <= keys.count()-1; n++)
{
    qDebug() << extRoot.value(keys[n]).toString();
}

当我这样调用我的程序时它起作用了:

myprogram < ./data.json

但是如果我调用它时没有任何“<”,它就会挂在 qtin.readAll() 中。

如果标准输入为空,我如何检查 Qt?

(我假设 Linux - 或至少 POSIX- 操作系统)

QTextStream qtin(stdin);
QString stdindata = qtin.readAll();

这将读取 stdin 直到到达文件末尾。因此可以使用像

这样的重定向输入
myprogram < ./data.json

But if I call it without any "<" it hangs ...

但是(也就是说,如果你单独 运行 myprogramstdin not 是空的。它与您的 shell 的标准输入相同。并且您的程序作为前台作业,正在等待您正在键入的终端上的输入(另请参阅 tty(4)). Try (in that case) typing some input on the terminal (which you could end with Ctrl D to make an end-of-file condition). Read about job control and the tty demystified and see also termios(3).

也许您可以通过例如isatty(3) on STDIN_FILENO. But that won't detect a pipe(7) 喜欢

tail -55 somefile | myprogram

您需要定义什么是空标准输入。我不知道这对你意味着什么,我会考虑 myprogram < /dev/null(参见 null(4))作为获得空标准输入的方式。

也许你应该设计 myprogram 这样一些程序 选项(可能 --ignore-stdin)避免从标准输入读取任何数据。

这里的问题是readAll。见 documentation:

Reads the entire content of the stream, and returns it as a QString. Avoid this function when working on large files, as it will consume a significant amount of memory.

所以它读取 stdin 直到它遇到文件结尾,因为 stdin 与控制台相关联,所以你必须发出文件结尾信号。通常是Ctrl-D然后回车。

你更有可能逐行阅读stdin。 为了允许用户文本编辑控制台仅将数据逐行传输到应用程序的标准输入。这是很久以前的设计,当时计算机只有打印机作为用户界面(没有屏幕)。


现在的问题是如何在没有文件结束信息的情况下读取 JSon 表单 stdin 与控制台连接的控制台?

我会使用一些 SAX 解析器,但这对您来说太复杂了。 那么还有另一种检测JSon结束的方法吗?

你可以试试这个方法(这是基本思路,不是最终解决方案,所以它有两个缺点):

QFile file(stdin);
QByteArray data = file.peak(largeNumber);
QJsonParseError error;
QJSonDocument doc = QJSonDocument::fromJson(data, &error);
while (!doc.isValid() && JSonNotTerminatedError(error.error))
{
    // TODO: wait for new data - it would be best to use readyRead signal
    doc = QJSonDocument::fromJson(data, &error);
}

其中 JSonNotTerminatedError returns 对于与未终止的 JSon 数据相关的各个 QJsonParseError::ParseError values 为真(请参阅链接文档)。

现在我看到 QFile 没有必需的构造函数,但主要概念应该很清楚。从 stdin 读取数据并检查它是否是有效的 JSon 文档。