复习文件管理

 

 

一.系统调用的定义:

操作系统提供给用户的一组“特殊”接口(API);

用户通过这些接口(API)使用内核停供的服务;(用户不能越过接口使用内核服务)

流程:

系统命令 ——>用户编程api——>系统调用内核

注意:linux 将程序空间分为内核空间和用户空间,这样可以更好的保护内核空间。

所以用户一般不允许访问内核空间数据,也不能使用内核函数;只能在用户空间操作用户数据,调用用户函数;

也就是说用户空间有:(系统命令和其他应用程序)在上层,通过用户编程接口api访问底层。

 内核空间在底层靠系统调用接受命令;

linux文件:普通文件,目录文件,链接文件(快捷方式),设备文件;

linux对目录或者对设备操作都是对文件操作

二。文件描述符

当打开一个存在的文件,或者创建一个文件的时候,内核会给进程一个描述符。读和写文件都需要文件描述符;

文件描述符一定是正数。

注意一个进程打开都会启动3个文件:标准输入,标准输出,标准出错处理

 

文件描述符

标准输入

0

STDIN_FILENO 

标准输出

1

STDOUT_FILENO 

标准出错

2

STDERR_FILENO 

man命令:2系统调用 2库函数

三。creat函数:通过man 2creat

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

       int open(const char *pathname, int flags);//   pathname文件名
       int open(const char *pathname, int flags, mode_t mode);
       int creat(const char *pathname, mode_t mode);

找到flags相关的文件,发现这是告诉以什么方式打开文件
  The parameter flags must include one of the following access modes: O_RDONLY, O_WRONLY, or O_RDWR.  These request
       opening the file read-only, write-only, or read/write, respectively.
 

其中:O_RDONLY   只读打开      O_WRONLY   只写打开      O_RDWR     读、写打开,为文件打开方式

    The following symbolic constants are provided for mode:

       S_IRWXU
              00700 user (file owner) has read, write and execute permission  //读  写  执行  许可

       S_IRUSR
              00400 user has read permission

       S_IWUSR
              00200 user has write permission

       S_IXUSR
              00100 user has execute permission

       S_IRWXG
              00070 group has read, write and execute permission

       S_IRGRP
              00040 group has read permission

以上为创建文件的权限

三。返回值:RETURN VALUE
       open() and creat() return the new file descriptor, or -1 if an error occurred (in which case, errno is set appro-
       priately).

可以知道open和creat返回一个文件描述符,如果出错返回-1

 

示例程序:

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

int main()
{
    int ret;

    ret = creat("hello.c", S_IRWXU | S_IRWXG | S_IWGRP);
    if (-1 == ret)    //返回值判断
    {
        perror("creat");//
        exit(1);
    }

    return 0;
}

四。perror函数

 #include <stdio.h>

       void perror(const char *s);//将上一个函数的的错误原因文字描述的字符串打印到平台上
 

open函数:

函数原型:

 

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

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);

pathname是文件名,flags是以什么方式打开,mode是文件具有什么权限

 

示例程序:

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

int main()
{
	int fd, ret;   //file description  文件描述符
	char buf[64] = "helloworldhelloworld";

#if 0
	fd = open("hello.c", O_RDWR);   //以读写方式打开文件hello.c
	if (-1 == fd)
	{
		perror("open");//打印出open的错误
		exit(1);
	}

	close(fd);//关闭文件流
#endif

	fd = open("hello.txt", O_RDWR | O_CREAT, S_IRWXU);  //创建文件xx.c,并且读写方式打开拥有可读可写可执行权限
	if (-1 == fd)
	{
		perror("open");
		exit(1);
	}

	ret = write(fd, buf, strlen(buf));   //buf写入到hello.txt,strlen(len)写入的长度
	if (-1 == ret)
	{
		perror("write");
		exit(1);
	}

	//ret = lseek(fd, -20, SEEK_END);   //相对某个位置移动某个长度
	ret = lseek(fd, 0, SEEK_SET);   //相对某个位置移动某个长度
	if (-1 == ret)
	{
		perror("lseek");
		exit(1);
	}
	
	memset(buf, 0, sizeof(buf));
	ret = read(fd, buf, sizeof(buf));
	if (ret == -1)
	{
		perror("read");
		exit(1);
	}
	printf("read from txt : %s\n", buf);

	close(fd);
		
	return 0;
}

五。write函数

函数原型 :

#include <unistd.h>

       ssize_t write(int fd, const void *buf, size_t count);

write(文件描述符,写的内容,内容的大小);

函数含义:是buf所指的内容写到fd所指的文件中,每次写count的字节数。,文件读写位置也会改变。

返回值:为实际的写的字节数。

六。lseek函数:

int lseek(int fd, offset_t offset,  int whence);

 文件读写指针相对于whence移动“  offset ”个字节

返回文件指针相对于头的位置。

whence可使用下述值:

SEEK_SET:相对文件开头

SEEK_CUR:相对文件读写指针的当前位置

SEEK_END:相对文件末尾

offest 可以取负值表示向前移动。

七。read函数:

定义函数:ssize_t read(int fd, void * buf, size_t count);//读取的内容放入到缓冲区buf中,并读取count的字节数。如果count为0,read会返回0.

使用的头文件:#include <unistd.h>

返回值:错误返回-1 ,成功返回实际读取的字节数,如果读取位置已经在文件内容末尾则返回0.。

所以在使用read时候要先用lseek函数 , 将文件指针(fd)移动到文件开头。

lseek(fd, 0, SEEK_SET);

八。memset函数

头文件:#include <string.h>

函数原型:  void *memset(void *s, int c, size_t n);

void*s可以是指针或者数组,int c是赋给void*s的值 ,size_tn是置位的长度。

一般用于给一个结构体或者数组赋值。当给int c为0或'\0'时。


#include <stdio.h>
#include<string.h>
struct student
{
    char name[20];
    int age;
    int sex;


};
int main()
{
   struct student s1={"hh",4,5};
   struct student s2={"re",6,7};

  printf("%s ,%d ,%d\n",s1.name,s1.age,s1.sex);
  printf("%s,%d,%d\n",s2.name,s2.age,s2.sex);
 memset(&s1,0,sizeof(struct student));
 memset(&s2,0,sizeof(struct student));
  printf("%s ,%d ,%d\n",s1.name,s1.age,s1.sex);
  printf("%s,%d,%d\n",s2.name,s2.age,s2.sex);
  return 0;
}

九:一些程序示例:

1.拷贝文件内容

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

int main(int argc, char *argv[])//argc 是传递参数的个数,argv是指针数组指向每个传递的参数。
{
	int fd_from, fd_to, ret;
	char buf[32] = {0};

	if (argc != 3)    //入参判断
	{
		printf("Input Error!\n");
		exit(1);
	}

	fd_from = open(argv[1], O_RDONLY);  //只读方式打开第一个文件,需要注意的是./文件名或者./a.out也算一个参数放在argv[0]里面
	if (-1 == fd_from)
	{
		perror("open1");
		exit(1);
	}

	fd_to = open(argv[2], O_WRONLY | O_CREAT | O_EXCL, S_IRWXU);  //创建第二个文件,只写方式打开
	if (-1 == fd_to)
	{
		perror("open2");
		exit(1);
	}

	while ((ret = read(fd_from, buf, sizeof(buf) - 1)) > 0)//从fd_from读读sizeof(buf)-1个字节到缓冲区buf中,并返回读到的字节数
	{
		ret = write(fd_to, buf, ret);//调用buf缓冲区的内容写ret个字节到fd_to所指向的文件中
		if (-1 == ret)
		{
			perror("write");
			exit(1);
		}
		memset(buf, 0, sizeof(buf));
	}

	close(fd_from);//
	close(fd_to);//关闭文件描述符

	return 0;
}

2.保存结构体

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

struct Student
{
	char name[20];
	int age;
	char sex;
};

int main()
{
	struct Student s1 = {"aaaa", 20, 'm'};
	struct Student s2 = {"bbbb", 30, 'f'};//对应结构体成员类型赋值,字符串加双引号

	int fd = open("Student.txt", O_WRONLY | O_CREAT | O_EXCL, 0666);//0666对应可读可写可执行 O_EXCL文件已经存在会报错
	if (-1 == fd)
	{
		perror("open");
		exit(1);
	}

	int ret = write(fd, (void *)&s1, sizeof(s1));
	if (-1 == ret)
	{
		perror("write");
		exit(1);
	}

	ret = write(fd, (void *)&s2, sizeof(s1));//将s1 和s2的内容写到fd所指向文件去
	if (-1 == ret)
	{
		perror("write");
		exit(1);
	}

	struct Student s;
	
	fd = open("Student.txt", O_RDONLY);
	if (-1 == fd)
	{
		perror("open");
		exit(1);
	}

	while (1)
	{
		ret = read(fd, (void *)&s, sizeof(s));//读取fd所指向的student.txt中的内容将放入s所对应的结构体中。读取结构体大小的字节
		if (-1 == ret)
		{
			perror("read");
			exit(1);
		}
		if (ret == 0)
		{
			break;
		}
		printf("%s %d %c\n", s.name, s.age, s.sex);
		memset(&s, 0, sizeof(s));//清空结构体内容
	}

	close(fd);
	return 0;
}

十:fread与read的区别---open和fopen的区别--fread函数和fwrite函数的区别

带f的是标准C库文件,后者是Linux系统下的库文件。

也可以fread是由read函数实现的,目的是减少read的调用。

十一:FILE类型的文件

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

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

mode打开模式有:

r,  rb :   只读方式打开,文件必须已存在

w,wb : 只写方式打开,如果文件不存在则创建,   

          如果文 件已存在清空重写

a, ab: 只能在文件末尾追加数据,如果文件不存在则创建

r+,rb+,r+b:      读写方式打开,文件必须已存在

w+,w+b,wb+:  读写方式打开,如果文件不存在则    创建,如果文件已存在清空重写

a+,a+b,ab+:      读和追加方式打开,如果文件不存在则创建

十二。库函数的关闭

头文件:#include<stdio.h>

函数原型:int fclose(FILE * stream);

程序中写fclose(fd)就行

十三。文件长度用c库函数描述

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{	
	FILE *fp;//创建一个文件流

	if (argc != 2)
	{
		printf("Input Error!\n");//如果输入不是./文件名 测试文件名报错
		exit(1);
	}

	fp = fopen(argv[1], "r");//只读方式打开文件必须存在
	if (NULL == fp)
	{
		perror("fopen");
		exit(1);
	}

	fseek(fp, 0, SEEK_END);  //文件指针移动到文件末尾

	int length = ftell(fp);//ftell是文件指针相对当前文件开头的距离,返回值就是文件的长度
	printf("length is %d\n", length);

	fclose(fp);
	return 0;
}

十二:fread函数

size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;

buffer

将读取的内容放入指针buffer所指向的内存中

size

每次读取的字节数

count

读取的次数

stream

文件流或者读取的文件

返回值为读取的次数

十三:fwrite函数

函数原型:size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)

ptr -- 将元素写入ptr所指向的内存空间

size -- 每个元素的大小

nmemb -- 写入的元素的个数

stream -- 文件指针对应的输出流,要写入的文件。

返回值为元素的个数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{	
	FILE *fp;
	int ret;
	char buf[32] = {0};

	fp = fopen("hello.c", "a+");  //读和追加的方式打开hello.c,不存在则创建
	if (NULL == fp)
	{
		perror("fopen");
		exit(1);
	}

	/*ret = fseek(fp, 0, SEEK_SET);    //文件指针移动到文件开头
	if (-1 == ret)
	{
		perror("fseek");
		exit(1);
	}*/

	ret = fread(buf, 1, sizeof(buf), fp);//从fp读取sizeof(buf)个元素,每次写入1字节的大小的元素到buf中
	if (-1 == ret)
	{
		perror("fread");
		exit(1);
	}
	printf("read from txt : %s\n", buf);//输出缓冲区的值

	memset(buf, 0, sizeof(buf));//清空缓冲区的值
	scanf("%s", buf);//输入字符到buf
	ret = fwrite(buf, 1, strlen(buf), fp);//将buf中的内容以一个单元1字节,写入strlen(buf)个元素到fp中
	if (ret < 0)
	{
		perror("fwrite");
		exit(1);
	}

	fclose(fp);

	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值