我需要将 n
字节写入文件,并且我有 QTemporaryFile
,
我应该如何写这些字节?
我阅读了QIODevice::write
文档:
qint64 QIODevice::write(const char *data, qint64 maxSize) Writes at most maxSize bytes of data from data to the device. Returns the number of bytes that were actually written, or -1 if an error occurred.
所以看起来我需要循环来写字节,因为没有被授予者
它写入所有字节,它可能会在写入 k
字节后返回控制权,
其中 k
<n
。
我可以从TemporaryFile
创建QDataStream
,但是QDataStream::writeRawData
函数有同样的限制:
int QDataStream::writeRawData(const char *s, int len) Writes len bytes from s to the stream. Returns the number of bytes actually written, or -1 on error. The data is not encoded.
所以 Qt
中没有函数可以准确地写入 n
字节或返回错误?
最佳答案
这是一件奇怪的事情......
一方面:
QFile::write
的实现基于writeData
, 和 documentation for theQIODevice::writeData
abstract method说:When reimplementing this function it is important that this function writes all the data available before returning. [The next few sentences, as far as I understand them, tell that that's important, because the relying class
QDataStream
in its high-level methods (which don't return a number of bytes written) don't do the cycling.]所以,看来我们也不需要骑自行车了。
真的,
QFileDevice::writeData
(覆盖QIODevice::writeData
)似乎调用QFSFileEnginePrivate::writeFdFh
方法(具体为:QIODevice::write
→QFileDevice::writeData
→QFSFileEngine::write
→QFSFileEnginePrivate::nativeWrite
→QFSFileEnginePrivate::writeFdFh
),其中does the cycling by itself :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)
and the underlying methods 、QDataStream::operator<<(const char *s)
and the underlying methods ),不要自己骑自行车(而是依靠QFSFileEnginePrivate::writeFdFh
中的自行车)。
因此,看起来 Qt 不遵循典型的 POSIX 约定 a-la“读/写少于请求不一定是错误,只需重试”。相反 QFile
的方法被调整为只在错误的情况下读取/写入少于请求。所以通常你不应该在 QFile::write
附近骑自行车自己。
但是,另一方面,根据线程“QFile::write(const QByteArray&) 不写入所有数据?”在“兴趣”Qt 邮件列表中 May 2018 , 存在以下情况 QFile::write
写的比请求的少,并且围绕 QFile::write
循环很有用。至少它们存在于 2018 年 5 月,Alexander Golks said he couldn't reproduce the problem after upgrading to Qt 5.6.4 (但我不知道到底是什么被修复/改变了,因为在那之前的很多年里,自行车都是QFSFileEnginePrivate::writeFdFh
)。但令我震惊的不是QFile::write
。没有外部循环在一个较旧的 Qt 版本中是不够的(谁知道,也许这是一个已修复的 Qt 错误或必须通过其他方式解决的硬件/驱动程序问题)但是直接接受的邮件列表成员参与 Qt 开发(例如 Thiago Macieira)的立场是 a-la “不要指望 QFile::write
写一切,骑自行车”。
结论。我不知道该说些什么。我的猜测是:
- Qt 的精神是“
QIODevice::write
只有在出现错误的情况下才会写入少于请求的内容,因此不需要外部循环”。这就是为什么 Qt 开发人员既不提供围绕QIODevice::write
进行外部循环的便捷方法的原因。外部循环也不围绕QIODevice::write
他们自己在更高级别的类(class)中,例如QTextStream
,QDataStream
. - 但是他们不敢保证这种方法会奏效(总是对所有
QIODevice
后代)。这就是文档的字母 不提供此类保证的原因。 (它仅对QIODevice::writeData
实现者施加义务,但对QIODevice::write
用户不施加特权。) - 我个人的选择是不围绕
QFile::write
进行外部循环.
关于c++ - 使用 QFile::write 的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51170486/