笔记:
/*
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
当flags包含O_CREAT时,需要加参数mode。其他情况不用mode参数,加了也被忽略。
ssize_t read(int fd, void *buf, size_t count);
从fd中读取count大小的字节内容到buf中。返回读到的长度,出错返回-1。返回值可能比count小,这不被认为时错误,原因可能是文件本来就没有那么多东西读(已到达文件末尾,或者从pipe或terminal读),也可能是被信号打断了。
ssize_t write(int fd, const void *buf, size_t count);
从buf中写count大小的字节内容到fd。返回写入的长度(0表示没写进去任何东西),出错返回-1。实际写入字节数可能比count小,这不算错误,原因可能是因为磁盘中没有更多空间让你写了,或者文件大小已超过RLIMIT_FSIZE限制,或者写的过程中被信号打断了。
在写的过程中要注意文件是否被lseek了或文件是否有O_APPEND标记。
O_CREAT需要读写buffer对齐。
O_RDONLY, O_WRONLY, O_RDWR的值分别为0,1,2,因此,O_RDONLY|O_WRONLY和O_RDWR不一样哦。
open()可以创建设备文件,但creat()不行,可以用mknod。
O_NONBLOCK通常只用在你想打开文件但不想去读写,例如打开设备文件只进行ioctl操作。
用FILE指针打开和读写文件:
#include <stdio.h>
FILE *fopen(const char *path, const char *mode);
其中mode可以取:
r 读方式打开,文件pos在文件开头。
r+ 读写方式打开,文件pos在文件开头。
w 写方式打开,将文件truncate到0,如果文件不存在则新建。文件pos在文件开头。
w+ 读写方式打开,将文件truncate到0,如果文件不存在则新建。文件pos在文件开头。
a 追加方式打开,如果文件不存在则新建。文件pos在文件末尾(EOF)。
a+ 读和追加方式打开,如果文件不存在则新建。读时文件pos在文件开头,写时pos在文件末尾(EOF)。
b 二进制方式,可加在上述mode的后面或mode组合的中间。在一些系统上,文本文件和二进制文件处理方式不同,想要读二进制就要加这个。
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb,
FILE *stream);
注意fread不会区分end-of-file和error,返回值都会小于你本要写的长度,要通过feof()和ferror()做进一步判断。
int fseek(FILE *stream, long offset, int whence);//参数同lseek。第二个参数要传long型。成功返回0.
long ftell(FILE *stream);//获得当前pos。
void rewind(FILE *stream);//把文件流的pos指向0位置。同(void) fseek(stream, 0L, SEEK_SET);
char * readline (const char *prompt);
从命令行读取一行,以字符串形式给出结果。参数prompt通常为空,其他语言没有这个参数。
readline遇到换行符或EOF就返回,出错也返回(NULL)。返回值为读到的内容的指针(换行符被跳过,不返回)。
读的buffer是内部分配的,所以用完后记得手动释放掉。
读不到换行是阻塞住不返回的。
如果一行除了EOF没有内容,函数返回NULL。
*/
示例程序:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define TEST_FILE_NAME "./ftest.txt"
int main()
{
int fd;
unsigned char rwbuf[64];
int readc, writec;
off_t curoffset;
//不加O_CREAT就不能新建
fd = open(TEST_FILE_NAME, O_RDWR|O_CREAT, S_IRWXU); //O_RDONLY, O_WRONLY, O_CREAT, O_APPEND, O_SYNC, O_CLOEXEC,O_DIRECT
if (fd == -1)
{
perror("open file failed");
return 1;
}
#if 1
memset(rwbuf, 0, 64);
readc = read(fd, rwbuf, 64);
printf("%d, %s\n", readc, rwbuf); //不会因为'\0'或'\r''\n'停下来,并且它们也算一字节长度。
//offset指向已经读的下一个字节
curoffset = lseek(fd, 0, SEEK_CUR); //SEEK_SET, SEEK_END, SEEK_DATA, SEEK_HOLE
printf("offset = %d\n", curoffset);
lseek(fd, 12, SEEK_SET); //lseek64?
writec = write(fd, "zhenfg", 6);
#else
memset(rwbuf, 0, 64);
readc = read(fd, rwbuf, 64);
int i;
for (i = 0; i < readc; i++) //可以读取二进制文件。不像fopen还要加"b"模式
{
printf("%02x ", rwbuf[i]);
}
printf("\n");
#endif
close(fd);
return 0;
}
读写文件时的判断示例:
#if 0
raw发包:
while (send_left > 0/* && try_time--*/)
{
sent_bytes = send(sockfd, bufp, send_left, flags);
if (0 > sent_bytes)
{
if (errno == EAGAIN || errno == EINTR)
{
continue;
}
else
{
return -1;
}
}
if (0 == sent_bytes)
{
continue;
}
bufp += sent_bytes;
send_left -= sent_bytes;
}
读body:
while (判断) {
...
ret = read(...);
if (ret == 0) {
return -1;
} else if (ret == -1) {
if (errno == EAGAIN) {
read_deep--;
if (read_deep <= 0)
return 0;
else
continue;
} else {
return -1;
}
}
}
#endif