Linux下文件编程(1)

本文章将详细的讲解Linux下基本的文件I/O操作,以及文件的高级操作。

本文代码运行在codeblocks的IDE中,Linux系统采用的是Ubuntu12.04

1.1 文件描述符

     文件描述符就相当于文件的身份证号,通过它来标示文件,文件描述符是一个非负整数。表示为int类型的对象,它是一个索引值,指向内核中每个进程打开文件的记录表。

     每个进程都可以拥有若干个文件描述符,Linux中每个进程可以拥有1024个文件描述符。

     文件描述符中0是标准输入文件,对应键盘,符号常量为STDIN_FILENO;1是标准输出文件,对应显示器,符号常量为STDOUT_FILENO ; 2是标准错误输出文件,符号常量为STDERR_FILENO,他们都定义在<unistd.h>中

1.2 基本文件I/O操作

   这些基本的I/O操作函数的头文件如下:

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    #include<unistd.h>

1.2.1 open函数

   功能:打开或者创建一个文件,open函数是一个进程存取一个文件中的数据必须首先完成的系统调用。

   格式:int open( const char* pathname, int flag, .../* mode_t mode */ );

   返回值:成功时返回一个int的非负整数,此时是最小编号的文件描述符,失败时返回-1

   参数说明:pathname表示要打开或者创建的文件名;

                       flag表示打开方式,其中常用的O_RDONLY,O_WRONLY,O_RDWR分别表示只读、只写、可读/写方式打开文件。常用的标志还有O_CREAT,表示若此文件不存在,则创建,使用此选项时,要用到mode参数以设定新文件的访问权限。其他不常用的标志还有:

                      O_APPEND(在文件尾端追加)

                      O_EXCL      测试一个文件是否存在。

                      O_TRUNC     如果文件成功打开,则将其长度截短为0。

                      O_NOCTTY    如果pathname参数指的是终端设备,则不将该设备作为此进程的控制终端。

                      O_NONBLOCK  如果pathname指的是一个FIFO,块特殊文件或字符特殊文件,则该选项为文件的本次打开操作和后续的I/O操作设置非阻塞模式。

                      O_DSYNC     使该文件所有的write操作等待,直到对该文件所有的I/O操作都完成之后,但是如果write操作不影响读取刚写入的数据时,不用等待文件属性被更新。

                      O_RSYNC     使该文件所有的read操作等待,直到对该文件所有的write操作都完成之后。

                      O_SYNC      使该文件所有的write操作等待,直到对该文件所有的I/O操作都完成之后。

                     在这儿注意:除了常用的三种标志外,其他的标志可以通过&来结合使用,三种读写的标志只能使用一个!!!!

                      mode表示在创建一个新文件时设定的新文件的权限。

1.2.2  close 函数

    功能:关闭不再使用的文件

    格式:int close( int fd );

    返回值:成功返回0,反之返回-1

1.2.3 read 函数

    功能:从文件中读取指定长度的数据到内存中。

    格式:ssize_t read( int fd, void *buf, size_t count);

    返回值:成功返回读到的字节数,若已到文件结尾返回0,出错返回-1。

    参数说明:fd表示文件描述符;buf表示输入缓冲区指针;count表示要读入的字节数。

    备注:read函数是从fd指定的文件中读取count个字节到buf中,如果count为0,那么该系统调用返回0;如果该count大于SSIZE_MAX,则结果不能确定。

1.2.4 write 函数

    功能:从内存中写指定长度的数据到文件中。

    格式:ssize_t write( int fd, void *buf, size_t count);

    返回值:成功返回已写的字节数,出错返回-1。。

    参数说明:fd表示文件描述符;buf表示输出缓冲区指针;count表示要写的字节数。

1.2.5 creat 函数

    功能:创建一个文件。

    格式:int creat(const char * pathname,mode_t mode)

    返回值:成功返回该文件的文件描述符,出错返回-1。

    参数说明:pathname表示创建的文件名,创建的文件以只读方式打开。mode表示该文件的权限

1.2.6 lseek 函数

    功能:文件偏移

    格式:off_t lseek( int fd, off_t offset, int whence );

    返回值:成功时返回新的文件偏移量,失败时返回-1

    参数说明:fd表示文件描述符。offset表示偏移量,whence表示当前位置的基点,其中取值为如下三种:    

                        SEEK_SET    将文件的读写偏移量设置为距离文件首段offset个字节处。

                        SEEK_CUR    将文件的读写偏移量设置为距离当前值加offset个字节处,offset可为正负。

                        SEEK_END    将文件的读写偏移量设置为距离文件尾端offset个字节处,offset可为正负。

下面是关于这些基本函数的两个例子:

简单复制函数:用于从一个文件中复制数据到一个新建的文件中,该程序是用于命令行中输入的

#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>

#define PERMS 0666 //文件权限
#define DUMMY 0  //mode 参数默认值
#define BUFSIZE 1024 //缓冲区大小


int main(int argc,char *argv[])
{
    int source_fd,target_fd;//文件描述符
    int num;  //读取的数据大小
    char iobuf[BUFSIZE];//缓冲区

    if(argc!=3)
    {
        printf("参数错误\n");
        return 1;
    }

    if((source_fd=open(*(argv+1),O_RDONLY,DUMMY))==-1)
    {
        printf("原文件打开失败\n");
        return 2;
    }

    if((target_fd=open(*(argv+2),O_CREAT|O_WRONLY,PERMS))==-1)
    {
        printf("目标文件打开失败\n");
        return 3;
    }

    while((num=read(source_fd,iobuf,BUFSIZE))>0)
    {
        if(write(target_fd,iobuf,num)!=num)
        {
            printf("目标文件写操作失败\n");
            return 4;
        }
    }

    close(source_fd);
    close(target_fd);

    return 0;
}

其中,下面的这个程序实现同样的功能

#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<stdio.h>
#include<fcntl.h>

#define DUMMY 0
#define PERMS 0666
#define BUFSIZE 1024

int main()
{
    int source_fd,target_fd;
    int num;
    char iobuf[BUFSIZE];

    if((source_fd=open("tz.txt",O_RDONLY,DUMMY))==-1)
    {
        printf(" 打开原文件失败\n");
        return 1;
    }

    if((target_fd=open("dq.txt",O_CREAT|O_WRONLY,PERMS))==-1)
    {
        printf("打开目标文件失败\n");
        return 2;
    }

    while((num=read(source_fd,iobuf,BUFSIZE))>0)
    {
        if(num!=(write(target_fd,iobuf,num)))
        {
            printf("目标文件写操作失败\n");
            return 3;
        }
        printf("%s\n",iobuf);
    }

    close(source_fd);
    close(target_fd);

    return 0;
}
对于结构体的复制:

#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>

#define LNAME 9             //用户名长度
#define PERMS 0666          //文件权限
#define DATAFILE "datafile.txt" //写入数据的文件名
#define USERS 10            //用户结构大小

typedef struct user
{
    int uid;
    char login[LNAME+1];
}RECORD;

char *user_name[10]={"u1","u2","u3","u4","u5","u6","u7","u8","u9","admin"};

int main()
{
    int i,fd;
    RECORD rec;

    if((fd=open(DATAFILE,O_WRONLY|O_TRUNC|O_CREAT,PERMS))==-1)
    {
        perror("open");
        return 1;
    }
    for(i=USERS-1;i>=0;i--)
    {
        rec.uid=i;
        strcpy(rec.login,user_name[i]);
        lseek(fd,(long)i*sizeof(RECORD),SEEK_SET);
        write(fd,(char *)&rec,sizeof(RECORD));
        //printf("%d %s\n",rec.uid,rec.login);
    }

    lseek(fd,0L,SEEK_END);
    close(fd);

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值