最近在看linux C,前五章觉得跟学校里讲的没什么区别,但是一进入第六章,感觉自己什么都不知道,没办法周四自己要实现ls的命令,只好自己硬着头皮看。坚持了三天之后渐渐觉得自己入了门,对文件的操作逐渐有了感觉,也找到了感觉适合自己学习方式。现在先来分享一下自己的学习方法。
刚开始翻到文件操作这一章时候,自己被吓了一跳,什么#include<sys/stat.h>,什么#include<sys/types.h> 这些头文件 基本就没几个见过的。我想这下完了,周四还不知道能不能顺利完成任务....
之后自己就按照书上的,一个一个程序的敲,皇天不负有心人啊,基本上敲到百分之80的时候,感觉来了,看着都能看懂了(前提是敲完一个弄懂一个)。我觉得这个方法很好,计算机就要多实践,才能学会更多。
好了,现在回归正题。现在开始介绍文件的操作。
首先先列个大纲:
part one:
- 要是想对文件进行相关操作,首先要有文件。这就要用到open();或者creat();函数来创建文件。
- 文件创建好了,接着就是对文件操作啦。用到的相关函数有 read();write();函数。从函数名上就能看出这两个函数的功能。
- 这是大家就会发现,read();和wirte();函数不够自由啊,只能从文件的头行进到尾部。这时,就有用来操作一个文件读写的指针的函数——lseek();
具体介绍一下相关函数:
首先是open(),creat()函数。
#include<fcntl.h>
intopen(const char * pathname,int flags);
intopen(const char * pathname,int flags,mode_tmode);
对于open()函数,头文件跟函数原型已经列出来。现在介绍一下函数的参数分别是怎么用的。pathname就是要打开的文件的路径和文件名。flags表示文件的打开方式。打开方式有:
O_RDONLY 只读模式
O_WRONLY 只写模式
O_RDWR 读写模式 (这三个是必须要选一个,而且仅能选其中一个)
O_APPEND 每次写操作都写入文件的末尾(类似c语言文件的写入时候的追加模式)
O_CREAT 如果指定文件不存在,则创建这个文件
O_EXCL 如果要创建的文件已存在,则返回-1,并且修改errno的值(errno是记录系统的最后一次错误代码。代码是一个int型 的值)
O_TRUNC 如果文件存在,并且以只写/读写方式打开,则清空文件全部内容(即将其长度截短为0)
O_NOCTTY 如果路径名指向终端设备,不要把这个设备用作控制终端。
O_NONBLOCK 如果路径名指向FIFO/块文件/字符文件,则把文件的打开和后继I/O (这六个可根据需要加上)
注意:
当用到O_CREAT这个参数时,就用到第三个参数。第三个参数意思是创建文件时候,文件的权限位(就是文件存取的权限)。文件的实际存取权限是(mode& ~umask)而来。为了简单明了,我们可以记这些参数
S_IRWXU 所有者具有可读可写可执行的权限
S_IRWXG 所有者所在的group具有可读可写可执行的权限
S_IRWXO 其他用户具有可读可写可执行的权限
就介绍这几个 有兴趣的可以查查
#include<sys/types.h>
int creat(const char * pathname , mode_t mode);
#include<sys/stat.h>
#include<fcntl.h>
C语言:#include<io.h>
看到这个creat()函数的原型,接着比较一下open()函数的第二个原型。所以说creat函数用法很接近,但是头文件差异很大。这里就不介绍了。
贴一个使用的列子:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd;
if((fd = open( "example.c" , O_CREAT | O_EXCL , S_IRUSR | S_IWUSR )) == -1 ) {
perror("open");
printf("open:%s with errno:%d\n",strerror(errno),errno);
}
else {
printf("creat file success\n");
}
close(fd);
return 0;
}
在c语言中我们见过fread(),fwrite()函数。现在我们看到了没见过的函数,man一下。可以看到
#include <unistd.h>
ssize_t r表明文件开始处到文件当前位置的字节数。
ead( int fd , void *buf , size_t count ); ssize_t write ( int fd , const void * buf , size_t count );
size_t 是为了方便系统之间的移植而定义的 ssize_t是signed size_t
对于read函数,这个函数的意思是,从fd所指的文件中,读出count个字节到buf所指的缓存中。同理,wirte函数是把buf缓存区的count个字节数据写入到fd所指的文件中。很好理解就贴一个代码就好了。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
void my_err( const char * err_string, int line )
{
fprintf(stderr,"line:%d ",line);
perror(err_string);
exit(1);
}
int my_read( int fd )
{
int len;
int ret;
int i;
char read_buf[64];
if( lseek( fd , 0 , SEEK_END) == -1 ) {
my_err("lseek",__LINE__);
}
if(( len = lseek(fd , 0 , SEEK_CUR )) == -1 ) {
my_err("lseek",__LINE__);
}
if((lseek(fd, 0 , SEEK_SET)) == -1 ) {
my_err("lseek",__LINE__);
}
printf("len:%d\n",len);
if((ret = read(fd , read_buf , len)) < 0 ) {
my_err("read",__LINE__);
}
for( i = 0 ; i < len ; i++ ) {
printf("%c",read_buf[i]);
}
printf("\n");
return ret;
}
int main(int argc, char *argv[])
{
int fd;
char write_buf[32] = "hello world!";
//if((fd = open( "example.c" , O_CREAT | O_RDWR | O_TRUNC , S_IRWXU )) == -1 ) {
if((fd = creat("example.c", S_IRWXU)) == -1) {
my_err("open",__LINE__);
}
else {
printf("creat file success\n");
}
if(write(fd , write_buf , strlen(write_buf) != strlen(write_buf))) {
my_err("write",__LINE__);
}
my_read(fd);
printf("/*---------------------------------*/\n");
if(lseek(fd , 10 , SEEK_END ) == -1 ) {
my_err("lseek",__LINE__);
}
if(write( fd , write_buf , strlen(write_buf)) != strlen(write_buf) ) {
my_err("write",__LINE__);
}
my_read(fd);
close(fd);
return 0;
}
接下来介绍lseek函数
#include <sys/types.h> #include <unistd.h>
off_t lseek( int fd , off_t offset , int whence );
lseek这个函数,第一个参数是指向某一文件的参数。第二个参数是表明文件开始处到文件当前位置的字节数。除非打开方式为O_APPEND。第三个参数是从哪开始计算偏移量。有三个参数
SEEK_SET 从文件开始计算偏移量。
SEEK_CUR 从文件当前位置开始计算偏移量。(文件指针的值是此位置的偏移量加上offset的值)
SEEK_END 从文件末尾处开始计算偏移量。
通过lseek这个函数就可以把文件指针移动到想移动到的位置(天马行空就算了)。lseek( fd ,0 , 三个参数 );
具体用法贴个例子:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
void my_err( const char * err_string, int line )
{
fprintf(stderr,"line:%d ",line);
perror(err_string);
exit(1);
}
int my_read( int fd )
{
int len;
int ret;
int i;
char read_buf[64];
if( lseek( fd , 0 , SEEK_END) == -1 ) {
my_err("lseek",__LINE__);
}
if(( len = lseek(fd , 0 , SEEK_CUR )) == -1 ) {
my_err("lseek",__LINE__);
}
if((lseek(fd, 0 , SEEK_SET)) == -1 ) {
my_err("lseek",__LINE__);
}
printf("len:%d\n",len);
if((ret = read(fd , read_buf , len)) < 0 ) {
my_err("read",__LINE__);
}
for( i = 0 ; i < len ; i++ ) {
printf("%c",read_buf[i]);
}
printf("\n");
return ret;
}
int main(int argc, char *argv[])
{
int fd;
char write_buf[32] = "hello world!";
//if((fd = open( "example.c" , O_CREAT | O_RDWR | O_TRUNC , S_IRWXU )) == -1 ) {
if((fd = creat("example.c", S_IRWXU)) == -1) {
my_err("open",__LINE__);
}
else {
printf("creat file success\n");
}
if(write(fd , write_buf , strlen(write_buf) != strlen(write_buf))) {
my_err("write",__LINE__);
}
my_read(fd);
printf("/*---------------------------------*/\n");
if(lseek(fd , 10 , SEEK_END ) == -1 ) {
my_err("lseek",__LINE__);
}
if(write( fd , write_buf , strlen(write_buf)) != strlen(write_buf) ) {
my_err("write",__LINE__);
}
my_read(fd);
close(fd);
return 0;
}
这个文章颜色较花,我觉得比较像vim的配置,给人很好看的感觉。我感觉我介绍比较详细,我看书时候有些还看不懂,百度了好多。