Linux编程——文件操作

文件操作系统调用

在linux系统中,几乎一切都是文件。

当一个程序开始运行的时候, 一般会有已经打开的文件描述符:
0: 标准输入
1: 标准输出
2: 标准错误

文件的读写

文件的读写通过write和read的系统调用来完成。 它们的原型如下:

#include <unistd.h>

size_t write(int fildes, const void *buf, size_t nbytes);
size_t read(int fildes, void *buf, size_t nbytes);

write是把缓冲区buf的前nbytes个字节写入与文件描述符fildes关联的文件中;
read是从文件描述符fildes关联的文件中读入nbytes个字节的数据, 并把它们放到数据区buf中;

/**
 * simple_write.c
 */
#include <unistd.h>
#include <stdlib.h>

int main()
{
    if ((write(1, "Here is some data!\n", 19) != 19))
    {
        write(2, "A write error has occurred on file descriptor!\n", 48);
    }

    exit(0);
}
#include <unistd.h>
#include <stdlib.h>

int main()
{
    char buffer[128];
    int nread;

    nread = read(0, buffer, 128);
    if (nread == -1)
    {
        write(2, "A read error has occurred\n", 26);
    }

    if ((write(1, buffer, nread)) != nread)
    {
        write(2, "A write error has occurred\n", 27);
    }
    exit(0);
}

文件打开

文件打开是通过系统调用open完成的。

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

int open(const char *path, int oflags);
int open(const char *path, int oflags, mode_t mode);

oflags参数是通过命令文件访问模式与其他可选的模式相结合的方式来指定的。

模式说明
O_RDONLY只读方式打开文件
O_WRONLY只写方式打开
O_RDWR以读写方式打开

以上表格中参数是必须指定的参数。 还有一些可选的模式如下:

模式说明
O_APPEND把写入的数据追加到文件的末尾
O_TRUNC把文件长度设置为零, 丢弃已有的内容
O_CREAT如果需要,就按mode中给出的参数创建文件
O_EXCL与O_CREAT一起使用,确保调用者创建出文件。可以防止两个程序同时创建一个文件
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

int main()
{
    char c;
    int in, out;

    in = open("file.in", O_RDONLY); // 只读打开文件
    out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); //只写方式打开并创建文件, 文件属主具有读写权限

    while(read(in, &c, 1) == 1) {
        write(out, &c, 1); //一次复制一个字符
    }

    exit(0);
}

lseek系统调用

lseek系统调用对文件描述符fildes的读写指针进行设置。

#include <unistd.h>
#include <sys/types.h>

off_t lseek(int fildes, off_t offset, int whence);

whence可以取如下值:
SEEK_SET: offset是一个绝对位置
SEEK_CUR: offset 是当前位置的一个相对位置。
SEEK_END: offset是相对于文件尾的一个相对位置。
lseek返回的是从文件头到文件指针被设置处的字节偏移值, 失败时返回-1。 off_t是一个与具体实现有关的整数类型。定义在types.h头文件中。

fstat、stat 和 lstat系统调用

fstat系统调用返回与打开文件描述符相关的文件的状态信息, 该信息将会写入到一个buf结构中,buf的地址以参数形式传递给fstat。

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

int fstat(int fildes, struct stat *buf);
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);

dup和 dup2系统调用

#include <unistd.h>

int dup(int fildes);
int dup2(int fildes, int fildes2);

dup提供了一种复制文件描述符的方法, 使得我妈能够通过两个或者更多个不同的描述符来访问同一个文件。 dup系统调用复制文件描述符fildes,返回一个新的描述符。 dup2系统调用则是通过明确指定目标描述符来把一个文件描述符复制为另一个。
当通过管道进行通信时, 这些调用也非常有用。

ioctl系统调用

#include <unistd.h>

int ioctl(int fildes, int cmd, ...);

ioctl系统嗲有提供了一个用于控制设备及其描述符行为和配置底层服务的接口。 终端、文件描述符、套接字甚至磁带机都可以有为它们定义的ioctl。 ioctl对描述符引用的对象执行cmd参数中给出的操作。
比如 对ioctl的如下调用将打开键盘上的LED灯。

ioctl(tty_fd, KDSETLED, LED_NUM | LED_CAP | LED_SCR);

标准I/O

fopen函数

#include <stdio.h>

FILE *fopen(const char *filename, const char *mode);

fopen打开由filename参数指定的文件,并把它与一个文件流关联起来, mode参数指定文件的打开方式,取值如下:
1. “r” “rb”: 只读方式打开
2. “w” “wb” : 以写的方式打开, 并把文件长度截断未零。
3. “a” “ab”: 以写的方式打开, 新内容追加在文件尾。
4. “r+” “rb+” “r+b”: 以更新的方式打开

fread函数 和 fwrite函数

fread函数和fwrite函数的原型如下:

#include <stdio.h>

size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);

fread函数用于从一个文件流里读取数据, 数据从文件流stream读到由ptr指向的数据缓冲区里。 fread和fwrite都是对数据记录进行操作的, size参数指定每个记录的长度, nitems指定要传输的记录个数。 fread的返回值是值成功读取到缓冲区里面的记录个数。 fwrite的返回值是成功写入的记录个数。

/*
 * 向input.txt写入4个int数据
 */
#include <stdio.h>
#include <stdlib.h>

int main()
{

    int data[4] = {1, 2, 3, 4};
    FILE *file;
    file = fopen("input.txt", "wb"); //写方式打开文件,并将文件长度截断为零
    if (file == NULL) {
        printf("can't open file: input.txt");
        exit(1);
    }

    int nwrite = fwrite(data, sizeof(int), 4, file);
    if (nwrite > 0) {
        printf("write %d int number into input.txt\n", nwrite);
    }
    fclose(file);
    exit(0);
}
/*
 * 从input.txt 文件中读取第二个整数
 */
#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fp;
    int data[4];
    fp = fopen("input.txt", "rb");

    if (fp == NULL) {
        printf("can't open file input.txt");
        exit(1);
    }
    int res = fseek(fp, sizeof(int), SEEK_SET); //从第二个整型数开始
    int nread = fread(data, sizeof(int), 1, fp);

    if (nread > 0) {
        printf("success reading %d number of int.\n", nread);
        for (int i = 0; i < nread; i++) {
            printf("%d\t", data[i]);
        }
        printf("\n");
    }
    fclose(fp);
    exit(0);
}

运行结果:

success reading 1 number of int.
2   

fseek, fclose, fflush函数

fseek函数是与lseek系统调用对应的文件流函数。
fclose函数关闭指定的文件流, 使所有尚未写出的数据都写出。如果程序需要确保数据已经全部写出, 就应该调用fclose函数。
fflush函数是把文件流的所有未写出数据立即写出。 调用fclose函数隐含执行了一次flush操作。

#include <stdio.h>

int fclose(FILE *stream);
int fflush(FILE *stream);
int fseek(FILE *stream, long int offset, int whence);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值