可靠地计算磁盘已满时 fwrite 写入的字节数
Reliably counting bytes written by fwrite when disk is full
有谁知道一种可靠的方法来计算实际有多少字节
是否已使用 C 标准 I/O (fwrite
) 在磁盘已满的情况下编写?
我在让它工作时遇到了很多麻烦。问题似乎是
fwrite
被缓冲,有时它认为它已经写了
比设备实际接受的字节多。
使用与设备块大小相同的小缓冲区,fwrite
将
报告它已经写入了一个完整的缓冲区,而实际上并没有,所以
count 最终比正确的多了一个块。我修好了
测试错误,只有在没有错误的情况下才添加到总数中。
但是,如果缓冲区更大,fwrite
会写入部分缓冲区,
我不会算那个。所以我检查了部分写入,添加
并跳出循环。结束了以下程序
(减少到 MCVE):
#include <stdio.h>
#include <string.h>
//#define BUF_SIZE 4096
#define BUF_SIZE 8192
//#define BUF_SIZE 16384
int main(void)
{
unsigned long long ct = 0;
size_t written;
unsigned char *buf;
buf = malloc(BUF_SIZE);
memset(buf, 0xFF, BUF_SIZE);
while (1) {
written = fwrite(buf, 1, BUF_SIZE, stdout);
if (written < BUF_SIZE) {
ct += written;
break;
}
fflush(stdout);
if (ferror(stdout))
break;
ct += written;
}
fprintf(stderr, "%llu bytes written\n", ct);
return 0;
}
设备有 4k 块,还有 68k 或 72k 空闲。我试过缓冲区
4k、8k 和 16k 大小。
这该死的东西 仍然 不起作用。当有 72k 免费的时候,我
使用 8k 缓冲区,它写入 72k,然后认为它写入另一个 4k 并且
补充说。
我想我可以只使用等于块大小的缓冲区大小。
但我什至不确定这是否可靠。
有谁知道如何让它在所有情况下都能正常工作?我想它可能
最好完全绕过缓冲问题并使用 POSIX I/O
相反(open
和 write
)。
编辑:nsilent22 的建议正确并减少了
循环到两行:
setbuf(stdout, NULL);
...
while ((written = fwrite(buf, 1, BUF_SIZE, stdout)) > 0)
ct += written;
I’m thinking it might be best to just bypass the buffering issue entirely and use POSIX I/O instead (open
and write
).
你有办法!缓冲确实妨碍了你。 fread
returns 正确写入流的元素数,但部分流可能尚未刷新,如果设备已满,fflush()
随后可能会失败。没有可移植的方法来找出有多少字节没有被刷新。
您可以 fclose()
文件,重新打开它(以二进制模式)并搜索到最后找出答案,但使用低级别会更简单 Posix I/O首先。
将流缓冲设置为无缓冲应该可行,但如果文件很大,可能会导致性能显着下降。
您确实要写入大量数据以尝试覆盖硬盘。很久以前我写了一个这样的实用程序......绝对使用无缓冲的 strams 并使用低级别 Posix API 和一个大缓冲区,其大小应该是 2 的幂并且你填充随机失败 OS 或可能尝试压缩或以其他方式共享您的数据块的硬件算法。任何伪随机多项式都可以,但一定要在每次写入之间更改缓冲区内容。
请注意,如果您的系统是 32 位,您可能 运行 将文件大小限制为 2G 或 4G。由于使用的文件系统,也可能存在这样的限制。您可以通过创建多个文件来解决这些问题。
考虑使用带有 NULL 参数的 setbuf
函数作为缓冲区。它将关闭流缓冲。
有谁知道一种可靠的方法来计算实际有多少字节
是否已使用 C 标准 I/O (fwrite
) 在磁盘已满的情况下编写?
我在让它工作时遇到了很多麻烦。问题似乎是
fwrite
被缓冲,有时它认为它已经写了
比设备实际接受的字节多。
使用与设备块大小相同的小缓冲区,fwrite
将
报告它已经写入了一个完整的缓冲区,而实际上并没有,所以
count 最终比正确的多了一个块。我修好了
测试错误,只有在没有错误的情况下才添加到总数中。
但是,如果缓冲区更大,fwrite
会写入部分缓冲区,
我不会算那个。所以我检查了部分写入,添加
并跳出循环。结束了以下程序
(减少到 MCVE):
#include <stdio.h>
#include <string.h>
//#define BUF_SIZE 4096
#define BUF_SIZE 8192
//#define BUF_SIZE 16384
int main(void)
{
unsigned long long ct = 0;
size_t written;
unsigned char *buf;
buf = malloc(BUF_SIZE);
memset(buf, 0xFF, BUF_SIZE);
while (1) {
written = fwrite(buf, 1, BUF_SIZE, stdout);
if (written < BUF_SIZE) {
ct += written;
break;
}
fflush(stdout);
if (ferror(stdout))
break;
ct += written;
}
fprintf(stderr, "%llu bytes written\n", ct);
return 0;
}
设备有 4k 块,还有 68k 或 72k 空闲。我试过缓冲区 4k、8k 和 16k 大小。
这该死的东西 仍然 不起作用。当有 72k 免费的时候,我 使用 8k 缓冲区,它写入 72k,然后认为它写入另一个 4k 并且 补充说。
我想我可以只使用等于块大小的缓冲区大小。 但我什至不确定这是否可靠。
有谁知道如何让它在所有情况下都能正常工作?我想它可能
最好完全绕过缓冲问题并使用 POSIX I/O
相反(open
和 write
)。
编辑:nsilent22 的建议正确并减少了 循环到两行:
setbuf(stdout, NULL);
...
while ((written = fwrite(buf, 1, BUF_SIZE, stdout)) > 0)
ct += written;
I’m thinking it might be best to just bypass the buffering issue entirely and use POSIX I/O instead (
open
andwrite
).
你有办法!缓冲确实妨碍了你。 fread
returns 正确写入流的元素数,但部分流可能尚未刷新,如果设备已满,fflush()
随后可能会失败。没有可移植的方法来找出有多少字节没有被刷新。
您可以 fclose()
文件,重新打开它(以二进制模式)并搜索到最后找出答案,但使用低级别会更简单 Posix I/O首先。
将流缓冲设置为无缓冲应该可行,但如果文件很大,可能会导致性能显着下降。
您确实要写入大量数据以尝试覆盖硬盘。很久以前我写了一个这样的实用程序......绝对使用无缓冲的 strams 并使用低级别 Posix API 和一个大缓冲区,其大小应该是 2 的幂并且你填充随机失败 OS 或可能尝试压缩或以其他方式共享您的数据块的硬件算法。任何伪随机多项式都可以,但一定要在每次写入之间更改缓冲区内容。
请注意,如果您的系统是 32 位,您可能 运行 将文件大小限制为 2G 或 4G。由于使用的文件系统,也可能存在这样的限制。您可以通过创建多个文件来解决这些问题。
考虑使用带有 NULL 参数的 setbuf
函数作为缓冲区。它将关闭流缓冲。