Linux 文件IO与标准IO

Linux 文件IO与标准IO

按字符输入输出

fgetc与fputc实现文件复制(出现段错误 (核心已转储))(拷贝的文件 \ 文件尾没有换行符)

#include <stdio.h>
int main(int argc, char *argv[])
{                    // 参数个数,字符指针数组
    FILE *fps, *fpd; // 两个流指针,打开源文件与目标文件
    int ch;//保存读出的字符
    if (argc < 3)//检查命令行参数个数
    {
        printf("Usage : %s < src_file > < dst_file >\n", argv[0]);//正确格式
        return -1;
    }
    if ((fps = fopen(argv[1], "r")) == NULL)//打开源文件,以只读方式“r” //注意括号,关系运算符==比赋值=优先
    {
        perror("fopen src file");
        return -1;
    }
    if ((fps = fopen(argv[2], "w")) == NULL)//打开目标文件
    {
        perror("fopen dst file");
        return -1;
    }
    while ((ch = fgetc(fps)) != EOF)//fgetc函数 > 成功时返回读取字符,文件末尾或者出错返回EOF
    {
        fputc(ch, fpd);
    }
    fclose(fps);
    fclose(fpd);

    return 0;
}

按行输入输出

在这里插入图片描述

与fgetc区别,fgets不能读取二进制文件,只可以读文本(因为fgets把0理解为终止符)

fgets遇到换行符则不会继续读了,会直接在后面追加一个\0,表示字符串结束

没有换行符,最多读取size-1个(最后一个存放\0)

数组名=数组首地址

在这里插入图片描述

结束符不写入流中

成功时返回字符个数,出错时返回EOF

puts 会追加’\n’

如何统计一个文本文件包含多少行?

fgets不能保证每一次都读一行(可能读到的不是完整一行)在数组缓存小的情况下

判断结束符前一个位置是不是换行符

buf[ strlen(buf) -1 ]//strlen 求数组长度 = 结束符下标

按对象输入输出

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);//缓冲区首地址,每个对象占大小,读取多少对象,流指针
//返回值 成功:实际读写对象个数,出错:EOF(-1),读到末尾:0
//既可以读文本,也可以读数据

使用fread与fwrite实现文件复制

#include <stdio.h>

#define N 64 // 定义一个大的缓冲区,用来一次操作多个对象

int main(int argc, char *argv[])
{
    FILE *fps, *fpd;
    char buf[N]; // 存放读出来的对象
    int n;       // 记录每一次实际读取的对象个数
    if (argc < 3)
    {
        printf("Usage: %s <src_file> <dst_file>\n", argv[0]);
        return -1;
    }
    if ((fps = fopen(argv[1], "r")) == NULL)
    {
        perror("fopen src file");
        return -1;
    }
    if ((fpd = fopen(argv[2], "w")) == NULL)
    {
        perror("fopen dst file");
        return -1;
    }
    while ((n = fread(buf, 1, N, fps)) > 0) // N读取多少对象 n实际读取对象个数
    {
        fwrite(buf, 1, n, fpd);
    }
    fclose(fps);
    fclose(fpd);
    return 0;
}

备份文件

 ./fread_fwrite fread_fwrite.c fread_fwrite.c.bak//.bak为备份文件,直接重命名即可使用

比较文件

diff -ruN 第一个文件名 第二个文件名

向流中缓冲区中输出字符串

流fprintf 缓冲区 sprintf

以指定格式"年月日"写入文件和缓冲区

#include <stdio.h>
#include <unistd.h> //sleep
#include <time.h>   //time localtime
#include <string.h>

int main()
{
    FILE *fp;     // 打开文件,定义一个流指针
    int line = 0; // 统计原先多少行
    char buf[64];
    time_t t;
    struct tm *tp;//结构体指针,接收返回值

    if ((fp = fopen("test.txt", "a+")) == NULL)
    {
        perror("fopen");
        return -1;
    }
    while (fgets(buf, 64, fp) != NULL)
    {
        if (buf[strlen(buf) - 1] == '\n')
            line++; // 判断是否读到完整的一行,如果有换行符(在结束符前),表明读到完整一行
    }
    while(1){
        time(&t);
        tp = localtime(&t);

        fprintf(fp,"%02d,%d-%02d-%02d   %02d:%02d:%02d\n", ++line, 
        tp ->tm_year+1900, tp ->tm_mon+1, tp ->tm_mday,tp->tm_hour,tp->tm_min,tp->tm_sec);//行号,年月日时分秒

        fflush (fp);//强制刷新确保字符串从缓冲区写入文件里(默认普通文件打开是全缓冲,流关闭或缓冲区满了或出现换行 或fflush才会刷新)
        sleep(1);//1秒睡眠
        }

    return 0;
}

刷新流(将流缓冲区的数据写入实际文件)

int fflush(FILE *stream);

定位流

int fseek(FILE *stream, long offset, int whence);//offset 基准点 //参数whence
//SEEK_SET/SEEK_CUR当前/SEEK_END
long ftell(FILE *stream);//当前读写位置
void rewind(FILE *stream);//起始位置

判断流出错

ferror ()//判断是否出错,返回1表示出错,否则返回0
feof()//返回1表示文件已到末尾,否则返回0

文件描述符

open

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

//int open ( const char *pathname, int flags );
//参数1: 文件名,可包含路径
//参数2: 打开方式 
// O_RDONLY只读
// O_WRONLY只写
// O_RDWR可读可写
// O_CREAT文件不存在,则创建( 需要第三个参数 )
// O_EXCL,文件存在则出错
// O_APPEND可追加
//返回值: 打开成功返回文件描述符,( 非负整数 )
//int open ( const char *pathname, int flags, mode_t mode );
//参数3 创建文件时指定新的文件的权限

int main(int argc, const char *argv[]) 
//argc (argument count) 参数个数 value 值
{
    int fr = 0;
    fr = open("1.txt", O_RDONLY);
    if (fr < 0)
    {
        perror("open error");
        return -1;
    }
    printf("open sucess\n");//标准输出流是行缓冲的,必须加\n
    return 0;
}

在这里插入图片描述
在这里插入图片描述

动态库的制作

创建静态库(lib开始, .a结束,表示静态库)

库文件名: libhello.a

库名:hello

ar crs libhello.a hello.o

编译(-L指定路径 . 当前目录 -l 加库名,而不是库文件名)

gcc -o hello hello.c -L. -lhello

库中代码必须与位置无关

(1)

gcc -c -Wall -Werror -fPIC hello.c

(2)

gcc -c -fPIC hello hello.c

创建共享库(共享库不能以main为入口)

共享库命名规则(lib+库名.so(表示是一个共享库).1版本)

gcc -shared -o libcommon.so.1 hello.o

为共享库文件创建链接文件(链接文件必须以so结尾)

为了让编译器能找到共享库

ln -s libcommon.so.1 libcommon.so

编译test.c并链接共享库libcommon.so

先链接共享库,再链接静态库,没有–>报错

(若要指定静态库 加上 -static)

gcc -o test test.c -L. -lcommon

在这里插入图片描述

修改系统配置文件,添加库路径,再运行工具,把路径加到系统默认路径里

sudo vi /etc/ld.so.conf.d/my.conf
加入当前库所在路径

在这里插入图片描述

读取这个目录下所有配置文件,把所有路径中的库信息提取出来

sudo ldconfig

静态创建与动态创建

ar crs libhello.a hello.o
gcc -shared -o libcommon.so.1 hello.o

进程创建


#include <sys/types.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{
    pid_t pid  = fork();//创建一个进程
    if (pid < 0){
        perror("fork err\n");
        return -1;
    }
    if (pid > 0){
        printf ("parent process,pid = %d\n", pid);
    }
    else if (pid == 0){
        printf ("chlid process,pid = %d\n", pid);
    }
    return 0;
}

线程

安装pthread_create手册

sudo apt-get install glibc-doc
sudo apt-get install manpages-posix manpages-posix-dev

2个线程,同时操作全局变量

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

int g_count = 0;
// 线程1---------g_count ++
void *thread1(void *arg)
{
    while (1)
    {
        g_count++;
        sleep(1);
        printf("g_count = %d\n", g_count);
    }
}
// 线程1---------g_count --
void *thread2(void *arg)
{
    while (1)
    {
        g_count--;
        sleep(1);
        printf("g_count = %d\n", g_count);
    }
}

int main(int argc, char const *argv[])
{
    char str1[20] = "0123456789";
    char str2[20] = "ABCDEFGHIJ";
    // 创建线程
    pthread_t t1, t2;
    pthread_create(&t1, NULL, thread1, str1);
    pthread_create(&t2, NULL, thread2, str2);
    // 线程资源回收(等待线程退出,回收资源 阻塞)--(线程退出,自动回收(非阻塞)-> pthread_detach())
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值