IO进、线程——标准IO文件操作和目录流

标准IO

标准IOl利用缓冲机制,减少系统调用,从而提高程序的运行效率。

缓冲区:全缓冲、行缓冲、无缓冲

  • 全缓冲:当缓冲区满的时候后,或者强制刷新缓冲区,这样才会进行实际的IO操作,一般当用户打开普通文件时默认使用全缓冲
  • 行缓冲:当缓冲区满或者遇到换行符‘\0’时,进行实际的IO操作,涉及到的终端相关的IO操作时使用全缓冲。
  • 无缓冲:涉及到标准错误时,使用无缓冲。

一般使用的对象是普通文件。

流 – IO_FILE结构体

文本流:
二进制流:

1、文件操作

文件描述符:系统分配的最小的非分数。

1.1 打开文件——fopen()、freopen()

①fopen()

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

功能:打开文件,并且生成一个流
返回值:成功返回值流指针,失败返回NULL
参数说明
pathname:文件名(包含路径)
mode:打开文件的方式(必须指定读写)
r:只读方式打开
r+:读写
w:文件存在则清空,文件不存在则创建。只写
w+:文件存在则清空,文件不存在则创建,读写
a:文件存在则在末尾进行写入,不存在则创建
a+:文件存在则在末尾进行写入,不存在则创建,还可以读

注:任何流刚生成时,不会开辟缓冲区,只有在读或者写时才会马上开辟缓冲区

参考代码
#include <stdio.h>

int main() {
    FILE *file;
    file = fopen("example.txt", "w"); // 以写入方式打开文件
    if (file != NULL) {
        fprintf(file, "Hello, World!\n"); // 向文件中写入内容
        fclose(file); // 关闭文件流
        printf("File opened and written successfully.\n");
    } else {
        printf("Failed to open the file.\n");
    }
    return 0;
}

②freopen()

FILE *freopen(const char *pathname, const char *mode, FILE *stream);

功能:重定向一个流,用pathname打开的文件生成的流来替代stream原本的流
返回值:成功返回流指针,失败返回NULL
参数说明
pathname:文件名(包含路径)
mode:打开文件的方式(必须指定读写)

r:只读方式打开
r+:读写
w:文件存在则清空,文件不存在则创建。只写
w+:文件存在则清空,文件不存在则创建,读写
a:文件存在则在末尾进行写入,不存在则创建
a+:文件存在则在末尾近些写入,不存在则创建,还可以读

stream:要替换的流

参考代码
#include <stdio.h>

int main(int argc, char *argv[])
{ 
    FILE* fp = freopen("xxx", "r+",stdout);
    if(fp == NULL){
        return -1;
    }
    printf("hello world\n");

    return 0;
} 

1.2 读写文件——fgetc()、fputc()、fgets()、fputs()、fread()、fwrite()、

①按字节读写——fgetc()、fputc()
int fgetc(FILE *stream);

功能:从流里面读取一个字符
返回值:成功返回实际读到的字符,失败返回-1
参数说明
stream:要读取的流

int fputc(int c, FILE *stream);

功能:往流里面写入一个字符
返回值:成功返回实际写入的字符,失败返回-1
参数说明
c:要写的内容
stream:要写入的流

参考代码
#include <stdio.h>

int main() {
    FILE *file;
    int ch;
    file = fopen("example.txt", "r"); // 以只读方式打开文件
    if (file != NULL) {
        while ((ch = fgetc(file)) != EOF) { // 逐字节读取文件内容
            putchar(ch); // 将读取到的字符打印到控制台
        }
        fclose(file); // 关闭文件流
    } else {
        printf("Failed to open the file.\n");
    }
    return 0;
}
②按行读写——fgets()、fputs()
char *fgets(char *s, int size, FILE *stream);

功能:目标是读取一行内容
返回值:成功返回字符串首地址,失败返回NULL
参数说明
s:用于存放读取到的字符串的缓冲区
size:预计要读多少个字节
stream:要读的流

注:fgets会读size-1个字节,如果在这个范围内读到了换行,那么在后面添加一个’\0’然后结束函数。如果没读到换行,会读取size-1个数据然后添加一个’\0’结束函数

int fputs(const char *s, FILE *stream);

功能:往流里面写入一串数据
返回值:成功返回1,失败返回-1
参数说明
s:要写入的内容所在的缓冲区
stream:要写入的流

参考代码
#include <stdio.h>

int main() {
    FILE *file;
    char buffer[100];

    file = fopen("example.txt", "r"); // 以只读方式打开文件
    if (file != NULL) {
        while (fgets(buffer, sizeof(buffer), file) != NULL) { // 逐行读取文件内容
            printf("%s", buffer); // 将读取到的行打印到控制台
        }
        fclose(file); // 关闭文件流
    } else {
        printf("Failed to open the file.\n");
    }
    return 0;
}
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{ 
    FILE* fp = fopen("xxx","r");
    if(fp == NULL){
        perror("fopen:");
        return -1;
    }    
    char buf[64] = {0};
    memset(buf, '#', sizeof(buf));
    fgets(buf, 5, fp);
    for(int i = 0; i < 64; i++){
        printf("%c", buf[i]);
    }   
    printf("\n");

    return 0;
} 
计算文件的行数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{ 
    if(argc != 2){
        printf("请输入要输入的文件%s\n",argv[0]);
    }

    FILE* fp = fopen(argv[1],"r");
    if(fp == NULL){
        perror("open perror:");
        return -1;
    }
    int count = 0;
    char buf[1024] = {0};
    while(fgets(buf,sizeof(buf),fp)){
        count++;
    }
    printf("%d行\n",count);
    fclose(fp);
    return 0;
} 
fgtes()和fputs()实现copy功能
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{ 
    FILE *fb,*fd;
    if(argc != 3){
        printf("%s <src_file> <dis_file>\n", argv[0]);
    }

    fb = fopen(argv[1],"r");
    if(fb == NULL){
        perror("open fb:");
        return -1;
    }

    fd = fopen(argv[2],"w+");
    if(fd == NULL){
        perror("poen fd:");
        return -1;
    }
        
    char buf[64];
    while(fgets(buf,sizeof(buf),fb) != NULL){
        fputs(buf, fd);
    }
    fclose(fb);
    fclose(fd);

    return 0;
} 
③按对象读写——fread()、fwrite()、
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:从流里面读取nmemb个对象的数据
返回值:成功返回实际读到对象数,失败返回0
参数说明
ptr:要保存内容的缓冲区地址
size:每个对象的字节大小
nmemb:预计要读多少个对象
stream:要读的流

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

功能:往流里面写入nmemb个对象的数据
返回值:成功返回实际写入的对象数,失败返回0
参数说明
ptr:保存要写入的数据的缓冲区
size:每个对象的字节大小
nmemb:预计要写多少个对象
stream:要写的流

参考代码
#include <stdio.h>

struct Student {
    char name[50];
    int age;
};

int main() {
    FILE *file;
    struct Student student;

    file = fopen("example.dat", "wb"); // 以二进制写入方式打开文件
    if (file != NULL) {
        student.age = 20;
        fwrite(&student, sizeof(struct Student), 1, file); // 将学生结构体写入文件
        fclose(file); // 关闭文件流
        printf("Student data written successfully.\n");
    } else {
        printf("Failed to open the file.\n");
    }
    return 0;
}

1.3 文件定位——fseek()

int fseek(FILE *stream, long offset, int whence);

功能:改变文件内的定位
返回值:成功返回0,失败返回-1
参数说明
stream:要操作的流
offset:偏移量,正数往后偏移,负数往前偏移
whence:基准点

SEEK_SET:文件头
SEEK_CUR:文件当前定位
SEEK_END:文件尾

long ftell(FILE *stream);

功能:获取当前文件位置的偏移量
返回值:成功返回当前偏移的量,失败返回-1
参数说明
stream:指定要获取当前文件位置的文件流

参考代码

读取指定位置的字符

#include <stdio.h>

int main() {
    FILE *file;
    char ch;

    file = fopen("example.txt", "r"); // 以只读方式打开文件
    if (file != NULL) {
        fseek(file, 5, SEEK_SET); // 将文件指针定位到文件头后的第5个字节处
        ch = fgetc(file); // 读取第5个字节
        printf("Character at position 5: %c\n", ch);
        fclose(file); // 关闭文件流
    } else {
        printf("Failed to open the file.\n");
    }
    return 0;
}

读取文件的大小

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{ 
    if(argc != 2){ 
        printf("请输入两个文件(可执行文件和要计算字节数文件):%s <file>\n",argv[0]);
    }   
    FILE *fp = fopen(argv[1],"r");
    if(fp == NULL){
        perror("fopen:");
        return -1; 
    }   
    fseek(fp, 0, SEEK_END);//将位置指到文件的末尾,向前偏移0
    int fileSize = ftell(fp);//
    fclose(fp);

    printf("文件大小为:%d 字节\n",fileSize);

    return 0;
} 

2.目录流——opendir()、readdir()

#include <dirent.h>

DIR *opendir(const char *name);

功能:打开一个文件夹,生成一个目录流
返回值:成功返回流指针,失败返回NULL
参数说明
name:要打开的文件夹

读文件——readdir()

struct dirent *readdir(DIR *dirp);

功能:读取一个文件,从打开的文件夹里面读
返回值:成功返回结构体指针,失败返回NULL
参数说明
dirp:打开的目录流

目录中的条目信息

struct dirent {
    ino_t          d_ino;       /* i节点号(inode number)*/
    off_t          d_off;       /* 不是偏移量;详见下文 */
    unsigned short d_reclen;    /* 记录的长度(字节数)*/
    unsigned char  d_type;      /* 文件类型;并非所有文件系统都支持该字段 */
    char           d_name[256]; /* 以空字符('\0')结尾的文件名 */
};

参考代码
#include <stdio.h>
#include <dirent.h>

int main() {
    DIR *dir;
    struct dirent *entry;

    dir = opendir("."); // 打开当前文件夹
    if (dir != NULL) {
        while ((entry = readdir(dir)) != NULL) { // 逐个读取文件夹中的文件信息
            printf("%s\n", entry->d_name); // 打印文件名
        }
        closedir(dir); // 关闭目录流
    } else {
        printf("Failed to open the directory.\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小羊客栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值