我需要将n
字节写入文件,我有QTemporaryFile
, 我应该如何写入这些字节?
我阅读了QIODevice::write
文档:
qint64 QIODevice::write(const char *data, qint64 maxSize( Write at 从数据到设备的最大大小数据字节数。返回数字 实际写入的字节数,如果发生错误,则为 -1。
所以看起来我需要循环来写入字节,因为没有受赠人 它写入所有字节,它可以在写入k
字节后返回控制权, 哪里k
<n
.>
我可以从TemporaryFile
创建QDataStream
,但QDataStream::writeRawData
函数具有相同的限制:
int QDataStream::writeRawData(const char *s, int len( Write len bytes 从 s 到流。返回实际写入的字节数,或 错误时为 -1。数据未编码。
所以Qt
中没有确切写入n
字节或返回错误的函数?
这是一件奇怪的事情...
一方面:
-
QFile::write
的实现是基于writeData
,QIODevice::writeData
抽象方法的文档说:重新实现此函数时,此函数在返回之前写入所有可用数据非常重要。[接下来的几句话,据我所知,这很重要,因为依赖类
QDataStream
其高级方法(不返回写入的字节数(不执行循环。所以,我们似乎也不需要骑自行车。
-
实际上,
QFileDevice::writeData
(覆盖QIODevice::writeData
(似乎调用了QFSFileEnginePrivate::writeFdFh
方法(特别是:QIODevice::write
→QFileDevice::writeData
→QFSFileEngine::write
→QFSFileEnginePrivate::nativeWrite
→QFSFileEnginePrivate::writeFdFh
(,该方法自行执行循环:if (fh) { // Buffered stdlib mode. size_t result; do { result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh); writtenBytes += result; } while (result == 0 ? errno == EINTR : writtenBytes < len); } else if (fd != -1) { // Unbuffered stdio mode. SignedIOType result; do { // calculate the chunk size // on Windows or 32-bit no-largefile Unix, we'll need to read in chunks // we limit to the size of the signed type, otherwise we could get a negative number as a result quint64 wantedBytes = quint64(len) - quint64(writtenBytes); UnsignedIOType chunkSize = std::numeric_limits<SignedIOType>::max(); if (chunkSize > wantedBytes) chunkSize = wantedBytes; result = QT_WRITE(fd, data + writtenBytes, chunkSize); } while (result > 0 && (writtenBytes += result) < len);
-
Qt中的更高级别的方法,如
QTextStream
和QDataStream
中的方法(例如,参见QTextStream::operator<<(const QString &string)
和底层方法,QDataStream::operator<<(const char *s)
和底层方法(,不会自己做循环(而是依靠QFSFileEnginePrivate::writeFdFh
中的循环(。
因此,看起来Qt并没有遵循典型的POSIX约定,例如"读取/写入少于请求不一定是错误,只需重试即可"。相反,QFile
的方法被调整为仅在出错的情况下才读取/写入少于请求的。所以通常你不应该自己骑自行车QFile::write
。
但是,另一方面,根据2018年5月"兴趣"Qt邮件列表中的一个线程"QFile::write(const QByteArray&(不写入所有数据?",在某些情况下,QFile::write
写入的少于请求的,并且围绕QFile::write
循环是有用的。至少它们在 2018 年 5 月就存在了,Alexander Golks 说他在升级到 Qt 5.6.4 后无法重现这个问题(但我不知道究竟修复/更改了什么,因为在此之前循环已经QFSFileEnginePrivate::writeFdFh
了很多年(。但对我来说,主要的震惊不是没有外部循环的QFile::write
在较旧的Qt版本中是不够的(谁知道呢,也许这是一个现在修复的Qt错误或必须通过其他方式解决的硬件/驱动程序问题(,而是直接参与Qt开发的邮件列表成员(例如Thiago Macieira(坚持a-la的立场"不要指望QFile::write
写所有东西, 骑自行车"。
结论。我不知道该说什么。我的猜测是:
- Qt的精神是"只有在出错的情况下
QIODevice::write
才会写入少于请求的,因此不需要外部循环"。这就是为什么Qt开发人员既没有为QIODevice::write
周围的外部循环提供方便的方法,也没有在QTextStream
、QDataStream
等高级类中QIODevice::write
外部循环
。 - 然而,他们不敢承诺这种方法会奏效(永远并且对所有
QIODevice
后代(。这就是为什么文件信没有提供这样的保证。(它仅对QIODevice::writeData
实施者应用义务,而不对QIODevice::write
用户应用特权。 - 我个人的选择是不在
QFile::write
周围进行外部骑行。
在没有错误但写入的字节少于n
个的情况下,您如何建议撤消某些字节的写入?特别是如果文件中已有数据(以前的writes
成功,或者因为您正在追加(。
如果没有外部操作,任何进一步尝试写入未写入所有n
字节的文件也可能失败或写入 0。浮现在脑海中的情况是可用磁盘空间耗尽。