文件IO-系统IO

文件IO的概念:

什么是文件IO,又称系统IO,系统调用

是操作系统提供的API接口函数。

POSIX接口 (了解)

注意:文件IO不提供缓冲机制

文件IO的API

open  close read read

 

文件描述符概念:

英文:缩写fd(file descriptor)

是0-1023的数字,表示文件。

0, 1, 2 的含义 标准输入,标准输出,错误

文件IO 打开

open

int open(const char *pathname, int flags);   不创建文件

int open(const char *pathname, int flags, mode_t mode);  创建文件,不能创建设备文件

成功时返回文件描述符;出错时返回EOF

 成功时返回文件描述符;出错时返回EOF

打开文件时使用两个参数

创建文件时第三个参数指定新文件的权限,(只有在建立新文件时有效)此外真正建文件时的权限会受到umask 值影响,实际权限是mode-umaks

可以打开设备文件,但是不能创建设备文件(创建设备mknode 驱动部分会讲)

文件IO和标准的模式对应关系:

r O_RDONLY

r+ O_RDWR

w O_WRONLY | O_CREAT | O_TRUNC, 0664

w+ O_RDWR | O_CREAT | O_TRUNC, 0664

a O_WRONLY | O_CREAT | O_APPEND, 0664

a+ O_RDWR | O_CREAT | O_APPEND, 0664

原型

int open(const char *pathname, int flags, mode_t mode);

参数

pathname

被打开的文件名(可包括路径名)。

flags

O_RDONLY:只读方式打开文件。

这三个参数互斥

O_WRONLY:可写方式打开文件。

O_RDWR:读写方式打开文件。

O_CREAT:如果该文件不存在,就创建一个新的文件,并用第三的参数为其设置权限。

O_EXCL:如果使用O_CREAT时文件存在,则可返回错误消息。这一参数可测试文件是否存在。

O_NOCTTY:使用本参数时,如文件为终端,那么终端不可以作为调用open()系统调用的那个进程的控制终端。

O_TRUNC:如文件已经存在,那么打开文件时先删除文件中原有数据。

O_APPEND:以添加方式打开文件,所以对文件的写操作都在文件的末尾进行。

mode

被打开文件的存取权限,为8进制表示法。

umask概念:

umask 用来设定文件或目录的初始权限

文件和目录的真正初始权限

文件或目录的初始权限 = 文件或目录的最大默认权限 - umask权限

文件的关闭

int close(int fd)

关闭后文件描述符不能代表文件

成功时返回0;

出错时返回EOF 程序结束时自动关闭所有打开的文件

文件关闭后,文件描述符不再代表文件

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char *argv[]){
    int fd;
    int ret;
     
    fd = open("test.txt",O_WRONLY|O_CREAT|O_TRUNC, 0666);
    if(fd<0){
       printf("open file err\n");
       return 0;

    }
    printf("sucess,fd=%d\n",fd);

    ret=  close(fd);
    if(ret<0){
        printf("close failed\n");
    }

    ret=close(fd);
    printf("ret=%d\n",ret);
}

文件IO的读写和定位

 read函数用来从文件中读取数据:

 #include  <unistd.h>  

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

成功时返回实际读取的字节数;出错时返回EOF

读到文件末尾时返回0 buf是接收数据的缓冲区

count不应超过buf大小

write函数用来向文件写入数据:

#include  <unistd.h>
 ssize_t  write(int fd, void *buf, size_t count);

成功时返回实际写入的字节数;出错时返回EOF

buf是发送数据的缓冲区

count不应超过buf大小

容易出错点:

求字符串长度使用sizeof,对二进制数据使用strlen

printf 的字符最后没有\0

 lseek函数用来定位文件:

 #include  <unistd.h>
 off_t  lseek(int fd, off_t offset, intt whence);

 成功时返回当前的文件读写位置;

出错时返回EOF

参数offset和参数whence同fseek完全一样

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(int argc,char *argv[]){

    int fd;
    int ret;
    char buf[32] = "hello world";
    char buf2[32]={0};
    fd = open("test.txt",O_RDWR | O_CREAT|O_APPEND, 0666);
    if(fd<0){
       printf("open file err\n");
       return 0;

    }
    printf("sucess,fd=%d\n",fd);

    ret=write(fd,buf,strlen(buf));
    if(ret<0){
       perror("write");
       goto END;
    }
    printf("write count=%d\n",ret);
    
    lseek(fd,0,SEEK_SET);
     
    ret = read(fd,buf2,32);
    if(ret<0){
        perror("read");
        goto END;
    }
    buf2[31]=0;//数组最后一位置零,不设置,超出数组范围会显示乱码
    printf("read buf2=%s\n",buf2);

END:


   close(fd);


}

利用文件IO实现文件的复制

#include <stdio.h>

int main() {
    FILE *source_file, *target_file;
    int ch;

    // 打开源文件和目标文件
    source_file = fopen("source.txt", "r");
    target_file = fopen("target.txt", "w");
    if(source_file==NULL){
       perror("fopen");
       return 0;
    }
    if(target_file==NULL){
         perror("fopen");
         return 0;
     }

    // 逐个字符读取源文件内容,并写入目标文件
    while ((ch = fgetc(source_file)) != EOF) {
    printf("ch=%d\n",ch);
    fputc(ch, target_file);
    }
     printf("ch=%d\n",ch);

    // 关闭文件
    fclose(source_file);
    fclose(target_file);

    printf("文件复制完成。\n");

    return 0;
}

上述代码中,我们使用`fopen`函数打开源文件和目标文件,并以读取模式`"r"`打开源文件,以写入模式`"w"`打开目标文件。然后,我们使用`fgetc`函数逐个字符读取源文件的内容,然后使用`fputc`函数将每个字符写入目标文件。最后,我们使用`fclose`函数关闭文件,并打印出复制完成的提示信息。

请注意,上述代码只适用于文本文件的复制。如果需要复制二进制文件,可以使用二进制模式的读写(如`"rb"`和`"wb"`)。

文件名通过命令行参数指定

如果希望通过命令行参数指定源文件和目标文件名,则可以使用 argcargv 参数来获取命令行参数,并将其作为文件名进行处理。下面是相应的示例代码:

#include <stdio.h>

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("Usage: %s <source_file> <target_file>\n", argv[0]);
        return 1;
    }

    FILE *source_file, *target_file;
    char ch;

    // 打开源文件和目标文件
    source_file = fopen(argv[1], "r");
    target_file = fopen(argv[2], "w");

    if (source_file == NULL || target_file == NULL) {
        printf("Failed to open file.\n");
        return 1;
    }

    // 逐个字符读取源文件内容,并写入目标文件
    while ((ch = fgetc(source_file)) != EOF) {
        fputc(ch, target_file);
    }

    // 关闭文件
    fclose(source_file);
    fclose(target_file);

    printf("文件复制完成。\n");

    return 0;
}

在上述代码中,argc 参数表示命令行参数的数量,argv 参数是一个指向字符指针的数组,其中保存了命令行参数的值。

main() 函数中,我们首先检查 argc 的值是否为3,即程序名 + 源文件名 + 目标文件名。如果参数数量不正确,我们打印出正确的用法提示并返回错误代码。

然后,我们使用 fopen 函数根据 argv[1]argv[2] 的值打开源文件和目标文件。

如果文件打开失败,我们打印出失败的提示信息并返回错误代码。否则,我们使用 fgetcfputc 函数来逐个字符读取源文件内容并写入目标文件。

最后,我们使用 fclose 函数关闭文件,并打印出复制完成的提示信息。

注意:上述代码只能用于文本文件的复制。如果需要复制二进制文件,可以使用二进制模式的读写(如 "rb""wb"

 

打开文件的方式?

在C语言中,可以使用标准库中的 fopen() 函数来打开文件。fopen() 函数提供了多种模式用于打开文件,这些模式可指定文件的读写权限和操作方式。以下是 fopen() 函数的基本形式:

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

其中,filename 参数是一个字符串,表示文件的路径和名称。

mode 参数是一个字符串,指定文件的打开模式。以下是常用的文件打开模式:

  • "r": 以只读模式打开文件。
  • "w": 以写入模式打开文件,如果文件不存在,则创建新文件;如果文件已存在,则清空文件内容。
  • "a": 以追加模式打开文件,如果文件不存在,则创建新文件;如果文件已存在,则在文件末尾追加内容。
  • "rb": 以二进制只读模式打开文件。
  • "wb": 以二进制写入模式打开文件,如果文件不存在,则创建新文件;如果文件已存在,则清空文件内容。
  • "ab": 以二进制追加模式打开文件,如果文件不存在,则创建新文件;如果文件已存在,则在文件末尾追加内容。

fopen() 函数返回一个文件指针,可以用于后续的文件读写操作。如果文件无法打开,fopen() 函数将返回 NULL

以下是一个示例代码,演示了如何使用 fopen() 函数打开文件:

#include <stdio.h>

int main() {
    FILE *file;
    file = fopen("example.txt", "r");  // 以只读模式打开文件 "example.txt"

    if (file == NULL) {
        printf("无法打开文件。\n");
        return 1;
    }

    // 在这里进行文件读写操作...

    fclose(file);  // 关闭文件
    return 0;
}

 

上述示例中,我们使用 fopen() 函数以只读模式打开了一个名为 "example.txt" 的文件,并进行了错误检查。如果文件打开失败,我们打印出错误提示信息。

在实际操作中,您可以根据需要选择合适的文件打开模式,并在打开文件后进行相应的读写操作。最后,使用

 

如何判断读到源文件的末尾? 

在C语言中,可以使用feof()函数或fgets()函数来判断是否读到了源文件的末尾。

  1. 使用feof()函数:该函数可以用于检测文件流上的文件结束符。当文件结束符被读取时,feof()函数返回非0值(即真);否则,返回0(即假)。
#include <stdio.h>

int main() {
    FILE *file = fopen("filename.txt", "r");
    if (file == NULL) {
        printf("文件打开失败\n");
        return 0;
    }

    char ch;
    while (!feof(file)) {
        ch = fgetc(file);
        if (ch == EOF) {
            break;
        }
        printf("%c", ch);
    }

    fclose(file);
    return 0;
}

 

  1. 使用fgets()函数:该函数可用于从文件中读取一行字符。当fgets()函数读取到文件末尾时,返回空指针。
#include <stdio.h>

int main() {
    FILE *file = fopen("filename.txt", "r");
    if (file == NULL) {
        printf("文件打开失败\n");
        return 0;
    }

    char line[100];
    while (fgets(line, sizeof(line), file) != NULL) {
        printf("%s", line);
    }

    fclose(file);
    return 0;
}

 注意:在任何情况下,都应该在读取文件之后及时关闭文件流

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值