文件操作
int open(const char filename, int flags);
int open(const char filename, int flags, mode_t, mode);
filename 如果不写路径,默认是当前路径。
flags 打开方式,O_RDONLY,O_WRONLY,O_RDWR中只选择一个。其他组合方式,如果没有实际意义,系统也不会处理,如O_RDONLY和O_APPEND
创建一个文件,不设置文件属主和属组的执行ID(0),文件属主有读写和执行的权限(1+2+4=7),文件属组有读和执行的权限(1+4=5),其他用户没有任何权限(0),则函数调用形式如下
- 文件属主 文件的创建人
- 文件属组 文件创建人权限,所属组
- 其他用户
open(“test”, O_CREAT, 00750);
如果文件创建成功,会返回一个文件描述符,以后对该文件的操作就可以通过此文件描述符进行,否则返回-1,并输出文件描述符。
打开文件
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> /** open */
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> /** close */
int main(int argvLength, char *argv[])
{
int fol;
// S_IRWXU 文件属主可以,读写执行
// S_IRGRP 文件属组可以,读
// S_IXGRP 文件属组可以,执行
// O_CREAT 如果没有文件的话,创建一个文件
fol = open("file.txt", O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP);
int i = S_IRWXU | S_IRGRP | S_IXGRP;
printf("%d\n", i);
printf("%d\n", fol);
// 关闭文件,释放资源 返回0标识关闭成功,-1表示关闭失败
int closeFlag = close(fol);
printf("关闭成功状态 %d\n", closeFlag);
// 创建一个文件 int creat(const char *filename, mode_t mode);
creat("file2.txt", 00750);
// O_EXCL 与 O_CREAT 配合使用,如果文件已存在会返回-1,并将错误码存在errno中
fol = open("file.txt", O_CREAT | O_EXCL, 00750);
if (fol == -1) {
// 读取变量errno中的的值,并打印
perror("文件打开失败"); // 文件打开是不:File exists
// 有时候也需要使用 char *strerror(int errnum); 函数,有些函数的错误码并不保存在errno中,
// 而是通过返回值返回,就只能使用strerror函数了。
exit(1);
}
return 0;
}
读写文件
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> /** open */
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> /** close */
/**
* @brief 关闭文件
*
* @param fol
* @return int
*/
int closeFile(int fol) {
int closeFlag = close(fol);
if (closeFlag == -1) {
printf("关闭文件失败");
exit(1);
}
printf("关闭文件成功\n");
return 0;
}
void toString(char *p) {
printf("%s\n", p);
}
int main(int argvLength, char *argv[])
{
int fol;
fol = open("file.txt", O_RDWR);
if (fol == -1) {
perror("打开文件失败");
exit(1);
}
// ssize_t write(int fd, void *buffer, size_t count);
// 写入数据
char str[] = "ABC\nDEF\n";
int len = sizeof(str) / sizeof(char);
write(fol, str, len);
closeFile(fol);
printf("写入内容\n %s \n成功\n", str);
fol = open("file.txt", O_RDWR);
// ssize_t read(int fd, void *buffer, size_t count);
// 读文件
char strBlock[100]; // 定义缓冲区
char *p;
int flag;
while ((flag = read(fol, strBlock, 100)) != 0)
{
if (flag == -1) {
perror("读取文件失败");
exit(1);
}
printf("%s \n", strBlock);
toString(strBlock);
p = strBlock;
printf("%s \n", p);
}
closeFile(fol);
return 0;
}
文件指针操作
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> /** open */
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> /** close */
#include <string.h>
/**
* @brief 关闭文件
*
* @param fol
* @return int
*/
int closeFile(int fol) {
int closeFlag = close(fol);
if (closeFlag == -1) {
printf("关闭文件失败");
exit(1);
}
printf("关闭文件成功\n");
return 0;
}
void toString(char *p) {
printf("%s\n", p);
}
int main(int argvLength, char *argv[])
{
int fd;
char inputStr[100];
fd = open("file.txt", O_RDWR);
if (fd == -1) {
printf("打开文件失败");
return -1;
}
char str[] = "ABCDEF\n";
int len = (sizeof(str) / sizeof(char));
write(fd, str, len);
len = (sizeof(inputStr) / sizeof(char));
printf("定义字段长度为:%d\n", len); // 输出100
printf("定义字段长度为:%lu\n", strlen(inputStr)); // 输出1
printf("请输入内容:");
scanf("%s", inputStr); // 输入 abcdef
// 文件指针操作 off_t lseek(int fd, off_t offset, int whence);
// whence 是参考点 取值范围如下。
// SEEK_SET 文件开始位置
// SEEK_CUR 文件指针当前位置
// SEEK_END 文件的结尾
// lseek(fd, 0, SEEK_SET) // 移动光标到开始位置
// lseek(fd, 0, SEEK_END) // 移动光标到结束位置
// lseek(fd, 0, SEEK_CUR) // 获取当前光标位置
lseek(fd, 0, SEEK_SET); // 将光标移动到开始位置
len = (sizeof(inputStr) / sizeof(char));
printf("输入内容的长度为:%d\n", len); // 输出100
printf("输入内容的长度为:%lu\n", strlen(inputStr)); // 输出6
write(fd, inputStr, len);
char nowStr[len];
lseek(fd, 0, SEEK_SET); // 将光标移动到开始位置 // 读写都要控制光标位置
read(fd, nowStr, len);
toString(nowStr);
closeFile(fd);
return 0;
}
硬链接,软链接,删除链接文件
软链接和硬链接的区别:
- 不能对目录创建硬链接;可以对目录创建软链接,遍历操作会忽略目录的软链接。
- 不能对不同的文件系统创建硬链接;可以跨文件系统创建软链接。
- 不能对不存在的文件创建硬链接;可以对不存在的文件创建软链接。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> /** open */
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> /** close */
#include <string.h>
/**
* @brief 关闭文件
*
* @param fol
* @return int
*/
int closeFile(int fol) {
int closeFlag = close(fol);
if (closeFlag == -1) {
printf("关闭文件失败");
exit(1);
}
printf("关闭文件成功\n");
return 0;
}
int main(int argvLength, char *argv[])
{
int fd;
fd = open("file.txt", O_RDWR | O_CREAT, 00750);
if (fd == -1) {
printf("打开文件失败");
return -1;
}
char str[] = "ABCDEF\n";
int len = (sizeof(str) / sizeof(char));
write(fd, str, len);
// int dup(int oldfd); // copy fd,不需要在open,不够要分开关闭哦
int newfd = dup(fd);
char str1[] = "GHIJKLMN\n";
len = (sizeof(str1) / sizeof(char));
write(newfd, str1, len);
closeFile(newfd);
closeFile(fd);
// int symlink(const char *oldPath, const char *newPath);
// 创建一个符号链接(软链接),成功返回0,失败返回-1,
// 用 ls -al 查看 显示 file1.txt -> ./file.txt
symlink("./file.txt", "./file1.txt");
// int link(const char *oldPath, const char *newPath); // 创建硬链接
symlink("./file.txt", "./file2.txt");
/**
* 区别:不能对目录创建硬链接;可以对目录创建软链接,遍历操作会忽略目录的软链接。
* 不能对不同的文件系统创建硬链接;可以跨文件系统创建软链接。
* 不能对不存在的文件创建硬链接;可以对不存在的文件创建软链接。
*/
// int unlink(const char *filename);
// 成功返回0,失败返回-1,,由于文件的硬链接是使用多个文件名来引用同一个数据块,
// 因此unlink函数实质上是将文件连接数减一,连接数为0时,才真正将文件删除
unlink("./file1.txt");
return 0;
}
文件目录新建和删除
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /*包含相关函数头文件*/
#include <fcntl.h>
#include <sys/stat.h>
int main(int argc, char **argv) {
// int rmdir(const char *) 删除文件, 只能删除空文件夹
int deleteResult = rmdir("abc");
if (deleteResult == -1) {
perror("删除文件夹失败");
exit(1);
}
// S_IRUSR 读
// S_IXUSR 执行
// S_IWUSR 写
// drwx------
// int result = mkdir("abcd", S_IRUSR | S_IXUSR | S_IWUSR);
// drwxr-x---
int result = mkdir("abcd", 00750);
if (result == -1) {
perror("创建文件目录失败\n");
exit(1);
}
printf("创建文件目录完成\n");
return 0;
}
目录操作
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /*包含相关函数头文件*/
#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
int main(int argc, char **argv) {
// 切换目录
// int chdir(const char *path);
chdir("/");
// 获取当前目录
// buf缓冲区指针,size_t 缓冲区大小,如果缓冲区不够大会返回NULL,并设置错误码ERANGE
// char *getcwd(char *buf, size_t size);
char __dirname[1024];
char *tempDirname = getcwd(__dirname, sizeof __dirname);
if (tempDirname == NULL) {
perror("获取当前目录失败");
exit(1);
} else {
printf("%s\n", tempDirname); // /Users/root/test
printf("%s\n", __dirname); // /Users/root/test
}
// DIR *opendir(const char *name); 打开文件目录
// int closedir(DIR *dir); // 关闭文件目录
DIR *dir;
struct dirent *dirp;
dir = opendir(argv[1]);
if (dir == NULL) {
perror("打开文件夹失败");
exit(1);
}
printf("打开文件成功\n");
// struct dirent {
// ino_t d_ino; /**索引节点编号*/
// ff_t d_off; /**记录的位移*/
// signed short int d_reclen; /**记录的长度*/
// unsigned char d_type; /**文件的类型*/
// har d_name[256]; /**文件名*/
// }
while ((dirp = readdir(dir)) != NULL) {
if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) {
// continue; // 跳过父目录,和自身
}
if (dirp->d_type == DT_DIR) {
printf("<directory> %s\n", dirp->d_name);
} else {
printf("%s\n", dirp->d_name);
}
}
closedir(dir);
return 0;
}
获取文件属性
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /*包含相关函数头文件*/
#include <sys/stat.h>
// struct stat {
// dev_t st_dev; /*设备编号*/
// int_t st_ino; /*索引节点*/
// mode_t st_mode; /*文件的类型和访问权限*/
// nlink_t st_nlink; /*连接到文件的硬连接个数,文件新创建时为1*/
// uid_t st_uid; /*文件的uid*/
// gid_t st_gid; /*文件的gid*/
// dev_t st_rdev; /*设备类型*/
// off_t st_size; /*文件的大小*/
// unsigned long st_blksize; /*文件系统I/O缓冲区大小*/
// unsigned long st_blocks; /*占用块的个数*/
// time_t st_atime; /*上一次访问文件的时间*/
// time_t st_mtime; /*上一次修改文件的时间*/
// time_t st_ctime; /*上一次修改文件属性的时间*/
// }
/* st_mode
S_IFSOCK 套接字
S_IFLNK 符号连接
S_IFREG 普通文件
S_IFBLK 块设备文件
S_IFDIR 目录文件
S_IFCHR 字符设备文件
S_IFIFO 管道文件
*/
/* 判断一个文件的类型可以通过 (st_mode & IFSOCK) == 0
S_ISSOCK(st_mode) 判断文件是否为套接字
S_ISLINK(st_mode) 判断文件是否为符号连接
S_ISREG(st_mode) 判断文件是否为普通文件
S_ISBLK(st_mode) 判断文件是否为块设备文件
S_ISDIR(st_mode) 判断文件是否为目录文件
S_ISCHR(st_mode) 判断文件是否为字符设备文件
S_IFIFO(st_mode) 判断文件是否为管道文件
*/
int main(int argc, char **argv) {
struct stat sta;
if (argc != 2) {
printf("请输入参数");
exit(1);
}
// int access(const char *filename, int mode);
// mode 为 R_OK W_OK X_OK 分别表示可读,可写,可执行
// F_OK 表示文件存在
if (access(argv[1], F_OK) != -1) {
if (access(argv[1], R_OK) != -1) {
printf("文件可以被读取\n");
}
if (access(argv[1], W_OK) != -1)
{
printf("文件可以被写入\n");
}
if (access(argv[1], X_OK) != -1)
{
printf("文件可以被执行\n");
}
} else {
printf("文件不存在!!");
exit(1);
}
// 获取文件属性
// int stat(const char *filename, struct stat *buf);
int fd = stat(argv[1], &sta);
// int fstat(int fd, struct stat *buf); 和 stat功能一致,只是如此不一样,fd为以打开的文件描述符
// open函数也可以返回文件描述符
printf("文件大小:%lld Byte\n", sta.st_size);
// 输出文件类型
switch(sta.st_mode & S_IFMT) {
case S_IFSOCK:
printf("套接字\n");
break;
case S_IFLNK:
printf("符号连接\n");
break;
case S_IFREG:
printf("普通文件\n");
break;
case S_IFBLK:
printf("块设备文件\n");
break;
case S_IFDIR:
printf("目录文件\n");
break;
case S_IFCHR:
printf("字符设备文件\n");
break;
case S_IFIFO:
printf("管道文件\n");
break;
}
return 0;
}
修改文件属性,访问权限,属主,属组
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> /*包含相关函数的头文件*/
int main(int argc, char **argv) {
int result = chmod("./text.txt", 00777);
if (result == -1) {
perror("修改文件权限失败");
exit(1);
}
printf("修改文件权限成功");
// int chown(const char *path, uid_t owner, gid_t group); // 修改用户属主和属组,成功返回0,失败返回-1
// int utime(const char *filename, struct utimebuf *buf); // 修改文件访问时间与修改时间,成功返回0,失败返回-1
// 更改正在使用的文件的属性,有以下三种形式
// int fcntl(int fd, int cmd);
// int fcntl(int fd, int cmd, long arg);
// int fcntl(int fd, int cmd, struct flock *lock);
return 0;
}
标准输入输出流
字符读取,字符写入
FILE fopen(const char filename, const char modes);
int fgetc(FILE fp);
int fputc(int c, FILE fp);
void rewind(FILE fp);
int fseek(FILE *fp, long offset, int whence);
#include <stdio.h>
#include <stdlib.h>
int main()
{
// FILE *fopen(const char *filename, const char *modes);
// modes = "r" | "w" | "a" | "r+" | "w+" | "a+"
// "r" 只读,文件必须存在
// "w" 写,文件不存在的话,创建文件,文件存在则替换文件原有内容
// "a" 在文件末尾追加,如果不存在的话,创建文件
// "r+" 读和写,文件必须存在
// "w+" 读和写,文件不存在创建文件,文件存在替换文件原有内容
// "a+" 读和追加,如果不存在则创建文件
FILE *fp;
FILE *fpw;
fp = fopen("./text.txt", "r+");
fpw = fopen("./text_w.txt", "r+");
if (fp == NULL) {
perror("打开文件失败!");
exit(1);
}
if (fpw == NULL)
{
perror("打开文件失败!");
exit(1);
}
printf("文件打开成功\n");
int c;
// 读
// int fgetc(FILE *fp) 从文件中读取一个字符
// stdin 表示输入流
// int fgetc(stdin) 等价于 int getchar();
// getchar函数是从标准输入流中读取一个字符
// 写
// int fputc(int c, FILE *fp); 向指定文件写入一个字符
// stdout 表示输出流
// int fputc(c, stdout) 等价于 int putchar(int c);
// putchar函数是向标准输出流中写入一个字节
// void rewind(FILE *fp); 重设读写的位置,将读写位置移动到开始位置,
// int fseek(FILE *fp, long offset, int whence); 和lseek的用法一致
// fseek(fp, 0, SEEK_SET) // 移动光标到开始位置
// fseek(fp, 0, SEEK_END) // 移动光标到结束位置
// fseek(fp, 0, SEEK_CUR) // 获取当前光标位置
// long ftell(*fp); 返回当前读写位置
while ((c = fgetc(fp)) != EOF) {
printf("%d %c\n", c, (char)c);
fputc(c, fpw);
}
fclose(fp);
fclose(fpw);
return 0;
}
缓冲区设置
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
fp = fopen("text.txt", "a+");
if (fp == NULL)
{
perror("打开文件失败!");
exit(1);
}
int c;
// 设置缓冲区属性
// int setvbuf(FILE *fp, char *buf, int mode, size_t size);
// mode: _IOFBF,_IOLBF,_IONBF 对应全缓冲,行缓冲,无缓冲
// 全缓冲,缓冲区被填满后才执行输入输出操作
// 行缓冲,填入换行符时,执行输入输出操作
// 无缓冲,不对数据进行缓冲
// (1) setvbuf(fp, NULL, _IONBF, 0); // 设置无缓冲
// char str[10];
// (2)setvbuf(fp, str, _IOFBF, 10); // 设置全缓冲
// (3)setvbuf(fp, NULL, _IOLBF, 0); // 设置行缓冲
// setbuf方法buf设置为NULL会变成无缓冲,否则为全缓冲,缓冲区大小由stdio.h中的常量BUFSIZE决定,
// 默认情况为512字节
// int setbuf(FILE *fp, char *buf);
// setbuffer如果buf为NULL,缓冲区将被设置成无缓冲,否则为全缓冲,大小由size决定
// int setbuffer(FILE *fp, char *buf, size_t size);
// 设置行缓冲等价于setvbuf(fp, NULL, _IOLBF, 0);
// int setlinebuf(FILE *fp);
while ((c = getchar()) != '0')
{
printf("%c", (char)c);
fputc(c, fp);
// 将缓冲区数据,写入磁盘或终端,如果不调用这个的话,
// 在程序未结束前或缓冲区未满前,不做写入操作
// int fflush(FILE *fp); // 将缓冲区数据,写入磁盘或终端
// int fpurge(FILE *fp); // 清空缓存区,丢弃
// fflush(fp);
}
fclose(fp);
return 0;
}
字符串读取,字符串写入
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
FILE *fp1;
fp = fopen("text.txt", "r+");
fp1 = fopen("text.txt", "a+");
if (fp == NULL || fp1 == NULL)
{
perror("打开文件失败!");
exit(1);
}
// int fputs(const char *s, FILE *fp);
fputs("今天是一个好天气", fp1);
fflush(fp1);
// char *fgets(char *s, int n, FILE *fp);
int size = 256;
char buffer[size];
// fgets(buffer, size, fp) != NULL
// int feof(FILE *fp); 测试是否到文件尾。
while (!feof(fp)) {
fgets(buffer, size, fp);
printf("%s", buffer);
}
printf("\n");
fclose(fp);
return 0;
}
读写数据块
#include <stdio.h>
#include <stdlib.h>
#define LEN 3
struct student {
int id;
int score;
};
int read()
{
struct student array[LEN];
FILE *fp;
// DAT是流格式: DAT是是数据流格式
fp = fopen("./text.dat", "r");
if (fp == NULL)
{
perror("打开文件失败!");
exit(1);
}
// 读取数据块
// size_t fread(void *ptr, size_t size, size_t n, FILE * fp);
int num = 0;
num = fread(array, sizeof(struct student), LEN, fp);
if (num != LEN) {
if (feof(fp)) {
printf("读取文件结束!");
} else {
printf("读取文件失败!");
}
}
int i = 0;
for (; i < LEN; i++) {
printf("id=%d, score=%d\n", array[i].id, array[i].score);
}
fclose(fp);
return 0;
}
int write()
{
struct student array[LEN];
FILE *fp;
// DAT是流格式: DAT是是数据流格式
fp = fopen("./text.dat", "w");
if (fp == NULL)
{
perror("打开文件失败!");
exit(1);
}
int i = 0;
for (; i < LEN; i++)
{
printf("id:");
scanf("%d", &array[i].id);
printf("分数:");
scanf("%d", &array[i].score);
printf("\n");
}
// 写入数据块
// size_t fread(void *ptr, size_t size, size_t n, FILE * fp);
int sum = 0;
sum = fwrite(array, sizeof(struct student), LEN, fp);
if (sum != LEN)
{
printf("写入失败");
exit(1);
}
fclose(fp);
return 0;
}
int main() {
// 数据块的读取和写入
write();
read();
return 0;
}
格式化输入输出
int printf(const char format, …);
int scanf(const char format, …);
int fprintf(FILE fp, const char format, …);
int fscanf(FILE fp, const char format, …);
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
// 定义可变参数函数
int myprintf(char *format, ...) {
// int vfprintf(FILE *fp, const char *format, va_list ap);
// int vprintf(const char *format, va_list ap);
// int vfscanf(FILE *fp, const char *format, va_list ap);
// int vscanf(const char *format, va_list ap);
// 宏 <stdarg.h>
// va_list
// va_start
// va_arg
// va_end
va_list vp;
int n;
va_start(vp, format);
n = vprintf(format, vp);
va_end(vp);
return n;
}
int main() {
// 格式化输入输出
// int fprintf(FILE *fp, const char *format, ...);
// stdout 输出流
// fprintf(stdout, const char *format, ...) 等价于 int printf(const char *format, ...);
// int fscanf(FILE *fp, const char *format, ...);
// stdin 输入流
// fscanf(stdin, const char *format, ...) 等价于 int scanf(const char *format, ...);
FILE *fp;
fp = fopen("./text.txt", "w");
if (fp == NULL) {
printf("打开文件失败!");
exit(1);
}
int i = 99;
fprintf(fp, "i = %d\n", i);
myprintf("%d ,%d\n", i, i);
fclose(fp);
return 0;
}