接上篇FILE的相关函数,继续看。
1.setbuf
void setbuf ( FILE * stream, char * buffer );
stream 文件流指针
buffer 将此buffer设置为stream的缓冲区,如果是NULL的话,表示不需要缓冲区,一有内容就写入硬盘
注意:在任何读写操作(fread, fwrite)之前就要设置要缓冲
1.1示例:
#include "stdafx.h"
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
char newbuffer[1000] = {'\0'};
FILE *fileForNewBuf = fopen("test.txt","w"); //示例就不检查fileForNewBuf是否为空了
setbuf(fileForNewBuf, newbuffer);
const char *str = "some test srings in buffer";
fwrite(str, 1, strlen(str), fileForNewBuf); // 缓冲区没满,这里没写入硬盘
fclose(fileForNewBuf); //这里面fflush了,写入硬盘
return 0;
}
1.2示例:
测试无缓冲情况
#include "stdafx.h"
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
FILE *noBufferFile = fopen("test.txt","w");
setbuf(noBufferFile, NULL); //无缓冲,有内容即马上写入硬盘
fwrite("a", 1, 1, noBufferFile);//这里已经写入硬盘
fclose(noBufferFile);
return 0;
}
函数的描述:
这里可以看到有一个最小缓冲长度,进去看可以发现是
(我的机子上,VS2012)
也就是说即便我们设置了char buf[10] 这样短的缓冲区,还是会被强制改成大小是512的,大于512的话就是实际设置的长度。这里面还说了stdin和stdout一般都是全缓冲或者行缓冲或者无缓冲,以来于系统的实现,不过一般都是行缓冲。stderr一般是行缓冲或者无缓冲。
“全缓冲”: 设置的缓冲区满了才往硬盘写。
“行缓冲”: 遇到换行(或缓冲区满)才往硬盘写。
“无缓冲”: 只要有字马上写入硬盘。
关于如何设置缓冲模式,看下一个函数。
2.setvbuf
int setvbuf ( FILE * stream, char * buffer, int mode, size_t size );
stream文件流指针
buffer缓冲区
mode缓冲模式
三种缓冲分别对应了之前说的情况
size 缓冲区大小,如果buffer是null,则由系统动态申请
返回值 : 成功返回0,不成功非0
2.1 全缓冲示例:
#include "stdafx.h"
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
char fullBuf[566] = {};
FILE *file = fopen("test.txt","w");
setvbuf(file,fullBuf, _IOFBF, 566); //写满566个字符才送入硬盘
for (int i = 0; i < 566; ++i)
{
fwrite("a", 1, 1, file);
}
fwrite("b", 1, 1, file); //这一句把566个a送入硬盘中,缓冲区刷新,第一个字符成了b
fclose(file);
return 0;
}
2.2 行缓冲示例:
#include "stdafx.h"
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
char lineBuffer[1024] = {};
FILE *file = fopen("test.txt","w");
int ret = setvbuf(file, lineBuffer, _IOLBF, 1024);
const char *str = "test line buffer";
fwrite(str, 1, strlen(str), file); //这里还没写入硬盘
fwrite("\n", 1, 1, file); //这里写入 , 但我在win7+vs2012上没有写进去,查了半天在MSDN才找到解释,起初还以为自己写错了,解释在下方截图
fclose(file);
return 0;
}
WIN32下面没有行缓冲一说,只有全缓冲,好操蛋,害我找半天原因。
2.3无缓冲示例:
#include "stdafx.h"
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
char lineBuffer[1024] = {};
FILE *file = fopen("test.txt","w");
int ret = setvbuf(file, lineBuffer, _IONBF, 1024);
const char *str = "test no buffer";
fwrite("a", 1, 1, file); //这里写一个字都会输出到硬盘去
fwrite(str, 1, strlen(str), file); //这句话也马上输出到硬盘
fclose(file);
return 0;
}
到这里,基本的文件输入输出也差不多了,一般带个’f’的(fprintf,fputs,fgets….)就表示对文件进行操作,省略了’f’的(printf, puts,….)一般是绑定在stdout,stdin,stderr这三个系统初始就有的流上面,带个’v’的(vprintf,vscanf,….)表示接受一个va_list 的参数(我没怎么用过)。
小结:
文件的本质上是一块内存(缓冲区)加一个管理对象(FILE结构体内的各个成员),stdout,stdin,stderr本质上也是文件。我们可以改变它们的缓冲方式,缓冲区大小,可以格式化输出。但是究其根本也只是个库,和C语言本身并无关系,在不同的平台下有各自不同的实现。就像_IOLBF在WIN7上根本就是不提供的,还害我查半天的错,囧。文件再深入本质一点就是内存地址,也就是说我们和底层硬件进行沟通,其实都是通过地址以及偏移来操作的。其实我觉得自己还是需要去学一点汇编的知识,更好地理解内存。
好啦,下一篇开始指针。