🐶博主主页:@ᰔᩚ. 一怀明月ꦿ
❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,linux
🔥座右铭:“不要等到什么都没有了,才下定决心去做”
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
目录
回顾文件
fopen()
fwrite
fputs
>文件名
追加重定向
认识系统接口
open
linux中常见的函数传参数
umask
write
read
语言和系统的区别
文件描述符
回顾文件
文件=内容+属性
1.所有对文件的操作:
1)对内容操作
2)对属性操作
2.内容是数据,属性也是数据
3.我们要访问一个文件的时候,都是先把这个文件先打开
我们:进程(我们在访问文件,其实都是进程要访问这个文件)
打开前:这个文件是普通的磁盘文件
打开后:文件加载到内存
4.一个进程可以打开多个文件吗?多个进程可以打开多个文件吗?
加载到内存中,被打开的文件,可能会存在多个
文件加载内存中是由操作系统来做的
操作系统在运行中,可能会打开很多个文件
操作系统要不要管理打开的文件呢???如何管理呢??
先描述,在组织
一个文件要被打开,一定先在内核中形成被打开的文件对象
5.文件按照是否被打开,分为:被打开的文件(内存中),没有被打开的文件(磁盘中)
6.研究本次文件操作的本质:进程和打开文件的关系
fopen()
fopen是C语言标准库中的一个函数,用于打开一个文件,并返回一个指向该文件的指针。其原型如下:
FILE *fopen(const char *filename, const char *mode); 其中,filename表示要打开的文件名,可以包含路径信息,mode则表示打开文件的模式,包括读、写等操作,具体的取值包括: * "r":以只读方式打开文件,如果文件不存在则返回NULL; * "w":以写方式打开文件,如果文件不存在则创建,如果文件存在则清空文件内容; * "a":以追加方式打开文件,如果文件不存在则创建; * "r+":以读写方式打开文件,如果文件不存在则返回NULL; * "w+":以读写方式打开文件,如果文件不存在则创建,如果文件存在则清空文件内容; * "a+":以追加方式打开文件,如果文件不存在则创建;
示例代码:
#include <stdio.h> int main() { FILE *fp = fopen("test.txt", "w"); if(fp == NULL) { printf("Failed to open file.\n"); return -1; } fprintf(fp, "Hello, world!\n"); fclose(fp); return 0; }
以上代码将会创建一个名为"test.txt"的文件,并向其中写入一行字符串"Hello, world!",然后关闭文件。
fwrite
fwrite是C语言标准库中的一个函数,用于向文件中写入数据。
其原型如下:
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream); 其中,ptr表示要写入的数据指针,size表示每个数据元素的大小(单位为字节), count表示要写入的数据元素的个数,stream表示要写入的文件流指针。
函数返回值为成功写入的数据元素个数。
示例代码:
#include <stdio.h> int main() { int arr[3] = {1, 2, 3}; FILE *fp = fopen("test.bin", "wb"); if(fp == NULL) { printf("Failed to open file.\n"); return -1; } fwrite(arr, sizeof(int), 3, fp); fclose(fp); return 0; }
以上代码将会创建一个名为"test.bin"的二进制文件,并向其中写入一个包含三个整数的数组。通过fwrite函数,将整数数组arr的内容写入到文件中。注意,使用二进制模式打开文件时应该使用"wb"模式。
对于写入文本文件,我们可以使用fputs或fprintf函数。例如:
#include <stdio.h> int main() { FILE *fp = fopen("test.txt", "w"); if(fp == NULL) { printf("Failed to open file.\n"); return -1; } fputs("Hello, world!\n", fp); fprintf(fp, "%d %s\n", 123, "abc"); fclose(fp); return 0; }
以上代码将会创建一个名为"test.txt"的文本文件,并向其中写入两行字符串。第一行是"Hello, world!\n",第二行是"123 abc\n"。注意,在文本模式下打开文件时应该使用"w"模式。
fputs
fputs是C语言标准库中的一个函数,用于向文件中写入字符串。
其原型如下:
int fputs(const char *str, FILE *stream); 其中,str表示要写入的字符串,stream表示要写入的文件流指针。 函数返回值为成功写入的字符个数(不包括字符串结尾的空字符'\0')。
示例代码:
#include <stdio.h> int main() { FILE *fp = fopen("test.txt", "w"); if(fp == NULL) { printf("Failed to open file.\n"); return -1; } fputs("Hello, world!\n", fp); fclose(fp); return 0; }
以上代码将会创建一个名为"test.txt"的文本文件,并向其中写入一行字符串"Hello, world!\n"。注意,在文本模式下打开文件时应该使用"w"模式。
>文件名
>文件名,1.如果文件不存在,就会创建文件 2.如果文件存在则会清空文件
[BCH@hcss-ecs-6176 testfile]$ >log.txt//>重定向log.txt文件时,需要打开文件, 但是也没有做什么,所以就会关闭文件,此时文件就会被清空,和"w"打开文件一样 [BCH@hcss-ecs-6176 testfile]$ ll 总用量 20 -rw-rw-r-- 1 BCH BCH 0 11月 23 23:16 log.txt -rw-rw-r-- 1 BCH BCH 65 11月 23 22:51 Makefile -rwxrwxr-x 1 BCH BCH 8512 11月 23 23:12 myfile -rw-rw-r-- 1 BCH BCH 414 11月 23 23:15 myfile.c
追加重定向
[BCH@hcss-ecs-6176 testfile]$ ll 总用量 24 -rw-rw-r-- 1 BCH BCH 63 11月 23 23:24 log.txt -rw-rw-r-- 1 BCH BCH 65 11月 23 22:51 Makefile -rwxrwxr-x 1 BCH BCH 8512 11月 23 23:20 myfile -rw-rw-r-- 1 BCH BCH 502 11月 23 23:23 myfile.c [BCH@hcss-ecs-6176 testfile]$ echo "hello linux" >>log.txt//>>和”a"打开文件一样 [BCH@hcss-ecs-6176 testfile]$ ll 总用量 24 -rw-rw-r-- 1 BCH BCH 75 11月 23 23:24 log.txt -rw-rw-r-- 1 BCH BCH 65 11月 23 22:51 Makefile -rwxrwxr-x 1 BCH BCH 8512 11月 23 23:20 myfile -rw-rw-r-- 1 BCH BCH 502 11月 23 23:23 myfile.c
认识系统接口
open
open是Linux系统中的一个系统调用,用于打开文件或创建文件。
其原型如下:#include <fcntl.h>//头文件 int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); 其中,pathname表示要打开或创建的文件路径名,flags表示打开或创建文件的方式和权限,mode表示创建文件时的权限。 flags参数可以使用以下常量进行组合: * O_RDONLY:只读打开; * O_WRONLY:只写打开; * O_RDWR:读写打开; * O_CREAT:如果文件不存在则创建; * O_TRUNC:打开文件时截断文件长度为0; * O_APPEND:在文件末尾追加数据; * O_EXCL:与O_CREAT一起使用,如果文件已经存在则报错。 mode参数可以使用以下常量进行组合: * S_IRWXU:用户具有读、写、执行权限; * S_IRUSR:用户具有读权限; * S_IWUSR:用户具有写权限; * S_IXUSR:用户具有执行权限; * S_IRWXG:组具有读、写、执行权限; * S_IRGRP:组具有读权限; * S_IWGRP:组具有写权限; * S_IXGRP:组具有执行权限; * S_IRWXO:其他用户具有读、写、执行权限; * S_IROTH:其他用户具有读权限; * S_IWOTH:其他用户具有写权限; * S_IXOTH:其他用户具有执行权限。
示例代码:
#include <fcntl.h> #include <unistd.h> #include <stdio.h> int main() { int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if(fd == -1) { printf("Failed to open file.\n"); return -1; } write(fd, "Hello, world!\n", 14); close(fd); return 0; }
以上代码将会创建一个名为"test.txt"的文件,并向其中写入一行字符串"Hello, world!\n",然后关闭文件。注意,在Linux系统中,文件的读写需要使用文件描述符来进行操作,因此需要先通过open函数打开文件,并返回一个文件描述符,然后使用write或read等函数进行读写操作,最后通过close函数关闭文件。linux中常见的函数传参数
#include<stdio.h> #define PRINT1 1 //0001//1 #define PRINT2 (1<<1) //0010//2 #define PRINT3 (1<<2) //0100//4 #define PRINT4 (1<<3) //1000//8 void print(int flags) { if(flags&PRINT1)printf("print : 1\n"); if(flags&PRINT2)printf("print : 2\n"); if(flags&PRINT3)printf("print : 3\n"); if(flags&PRINT4)printf("print : 4\n"); } int main() { print(PRINT1); print(PRINT1|PRINT2); print(PRINT1|PRINT2|PRINT3); print(PRINT1|PRINT2|PRINT3|PRINT4); return 0; }
umask
在Linux中,umask也是一个系统调用,用于设置当前进程的文件创建屏蔽字(file creation mask)。它可以通过umask()函数来调用。
#include <sys/stat.h> #include <sys/types.h> mode_t umask(mode_t mask); umask函数接受一个八进制数作为参数,表示要屏蔽的权限位。它返回先前的屏蔽字值。
以下是一个示例代码,展示了如何使用umask系统调用:
#include <stdio.h> #include <sys/stat.h> int main() { mode_t old_mask = umask(022); // 设置屏蔽字为022 printf("Old umask: %o\n", old_mask); // 创建文件 FILE *file = fopen("test.txt", "w"); if (file == NULL) { perror("Failed to create file"); return -1; } fclose(file); return 0; }
在上述示例中,首先使用umask(022)将屏蔽字设置为022,然后创建一个名为"test.txt"的文件。由于屏蔽字的设置,该文件的权限将是644(666 & ~022 = 644)。
需要注意的是,umask调用仅对当前进程及其子进程有效,不会永久更改系统的默认umask值。如果希望永久更改umask值,可以将其添加到shell的配置文件中,例如~/.bashrc或/etc/profile。
write
在Linux中,write是一个系统调用,用于将数据写入文件描述符(file descriptor)所指向的文件中。
#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count); * fd:文件描述符,表示要写入的文件。 * buf:指向要写入的数据的缓冲区。 * count:要写入的字节数。 write函数返回实际写入的字节数,如果出现错误则返回-1。
以下是一个示例代码,展示了如何使用write系统调用:
#include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <string.h> int main() { int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd == -1) { perror("Failed to open file"); return -1; } const char *data = "Hello, world!"; ssize_t bytes_written = write(fd, data, strlen(data)); if (bytes_written == -1) { perror("Failed to write to file"); close(fd); return -1; } printf("Bytes written: %zd\n", bytes_written); close(fd); return 0; }
在上述示例中,首先使用open函数打开或创建一个名为"test.txt"的文件,并获得对应的文件描述符。然后使用write函数将字符串"Hello, world!"写入文件中。最后,关闭文件。需要注意的是,文件需要以适当的方式打开(例如O_WRONLY表示只写),并且需要在使用write函数之前打开文件。并且,在写入数据时,需要确保缓冲区中的数据不会超过指定的字节数。
当我们想想向一个文件中写入字符串的时候,我们不需要在strlen()+1,\0是c语言的规定,不是文件的规定
read
在 Linux 中,read 系统调用用于从文件描述符读取数据。
它的原型如下:
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count); fd 是要读取的文件描述符,可以是文件、套接字、管道等。 buf 是用来存储读取数据的缓冲区的指针。 count 是要读取的字节数。 read 函数返回值为读取的字节数。如果返回 -1,则表示读取出错;如果返回 0,则表示已到达文件末尾(或者读取的字节数为 0)。
以下是一个简单的示例,演示如何使用 read 系统调用从文件中读取数据:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> int main() { char buffer[1024]; ssize_t bytes_read; // 打开文件 int fd = open("example.txt", O_RDONLY); if (fd == -1) { perror("open"); exit(EXIT_FAILURE); } // 从文件中读取数据 bytes_read = read(fd, buffer, sizeof(buffer)); if (bytes_read == -1) { perror("read"); exit(EXIT_FAILURE); } // 输出读取的数据 printf("Read %zd bytes: %s\n", bytes_read, buffer); // 关闭文件 close(fd); return 0; }
在这个示例中,程序打开名为 "example.txt" 的文件,并使用 read 函数从文件中读取数据到 buffer 中。然后输出读取的数据,并关闭文件。
语言和系统的区别
c语言函数接口
FILE* fp=fopen("log.txt","w"); FILE* fp=fopen("log.txt","a");
系统调用接口
int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC); int fd=open("log.txt",O_WRONLY|O_CREAT|O_APPEND);
文件描述符fd是一个连续的小整数理解文件,在操作系统中的表现:
fd的本质其实就是数组的下标
进程在运行的时候,默认是把
标准输入 键盘 stdin 0
标准输出 显示器 stdout 1
标准错误 显示器 stdout 2操作系统访问文件,只认文件描述符
FILE是一个C语言提供的结构体类型,这个结构体必定封装了文件描述符int main() { printf("stdin:%d\n",stdin->_file); printf("stdin:%d\n",stdout->_file); printf("stdin:%d\n",stderr->_file); FILE* fp=fopen("log.txt","w"); printf("fp:%d\n",fp->_file); fclose(fp); } 结果: stdin:0 stdin:1 stdin:2 fp:3
1.OS/C语言为什么默认要把0,1,2,stdin、stdout、strerr打开呢??就是为了让程序员默认进行输入输出代码编写
2.stderr是什么?
3.如何理解一切皆文件呢?
文件描述符
在Linux中,文件描述符fd(file descriptor)是一个非负整数,用于唯一标识打开的文件或其他输入/输出资源。文件描述符是操作系统内部维护的,应用程序通过文件描述符来访问文件、套接字、管道等。
下面是一些关于文件描述符的常见概念和用法:
1. 标准文件描述符:
* 0:标准输入(STDIN_FILENO),通常关联到键盘输入。
* 1:标准输出(STDOUT_FILENO),通常关联到屏幕输出。
* 2:标准错误(STDERR_FILENO),通常关联到屏幕输出。
2. 打开文件:
* 当你使用open函数打开一个文件时,它会返回一个文件描述符。
* 文件描述符从3开始递增,每次成功打开一个文件就会分配一个新的文件描述符。
3. 文件描述符的读写:
* 使用read函数从文件描述符中读取数据。
* 使用write函数将数据写入文件描述符。
4. 关闭文件:
* 使用close函数关闭文件描述符。
* 关闭文件描述符后,它可以被重用。
5. 其他操作:
* 可以使用dup或dup2函数复制文件描述符。
* 使用fcntl函数进行更高级的文件描述符操作,如非阻塞模式、文件状态标志等。下面是一个简单的示例,演示了打开文件、读取内容并关闭文件的过程:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> int main() { int file_desc = open("example.txt", O_RDONLY); if (file_desc == -1) { perror("Error opening file"); exit(1); } char buffer[100]; ssize_t bytes_read = read(file_desc, buffer, sizeof(buffer)); if (bytes_read == -1) { perror("Error reading file"); exit(1); } printf("Read %zd bytes: %s\n", bytes_read, buffer); close(file_desc); return 0; }
在这个例子中,我们使用open函数打开一个名为"example.txt"的文件,并通过read函数读取文件内容到缓冲区中。最后,使用close函数关闭文件描述符。
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸