打开(open)
open函数用来打开或创建一个文件,如果成功则返回一个文件描述符fd。
参数说明
头文件
#include <sys/types.h>// 用于 mode_t,pid_t和 size_t 类型
#include <sys/stat.h> // 用于文件权限常量
#include <fcntl.h>// 用于 open 函数
函数说明
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
- pathname: 需要打开文件的路径
- flags:用来打开文件文件的方式
O_RDONLY
只读打开O_WRONLY
只写打开O_RDWR
可读可写打开 不和O_APPEND
相与,写入多少字节就会从头开始覆盖过去
代码:
#include <sys/types.h>// 用于 mode_t,pid_t和 size_t 类型
#include <sys/stat.h> // 用于文件权限常量
#include <fcntl.h>// 用于 open 函数
#include <stdio.h>
int main()
{
int fd;
fd = open("./file1",O_RDWR);// ./file1文件的路径,O_RDWR可读可写打开
printf("fd = %d\n",fd);//打印文件描述符(成功返回一个非负整数)
return 0;
}
结果
返回值
- 成功时,返回一个非负整数,即文件描述符。
- 失败时,返回 -1,并设置 errno 变量以指示错误原因。
- 当我们附带了权限后,打开的文件就只能按照这种权限来操作。
以上三种标志不可同时使用,但可与以下标志利用OR | 运算符组合:O_CREAT
若文件不存在则创建它。使用此选项时,需要同时说明第三个参数。mode
,用其说明该新文件的存取许可权限。
–O_EXCL
如果同时指定了OCREAT
,而文件已经存在,则出错。
–O_APPEND
每次写时都加到文件的尾端。
–O_TRUNC
属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截短为0。 (里面的内容都删掉,只留写入的东西)
- mode:用来设置创建文件的权限(rwx),当
flags
中带有O_CREAT
时才有效。(许可文件有什么权限)
没有 file1 文件,打不开所以返回值为 -1
如果文件不存在,返回值会变成 -1 ,现在写一个当文件不在的话,就创建一个
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd = open("./file1",O_RDWR);//打开文件,没有文件返回 -1(文件描述符)
if(fd == -1){//判断有没有文件
printf("open file1 failed\n");//打开文件失败打印
fd = open("./file1",O_RDWR|O_CREAT,0600);//没有文件就在./file1路径创建一个,文件权限为可读可写
if(fd > 0){//创建成功,返回值大于0
printf("create file1 success\n");
}
}
return 0;
}
权限:
一共有10位数
其中: 最前面那个 – 代表的是类型
中间那三个 rw- 代表的是所有者(user)
然后那三个 rw- 代表的是组群(group)
最后那三个 r– 代表的是其他人(other)
r 表示文件可以被读(read)
w 表示文件可以被写(write)
x 表示文件可以被执行(如果它是程序的话)
rwx也可以用数字来代替
r ————4
w ———–2
x ————1
0600
0 –>代表十进制
6 –> 4 + 2 + 0 = 6 可读可写 所有者的权限
0 –> 组群 的权限
0 –> 其他人 的权限
写入(write)
write函数的头文件
#include <unistd.h>
writr函数的格式原型:
ssize_t write(int fd, const void *count, size_t count);
//write() 函数会从指针 buf 所指向的缓冲区中读取最多 count 个字节,并将其写入由文件描述符 fd 指定的文件中。
int fd –> open的返回值(文件描述符)
const void *count –> 无类型的指针,作为缓冲区来写入/读取文件
size_t count –> 写入文件的大小
wirte函数返回值
写入成功,返回值为写入成功的字节数
写入失败,返回值为 -1
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>//write和close的头文件
#include <string.h>//strlen
int main()
{
int fd;
char *buf = "xiaolong hen shuai!";//写入的内容
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file1 failed\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 success\n");
}
}
printf("open susceess : fd = %d\n",fd);
write(fd,buf,strlen(buf));
//write(int fd, const void *count, size_t count);//write() 函数会从指针 buf 所指向的缓冲区中读取最多 count 个字节,并将其写入由文件描述符 fd 指定的文件中。
close(fd);//要关闭的文件,将对应的fd(文件描述符)写进里面
return 0;
}
strlen (函数)
函数用于计算字符串的长度(不包括结尾的空字符’\0’)
strlen的头文件
#include <string.h> // 必须包含的头文件
#include <string.h> // 必须包含的头文件
int main() {
const char *str = "HelloWorld";//10个英文
size_t length = strlen(str); // 计算字符串长度
printf("字符串长度: %zu\n", length); // 输出:10,不包括结尾的空字符'\0'
return 0;
}
特性 | 说明 | |
---|---|---|
返回值类型 | size_t (无符号整型,用 %zu 打印) | |
计算范围 | 从字符串起始到第一个 \0 前的字符数 | |
不包含 | 结尾的空字符 \0 |
关闭 (Close)
close函数的头文件
#include <unistd.h>
close函数的格式原型:
int close(int fd);
int fd –> 写入需要关闭的文件,将对应的fd(文件描述符)写进里面
重点:
- writr函数的格式原型:
ssize_t write(int fd, const void *count, size_t count);
//write() 函数会从指针 buf 所指向的缓冲区中读取最多 count 个字节,并将其写入由文件描述符 fd 指定的文件中。
- close函数的格式原型:
int close(int fd);
int fd –> 写入需要关闭的文件,将对应的fd(文件描述符)写进里面
读取 (read)
read函数的头文件
#include <unistd.h>
read函数的格式原型:
ssize_t read(int fd, void buf[.count], size_t count);
描述 read() 函数尝试从文件描述符 fd 中读取最多 count 个字节的数据,并将其存储在从 buf 开始的缓冲区中
malloc函数 (动态分配内存空间)
在 C 语言中,malloc
函数用于动态分配内存空间,它在程序运行时从堆(heap)中申请指定大小的内存。
基本用法
头文件
#include <stdlib.h> // 必须包含此头文件
函数原型
void* malloc(size_t size);//空类型指针
- 参数:
size
是要分配的字节数。 - 返回值:
- 成功:返回指向分配内存起始地址的
void*
指针 - 失败:返回
NULL
- 成功:返回指向分配内存起始地址的
使用步骤
- 计算所需内存大小(通常用
sizeof
) - 调用
malloc
分配内存 - 检查指针是否为
NULL
(分配失败处理) - 使用分配的内存
- 释放内存(必须用
free()
避免内存泄漏)
示例代码
分配单个整型
#include <stdio.h>
#include <stdlib.h>
int main() {
// 动态分配一个 int 类型的内存空间
int* ptr = (int*)malloc(sizeof(int));
// 检查分配是否成功
if (ptr == NULL) {
printf("内存分配失败!\n");
return 1; // 退出程序
}
*ptr = 100; // 向分配的内存写入数据
printf("值 = %d\n", *ptr);
free(ptr); // 释放内存
ptr = NULL; // 避免悬空指针(可选但推荐)
return 0;
}
1. 类型转换(C++ 中必须,C 中可选但推荐):
int* ptr = (int*)malloc(sizeof(int)); // C/C++ 通用写法
2. 计算内存大小:
- 使用
sizeof
而非直接写数字(保证可移植性):
// 推荐
int* arr = malloc(10 * sizeof(int));
// 避免(硬编码大小)
int* arr = malloc(40); // 假设 int 占 4 字节(不通用!)
read返回0和读取的东西为空,因为写东西进里面的时候,写完光标在最后了,不会返回前面,所以读取到的东西就为0和空了
解决办法 //关闭,重新打开
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>//write和close的头文件
#include <string.h>//strlen
#include <stdlib.h>
int main()
{
int fd;//定义一个变量来接收返回值
char *buf = "xiaolong hen shuai!";//定义一个指向char型的指针
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file1 failed\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 success\n");
}
}
printf("open susceess : fd = %d\n",fd);
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1){
printf("write %d byte to file\n",n_write);
}
close(fd);//关闭
fd = open("./file1",O_RDWR);//重新打开
char *readBuf;
readBuf = (char *)malloc(sizeof(char)*n_write + 1);//这行代码动态分配了n_write + 1 字节的内存空间,用于存储一个以 '\0' 结尾的字符串,其中前 n_write 字节存放有效字符,最后 1 字节存放字符串结束符。
int n_read = read(fd, readBuf, n_write); //read() 函数尝试从文件描述符 fd 中读取最多 count 个字节的数据,并将其存储在从 buf 开始的缓冲区中
printf("read %d ,context:%s\n",n_read,readBuf);
close(fd);
return 0;
}
重点
- 描述 read() 函数尝试从文件描述符 fd 中读取最多 count 个字节的数据,并将其存储在从 buf 开始的缓冲区中
- 读取成功会返回读取的字节数
- 读取错误会返回 -1
- 函数原型 上面查看
文件光标移动操作
头文件
#include <unistd.h>
函数原型
off_t lseek(int fd, off_t offset, int whence);//以文件描述符来选择对应哪个文件,在文件里以 whence 方式来定义 offset 偏移数值(可正负偏移)
offset(偏移量)
- 可以正负偏移
whence的方式(哪个位置放置光标)
- SEEK_SET :在最前面放置光标
- SEEK_CUR :在当前位置放置光标
- SEEK_END :在末尾放置光标
代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>//write和close的头文件
#include <string.h>//strlen
#include <stdlib.h>
int main()
{
int fd;//定义一个变量来接收返回值
char *buf = "xiaolong hen shuai!";//定义一个指向char型的指针
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file1 failed\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 success\n");
}
}
printf("open susceess : fd = %d\n",fd);
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1){
printf("write %d byte to file\n",n_write);
}
close(fd);//关闭
fd = open("./file1",O_RDWR);//重新打开
lseek(fd, 0,SEEK_SET);//在最前面放置光标,偏移0
char *readBuf;
readBuf = (char *)malloc(sizeof(char)*n_write + 1);//这行代码动态分配了n_write + 1 字节的内存空间,用于存储一个以 '\0' 结尾的字符串,其中前 n_write 字节存放有效字符,最后 1 字节存放字符串结束符。
int n_read = read(fd, readBuf, n_write); //read() 函数尝试从文件描述符 fd 中读取最多 count 个字节的数据,并将其存储在从 buf 开始的缓冲区中
printf("read %d ,context:%s\n",n_read,readBuf);
close(fd);
return 0;
}
创建文件(creat)
和open
一样操作,一样要重新写 fd
文件操作指令,实现 cp 指令
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>//write和close的头文件
#include <string.h>//strlen
#include <stdlib.h>
int main(int argc, char **argv)
{
int fdSrc;//需要复制的文件
int fdDes;//复制出来的文件
char *readBuf = NULL;//读写的指针
if(argc != 3)//参数个数不等于3
{
printf("patatm error\n");
exit(-1);//退出
}
fdSrc = open(argv[1], O_RDWR);//获取文件描述符fd
int size = lseek(fdSrc,0,SEEK_END);//获取文件的字节来准备缓存空间
lseek(fdSrc,0,SEEK_SET);//光标放置最前面
readBuf = (char *)malloc(sizeof(char)*size + 8);//分配以size+8的动态内存的大小给readBuf
int n_read = read(fdSrc, readBuf, size);//读取fdSrc的内容放在readBuf里面,并返回读到的字节个数
fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);//创建一个新的文件
int n_write = write(fdDes,readBuf,strlen(readBuf));//写读到readBuf的东西给fdDes
close(fdSrc);//关闭fdSrc
close(fdDes);//关闭fdDes
return 0;
}
命令行参数 char **argv
int main(int argc, char **argv) {
// argv[0] → 程序名 (char*)
// argv[1] → 第一个参数 (char*)
for (int i = 0; i < argc; i++)
printf("参数 %d: %s\n", i, argv[i]);
return 0;
}
文件编程小应用之修改程序配置文件
strstr函数
strstr
是 C 语言中用于查找子字符串的标准库函数,它像一个“字符串探测器”。(在指定文件里面寻找需要修改的字符)
#include <string.h> // 必须包含头文件
char *strstr(const char *haystack, const char *needle);
haystack
:主字符串(干草堆)needle
:要查找的子字符串(针)- 返回值:指向
主字符串
中子串首次出现的指针
修改配置程序
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>//write和close的头文件
#include <string.h>//strlen
#include <stdlib.h>
int main(int argc, char **argv)
{
int fdSrc;
char *readBuf = NULL;
if(argc != 2)
{
printf("patatm error\n");
exit(-1);
}
fdSrc = open(argv[1], O_RDWR);
int size = lseek(fdSrc,0,SEEK_END);
lseek(fdSrc,0,SEEK_SET);
readBuf = (char *)malloc(sizeof(char)*size + 8);
int n_read = read(fdSrc, readBuf, size);
char *p = strstr(readBuf, "LENG=");//在 `readBuf` 字符串中搜索子串 `"LENG="`
if(p == NULL){
printf("not found\n");
exit(-1);
}
p = p + strlen("LENG=");//读取 LENG= 的个数 + p
*p = '5';//将光标位置的内容改为 5
lseek(fdSrc,0,SEEK_SET);
int n_write = write(fdSrc,readBuf,strlen(readBuf));
close(fdSrc);
// close(fdDes);
return 0;
}
写一个整数到文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>//write和close的头文件
#include <string.h>//strlen
#include <stdlib.h>
int main()
{
int fd;
int data = 100;
int data2 = 0;
fd = open("./file1",O_RDWR);
int n_write = write(fd, &data, sizeof(int));//写整数到file1文件里,之间取data地址的内容写进里面
lseek(fd, 0, SEEK_SET);//写完,光标放在最前面
int n_read = read(fd, &data2, sizeof(int));//将东西读取放到data2里面
printf("read %d \n",data2);
close(fd);
return 0;
}
写结构体数组到文件
单个结构体
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>//write和close的头文件
#include <string.h>//strlen
#include <stdlib.h>
struct Test
{
int a;
int c;
};
int main()
{
int fd;
struct Test data = {100,'a'};//初始化
struct Test data2;
fd = open("./file1",O_RDWR);
int n_write = write(fd, &data, sizeof(struct Test));//将data的内容写到file1文件里,
lseek(fd, 0, SEEK_SET);
int n_read = read(fd, &data2, sizeof(struct Test));//以struct Test的大小来读fd(文件描述符)所指的文件存储到 data2的地址里面
printf("read %d,%c \n",data2.a,data2.c);
close(fd);
return 0;
}
两个结构体
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>//write和close的头文件
#include <string.h>//strlen
#include <stdlib.h>
struct Test
{
int a;
int c;
};
int main()
{
int fd;
struct Test data[2] = {{100,'a'},{101,'b'}};//定义结构体数组
struct Test data2[2];
fd = open("./file1",O_RDWR);
int n_write = write(fd, &data, sizeof(struct Test)*2);
lseek(fd, 0, SEEK_SET);
int n_read = read(fd, &data2, sizeof(struct Test)*2);
printf("read %d,%c \n",data2[0].a,data2[0].c);
printf("read %d,%c \n",data2[1].a,data2[1].c);
close(fd);
return 0;
}