2015-12-27 13:51:56 qq_29422251 阅读数 328

3.1打开文件

3.1.1 函数名

fopen

3.1.2 函数原形

FILE *fopen(const char *path, const char*mode) 

//path 和 mode 都是字符串,因此要加双引号,例如:

fopen(“/home/test.txt”, “w+”)

3.1.3 函数功能

打开文件

3.1.4 所属头文件

<stdio.h>

3.1.5 返回值

成功:返回文件指针  失败:返回0

3.1.6 参数说明

path:指定打开的文件名字(含路径)

mode:文件打开模式 r r+ w w+ a a+

w+:如果文件存在,则被清空,如果文件不存在,则创建新文件


 3.2关闭文件

3.2.1 函数名

fclose

3.2.2 函数原形

int fclose(FILE *fp )

3.2.3 函数功能

关闭文件

3.2.4 所属头文件

<stdio.h>

3.2.5 返回值

成功:0  失败:EOF

3.2.6 参数说明

fp:待关闭的文件的指针


3.3读文件

3.3.1 函数名

fread

3.3.2 函数原形

size_t fread(void  *ptr,size_t  size, size_t  nmemb,FIFL  *stream)

3.3.3 函数功能

从文件中读取数据

3.3.4 所属头文件

<stdio.h>

3.3.5 返回值

成功:返回成功读取到的数据量  失败:返回0

3.3.6 参数说明

steram:待读取的文件

ptr:指向读取出来后的数据的保存位置

nmemb:读取的数据块数

size:每块数据的大小

每块大小为size字节,最后读取到的字节数为nmemb * size


3.4写文件

3.4.1 函数名

fwrite

3.4.2 函数原形

size_t fwrite(constvoid *ptr,size_t size,size_t nmemb,FILE * stream)

3.4.3 函数功能

向指定的文件中写入数据

3.4.4 所属头文件

<stdio.h>

3.4.5 返回值

成功:返回成功写入的数据量  失败:0

3.4.6 参数说明

stream:要写入数据的文件指针

ptr:存放要写入文件的数据

nmemb:写入的数据块数

size:每块数据的大小

每块大小为size字节,最后读取到的字节数为nmemb * size


3.5定位文件

3.5.1 函数名

fseek

3.5.2 函数原形

int fseek(FILE *stream, long offset, intwhence)

3.5.3 函数功能

设置文件内数据的位置指针

3.5.4 所属头文件

<stdio.h>

3.5.5 返回值

成功:返回0  失败:返回-1

3.5.6 参数说明

stream:待定位的文件指针

offset:偏移量

whence:起始位置

  SEEK_SET:起始位置为文件头

  SEEK_CUR:起始位置为当前位置

  SEEK_END:起始位置为文件末尾


2017-06-12 16:48:35 Gouhailiang 阅读数 1079

Linux中,文件有为操作系统和设备提供了一个简单而统一的接口。在Linux中,几乎一切都可以看做文件 。
Linux对文件的操作有两种方式文件IO函数(系统调用)和标准IO库函数调用。系统调用是最直接的方式,库函数调用最终也是通过系统调用实现的。可认为库函数调用是对系统调出于效率考虑而做出的优化。
二者区别:
系统调用是操作系统相关的,因此一般没有跨操作系统的可移植性。
库函数调用是系统无关的,因此可移植性好。标准的IO库函数对文件的操作最终是通过系统调用实现的,但标准io函数库采用缓存技术,减少系统调用的次数。
系统调用通常用于底层文件访问(low-level file access),例如在驱动程序中对设备文件的直接访问。
库函数调用通常用于应用程序中对一般文件的访问。
一、文件IO函数–系统调用
基本函数:

#include<unistd.h>
int open(const char *path, int flags);
-->打开或创建一个文件
int open(const char *path, int flags, mode_t mode );
-->当用于创建文件时需要用第二个函数指明文件的相关权限信息
size_t write(int fd, const void *buf, size_t nbytes);
-->
size_t read(int fd, void *buf, size_t nbytes);
int close(int fd);
off_t lseek(int filedes, off_t offset, int whence);
-->设置读写文件的当前位置
whence有三个参数SEEK_SET/SEEK_CUR/SEEK_END(文件开始/当前/结束位置),则文件的偏移量为设置的whence参数加上offset

二、标准IO库函数

    在基于文件描述符中的底层系统调用的I/O操作中,所有的I/O函数都是针对文件描述符的。当打开一个文件时,即返回一个文件描述符,然后该问价描述符就用于后续的I/O操作。
    在标准I/O库中,所有的I/O操作都是围绕流(stream)来进行的。在Linux中,文件和设备都可以看做是数据流。 
    Linux对一个进程预定义了三个流:标准输入流,标准输出流和标准错误输出流,它们自动地为进程打开并可用。这三个标准I/O流通过在头文件<stdio.h>中预定义的文件指针stdin,stdout和stderr加以引用。它们与文件描述符STDIN_FILENO,STDOUT_FILENO和STDERR_FILENO所表示的标准输入,标准输出和标准错误输出相对应。
     标准I/O库提供了函数fopen用于打开一个流。当打开一个流时,该函数会返回一个指向FILE对象的指针,即文件指针(类型为FILE *)。FILE对象通常是一个结构,它包含了I/O库为管理该流所需要的所有信息:用于实际I/O的文件描述符,指向流缓存的指针,缓存长度,当前在缓存中的字节数,出错标志等。但一般应用程序没有必要关心FILE结构体的各成员值,使用流时,只需要将FILE指针作为参数传递给每个标准I/O函数。 

基本函数:

#include <stdio.h>
FILE *fopen(const char *path, const char *mode);
FILE *fdopen(int fd, const char *mode);-->使一个标准的I/O流与该描述相结合。
FILE *freopen(const char *path, const char *mode, FILE *stream);
-->在指定的流上打开一个指定的文件,此函数一般用于将一个指定的文件打开为预定义的流(如标准输出)。
int flose(FILE *fp);-->关闭流

读写流:
(1)每次一个字符的IO

int getc(FILE *fp);
int fgetc(FILE *fp);
int getchar(void);
/* 上面三个函数的返回值为int,因为EOF常实现为-1,返回int就能与之比较 */

/* 判断出错或者结束 */
int ferror(FILE *fp);
int feof(FILE *fp);
void clearerr(FILE *fp); /* 清除error或者eof标志 */

/* 把字符压送回流 */
int ungetc(intc FILE *fp);

/* 输出 */
int putc(int c, FILE *fp);
int fputc(int c, FILE *fp);
int putchar(int c);

(2)每次一行的IO。

#include <stdio.h>
/* 输入 */
char *fgets(char *restrict buf, int n, FILE *restrict fp);
char *gets(char *buf);
/* gets由于没有指定缓冲区,所以有可能造成缓冲区溢出,要小心 */

/* 输出 */
int fputs(char *restrict buf, FILE *restrict fp);
int puts(const char *buf);

(3)直接IO

#include <stdio.h>
size_t fread(void *restrict ptr, size_t size, size_t nobj,
            FILE *restrict fp);
size_t fwrite(const void *restrict ptr, size_t size, size_t nobj,
            FILE *restrict fp);
/* 返回值:读或写的对象数 */

定位流

long ftell(FILE *fp);
/* 成功则返回当前文件位置指示,出错返回-1L */

int fseek(FILE *fp, long offset, int whence);
/* 成功返回0, 出错返回非0 */

int fgetpos(FILE *restrict fp, fpos_t *restrict pos);
int fsetpos(FILE *fp, fpos_t *pos);
/* 成功返回0,出错返回非0 */

格式化IO

执行格式化输出的主要是4printf 函数:
    printf  输出到标准输出
    fprintf  输出到指定流
    sprintf  输出到指定数组
    snprintf  输出到指定数组并在数组的尾端自动添加一个null字节
格式化输入主要是三个 scanf 函数:
    scanf  从标准输入获取
    fscanf  从指定流获取
    sscanf  从指定数组获取
2015-06-09 09:51:51 huaxiandao 阅读数 466

Linux应用程序学习之库函数方式文件编程

        上一篇我学习的是linux系统调用函数的文件编程,这一篇我们就来说说linux库函数方式文件编程,那系统调用和库函数方式有什么区别吗?前面我们也讲过,系统调用函数是由liunx内核提供的,存在于内核中,而我们的库函数是由外部链接库来提供的,它是基于C函数库独立于操作系统平台的,无论在linux或者windows下,我们都可以使用这些函数,因此采用库函数编程设计可提高程序的可移植性。

在进行linux库函数文件编程我们首选要了解“流”和“文件指针”这一个概念,对于标准的C函数库,它们的操作都是围绕流来进行的,当程序需要读取数据时,就会开启一个通向数据源的流,这个数据源可以是文件,内存或者网络连接。当程序需要写入数据的时候,也会类似开启一个通向目的地的流,总之,数据的读取和写入就像数据在两边流动一样,所以称之为流,如下图形象表明:


 

在前面我们学习系统调用方式来实现文件编程时,我们使用一个文件描述符来表示一个文件,而在库函数方式的文件访问中,我们使用文件指针来指向我们要操作的文件,也就是使用FILE类型来表示一个打开的文件,这个类型中包含了管理文件流的信息。下面我们就来学习一下相关文件编程的C库函数。

与文件编程有关的C库函数我们主要介绍下面五个函数

(1)    打开文件函数:fopen

(2)    关闭文件函数:fclose

(3)    读取文件函数:fread

(4)    写入文件函数:fwrite

(5)    定位文件函数:fseek

有了上一篇的函数学习方法,我们应该很容易去找到相关函数的资料信息了,就是在linux中使用我们的man命令了,具体用法可以参看上一篇。下面我们就来写一个示例程序来了解下这些函数的用法,我会在程序中写上必要的注释。程序如下:



#include <stdio.h>


void main()
{
    FILE *fp;
    FILE *fc;        //定义两个文件指针,
    char buf[10];    //定义一个缓冲数组
    
    //下面就是打开我们的两个文件了,具体参数含义可以在linux man命令查看 
    fp = fopen("/home/share/fun_call/fopen/haha.txt" , "r+");
    fc = fopen("/home/share/fun_call/fopen/copy.txt" , "w+");
    
    
    fread(buf , 1 , 8 , fp);     //读取fp文件指针所指文件中八个字节,我们在该文件中写入1234567890 
    buf[8] = '\0';               
    
    fwrite(buf , 1 , 8  , fc);   //将读取的字节写入fc所指向的文件中
    fseek(fc , 10 , SEEK_SET);   //利用定位函数定位到fc文件中的十字节后面
    fwrite(buf , 1 , 8  , fc);   //再次向其中写入数据
    
    
    printf("the buf is %s \n" , buf); //打印我们的buf
    fclose(fp);
    fclose(fc);
}


下图即为我们程序运行的结果,有关linux库函数方式编程我们就说到这了。

 

   

2016-09-06 16:17:08 PZ0605 阅读数 423


利用库函数操作文件具有跨平台的作用(库函数不随系统平台而变,即不管win还是Linux都适用),而利用Linux 系统调用操作文件,需要考虑平台的兼容性。

库函数 - 读文件

size_t fread(void *ptr, size_t size, size_t n, FILE *stream)

功能:stream指向的文件中读取n个字段,每个字段为size字节,并将读取的数据放入ptr所指向的字符数组中,返回实际已读取的字节数。(读出来的数据量为size*n

 

库函数 - 写文件

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

功能:从缓冲区ptr所指向的数组中把n个字段写到stream指向的文件中,每个字段长为size个字节,返回实际写入的字段数。

 

库函数 - 创建和打开

FILE *fopen(const char *filename, const char *mode)

filename打开的文件名(包含路径,缺省为当前路径)

mode打开模式 

实例代码

[plain] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. root@wl-MS-7673:/home/wl/桌面/c++# cat -n file_lib_copy.cpp   
  2.      1    
  3.      2  #include <stdio.h>  
  4.      3  #include <string.h>  
  5.      4  #include <stdlib.h>  
  6.      5  #define BUFFER_SIZE 1024  
  7.      6    
  8.      7  /*  
  9.      8   * 程序入口  
  10.      9   * */  
  11.     10  int main(int argc,char **argv)  
  12.     11  {  
  13.     12      FILE *from_fd;  
  14.     13      FILE *to_fd;  
  15.     14      long file_len=0;  
  16.     15      char buffer[BUFFER_SIZE];  
  17.     16      char *ptr;  
  18.     17    
  19.     18  /*判断入参*/  
  20.     19  if(argc!=3)  
  21.     20  {  
  22.     21      printf("Usage:%s fromfile tofile\n",argv[0]);  
  23.     22      exit(1);  
  24.     23  }   
  25.     24    
  26.     25  /* 打开源文件 */   
  27.     26  if((from_fd=fopen(argv[1],"rb"))==NULL)   
  28.     27  {   
  29.     28      printf("Open %s Error\n",argv[1]);   
  30.     29      exit(1);   
  31.     30  }   
  32.     31    
  33.     32  /* 创建目的文件 */   
  34.     33  if((to_fd=fopen(argv[2],"wb"))==NULL)   
  35.     34  {   
  36.     35      printf("Open %s Error\n",argv[2]);   
  37.     36      exit(1);   
  38.     37  }   
  39.     38    
  40.     39  /*测得文件大小*/  
  41.     40  fseek(from_fd,0L,SEEK_END);  
  42.     41  file_len=ftell(from_fd);  
  43.     42  fseek(from_fd,0L,SEEK_SET);  
  44.     43  printf("form file size is=%d\n",file_len);  
  45.     44    
  46.     45  /*进行文件拷贝*/  
  47.     46  while(!feof(from_fd))   
  48.     47  {   
  49.     48      fread(buffer,BUFFER_SIZE,1,from_fd);  
  50.     49      if(BUFFER_SIZE>=file_len)  
  51.     50      {  
  52.     51          fwrite(buffer,file_len,1,to_fd);  
  53.     52      }  
  54.     53      else   
  55.     54      {  
  56.     55          fwrite(buffer,BUFFER_SIZE,1,to_fd);  
  57.     56          file_len=file_len-BUFFER_SIZE;  
  58.     57      }  
  59.     58      bzero(buffer,BUFFER_SIZE);  
  60.     59  }   
  61.     60  fclose(from_fd);   
  62.     61  fclose(to_fd);   
  63.     62  exit(0);   
  64.     63  }   
  65.     64    
  66.     65    
  67. root@wl-MS-7673:/home/wl/桌面/c++# g++ file_lib_copy.cpp -o file_lib_copy  
  68. file_lib_copy.cpp: 在函数‘int main(int, char**)’中:  
  69. file_lib_copy.cpp:43:41: 警告: 格式 ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long int’ [-Wformat]  
  70. root@wl-MS-7673:/home/wl/桌面/c++# ./file_lib_copy file_lib_copy.cpp test2.c  
  71. form file size is=1030  
  72. root@wl-MS-7673:/home/wl/桌面/c++#


2020-02-12 18:09:34 sunshine612 阅读数 26

main 函数参数

int main(int argc,charargv[],charenvp[]):

  • argc:整形,传递给main函数的参数列表中参数的个数
  • argv:字符指针数组 传递给main函数的参数列表
  • envp:字符指针数组
    传递给main函数的环境变量

执行进程时,默认给主函数传递一个参数,执行进程的命令
所以argc最小也等于1的

int main(int argc,char*argv[])

传 ./main one two three

argc=4
argv[0]=./main
argv[1]=one
argv[2]=two
argv[3]=three

输出缓冲区:

  • printf 将需要输出的内容写入到输出缓冲区(内存上的一块存储区域)
    将缓冲区中的内容刷新到屏幕上的条件:
    1.遇到"\n"会输出
    2.程序结束
    3.缓冲区满 默认缓冲区大小为1024字节
    4.主动刷新 fflush(stdout)

PS:
_exit(0) 不管缓冲区有没有内容 直接结束
exit(0)
atexit(void (*fun)() );
在main函数结束以前来执行的函数 遇到exit就驱动它 将注册的这些函数执行完才能真正的结束

Linux文件操作:

C语言中文件操作函数:(C语言的库函数)
FILE *fopen(const char *filename,const char *mode);;
int fread(void *buff,int size,int count,FILE *fp);
int fwrite(void *buff,int size,int count,FILE *fp);
fgetc( ) fgetc( ) fgets( ) fputs( )
int fclose(FILE *fp);
int lseek(FILE *fp,int size,int flag)

Linux上文件操作函数:(系统调用函数)

int open(const char *filename,int flag,/int mode/);

返回类型为int类型 第三个参数是可选的

  • filename:文件路径+文件名

  • flag:打开模式 读写

     O_RDONLY     只读打开
     O_WRONLY    写
     O_RDWR        读写
     O_APPEND    追加
     O_CREAT        新建文件(第二个参数是这个的时候才需要第三个参数)
    
  • mode:新建文件时,指定文件的权限

如果设置多个选项,则将其按位或就OK

  • 成功:按返回值大于等于0
  • 失败:返回-1

int read(int rd,void *buff,int len

rd: open打开的文件标识符
buff: 内存上一块缓冲区的起始地址,指定read读到内容的存储位置
len:设置一次最多读取的字节长度,有buff缓存区大小决定—缓冲区的长度-1

  • 成功:返回读到的字节个数,如果返回值0,表示读到文件末尾
  • 失败:返回-1

int write(int rd,void *buff,int len)

buff:要写入的数据的起始地址
len:指定buff中要写入文件中的真实数据长度

  • 成功:大于等于0,表示实际写入的字节长度,由此可以看出是否全部写完了(一般和len一样 但是可能在管道文件等就不一样了)
  • 失败:返回-1

int lseek(int fd,int size,int flag)

操作读写指针
fd:指定操作的文件标识符
size:移动的大小
flag:

  • 相对于首端

    相对于当前

    相对于末端

  1. 欲将读写位置移到文件开头时:lseek(int fildes,0,SEEK_SET);
  2. 欲将读写位置移到文件尾时:lseek(int fildes, 0,SEEK_END);
  3. 想要取得目前文件位置时:lseek(int fildes, 0,SEEK_CUR);

系统调用函数和库函数的比较

在这里插入图片描述系统调用函数:
系统内核将底层管理起来,系统内核抛给外层一些 要实现的接口,这些接口叫做系统调用函数,所以如果我要实现一些功能,就需要调用系统调用函数去实现这些功能.
库函数:
库函数是属于开发语言带的一些东西,应用程序要实现一些功能,可能需要用到库函数
有些库函数会封装系统调用函数 所以库函数有的是在应用层直接可以自己实现的 有些是不得不用到底层的硬件 所以就需要封装系统调用函数

内核态 : 操作系统在运行时内核的形态
用户态: 系统正运行于用户的应用程序下。
就Intel x86架构的CPU来说,一共有0~3四个特权级,0级最高,3级最低,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查,当程序运行在3级特权级上时,就可以称之为运行在用户态,因为这是最低特权级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态;反之,当程序运行在0级特权级上时,就可以称之为运行在内核态。
库函数
调用,执行都在用户态 而且设计的时候会更偏向于人为的认知,有些不需要操作系统内核支持,

系统调用函数
调用在用户态 执行在内核态,会存在用户态切换内核态,它抛出来的接口没有库函数那么容易理解
但是让它干啥就干啥 不多做一件事

所以读取文件数据时 读一次系统调用函数会快一些 但是读多次的话 库函数更快

用户态:
fd = open(); 5
read(fd); 6
如上,每一个系统调用函数都有一个系统调用号
应用程序一旦调用了系统调用号 :

  1. 将调用函数的系统调用号保存到eax寄存器中
  2. 触发0x80中断,中断处理程序开始执行—不同的中断对应不同的中断处理程序 这些程序是在内核里写死了的

内核态:
call [_sys_call_table +eax4]
系统调用中断处理程序,会在系统调用表中查找对应的系统内核函数,在内核态中执行,
例如内核函数的实现:
5号下标 — int sys_open(char
,int,int)
在这里插入图片描述open返回值是PCB中一个成员(数组)的下标,数组的每一项指向一个struct file结构

struct file  ---》   f_mode  f_flag  f_count  f_pos  f_inode

linux C库函数(一)

阅读数 29

linux C库函数(二)

阅读数 16

linux C库函数(三)

阅读数 22

没有更多推荐了,返回首页