文件访问
将输出流与实际文件同步
std::fflush
int fflush( std::FILE* stream ); |
对于输出流(和最近操作为输出的更新流),将来自 stream
缓冲区的未写入数据写入关联的输出设备。
对于输入流(和最近操作为输入的更新流),行为未定义。
若 stream
为空指针,则冲入所有打开的输出流,包含在库包内操作,或其他情况下程序不能直接访问的流。
参数
stream | - | 要写入的文件流 |
返回值
成功时返回零。否则返回 EOF 并设置文件流的错误指示器。
注意
POSIX 通过定义其在输入流上的效果扩展 fflush 的规定,只要该流表示文件或另一可寻位设备:该情况下重定位 POSIX 文件指针以匹配 C 流指针(等效地撤销任何读缓冲)并舍弃任何未从流回读的 std::ungetc 或 std::ungetwc 的效果。
在宽字符 I/O 和窄字符 I/O 间切换文件流
std::fwide
int fwide( std::FILE* stream, int mode ); |
若 mode > 0
,则试图令 stream
为宽面向。若 mode < 0
,则试图令 stream
为字节面向。若 mode==0 ,则只查询流的当前面向。
若流的当前面向已决定(通过执行输出或通过之前调用 fwide ),则此函数不做任何事。
参数
stream | - | 指向要修改或查询的 C I/O 流的指针 |
mode | - | 大于零的整数值设置流为宽,小于零者设置流为窄,零值仅查询 |
返回值
若此调用后流为宽面向则为大于零的整数,若此调用后流为字节面向则为小于零的整数,若流无面向则为零。
为文件流设置缓冲区
std::setbuf
void setbuf( std::FILE* stream, char* buffer ); |
为 C 流 stream
上进行的 I/O 操作设置内部缓冲区。
若 buffer
非空,则等价于 std::setvbuf(stream, buffer, _IOFBF, BUFSIZ) 。
若 buffer
为空,则等价于 std::setvbuf(stream, NULL, _IONBF, 0) ,这会关闭缓冲。
参数
stream | - | 要设置缓冲区的文件流 |
buffer | - | 指向文件流所用的缓冲区的指针。若提供 NULL ,则关闭缓冲。若它非空,则数组必须足以保有至少 BUFSIZ 个字符 |
返回值
(无)
注意
若 BUFSIZ 不是适合的缓冲区大小,则能用 std::setvbuf 更改它。
std::setvbuf 亦应当用于检测错误,因为 std::setbuf
不指示成功或失败。
此函数仅可在已将 stream
关联到打开的文件后,但要在任何其他操作(除了对 std::setbuf/std::setvbuf
的失败调用)前使用。
一个常见错误是设置 stdin 或 stdout 的缓冲区为生存期在程序终止前结束的数组:
为文件流设置缓冲区与其大小
std::setvbuf
int setvbuf( std::FILE* stream, char* buffer, int mode, std::size_t size ); |
以 mode
所指示值更改给定文件流 stream
的缓冲模式。另外,
- 若
buffer
为空指针,则重设内部缓冲区大小为size
。 - 若
buffer
不是空指针,则指示流使用始于buffer
而大小为size
的用户提供缓冲区。必须在buffer
所指向的数组的生存期结束前(用 fclose )关闭流。成功调用setvbuf
后,数组内容不确定,而任何使用它的尝试是未定义行为。
参数
stream | - | 要设置缓冲的文件流 | ||||||
buffer | - | 指向要使用的流缓冲区的指针,或若仅更改大小和模式则为空指针 | ||||||
mode | - | 使用的缓冲模式。它能是下列值之一:
| ||||||
size | - | 缓冲区的大小 |
返回值
成功时为 0 ,失败时为非零。
注意
此函数仅可在已将 stream
关联到打开的文件后,但要在任何其他操作(除了对 std::setbuf/std::setvbuf
的失败调用)前使用。
不是所有 size
字节都需要用于缓冲:实际缓冲区大小通常向下取整到 2 的倍数、页面大小的倍数等。
多数实现上,行缓冲仅对终端输入流可用。
一个常见错误是设置 stdin 或 stdout 的缓冲区为生存期在程序终止前结束的数组:
调用示例
#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <sys/stat.h>
int main()
{
std::FILE* fp = std::fopen("test.txt", "r");
if (!fp)
{
std::perror("fopen");
return 1;
}
struct stat stats;
if (fstat(fileno(fp), &stats) == -1) // 仅限 POSIX
{
std::perror("fstat");
return 1;
}
std::cout << "BUFSIZ is " << BUFSIZ << ", but optimal block size is "
<< stats.st_size << '\n';
if (std::setvbuf(fp, NULL, _IOFBF, stats.st_size) != 0)
{
perror("setvbuf failed"); // POSIX 版本设置 errno
return 1;
}
int ch;
while ((ch = std::fgetc(fp)) != EOF); // 读取整个文件:用 truss/strace 观察
// 所用的 read(2) syscall
std::fclose(fp);
return 0;
}