栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

文件I/O

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

文件I/O

文件概念:一组相关数据的有序集合

文件类型:常规文件r

 目录文件d

 字符设备文件 c

 块设备文件 b

 管道文件 p

 套接字文件 s

 符号链接文件 L

标准I/O由ANSI C标准定义,主流操作系统上都实现了C库。标准I/O通过缓冲机制减少系统调用,实现更高的效率。

标准I/O用一个结构体类型来存放打开的文件的相关信息。标准I/O的所有操作都是围绕FILE来进行的

流(stream)FILE又被称为流(stream),文本流/二进制流

Windows

二进制流: 换行符< >’n’

文本流:   换行符< >’r’,’n’

Linux

换行符< >’n’

全缓冲(当流的缓冲区无数据或无空间时才执行实际I/O操作)

行缓冲(当在输入和输出中遇到换行符(‘n’)时,进行I/O操作。当流和一个终端关联时,典型的行缓冲)

无缓冲(数据直接写入文件,流不进行缓冲)

流的缓冲类型:stdin / stdout /stddir

Stdin/stdout默认时行缓冲

Stderr没有缓冲

写代码显示缓冲取大小

fopen()创建的文件访问权限是0666(rw-rw-rw-)

Linux系统中umask设定会影响文件的访问权限,其规则为(0666&~umask)

Root用户是022普通用户是002

用户可以通过umask函数或者命令修改相关设定

errno存放错误号,由系统生成

perror先输出字符串s,再输出错误号对应的错误信息

Strerror根据错误号返回对应的错误信息

Fclose()调用成功返回0,失败返回EOF,并设置errno

流关闭时自动刷新缓冲中的数据并释放缓冲区

当一个程序正常终止时,所有打开的流都会被关闭

流一旦被关闭后就不能执行任何操作。

程序中能够打开的文件或流的个数有限制

流支持不同的读写方式:

字符输入和输出:

读写一个字符:fgetc()/fputc()一次读/写一个字符

读写一行:fgets()和fputs()一次读/写一行

读写若干个对象:fread()/fwrite()每次读/写若干个对象,而每个对象具有相同的长度。

行输入和输出:

Char *gets(char *s);

Char *fgets(char *s,int size,FILE *stream);

成功时返回s,到文件末尾或出错时返回NULL。

Gets不推荐使用,容易造成缓冲区溢出

遇到’n’或已输入size-1个字符时返回,总是包含’

Int puts(const char *s);

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

成功时返回输出的字符个数;出错时返回EOF

Puts将缓冲区s中的字符串输入到stdout,并追加’n’

fputs将缓冲区s中的字符串输出到stream,不追加’n’

Size_t fread(void *ptr,size_t size,size_t n,FILE *fp);

Size_t fwrite(const void *ptr,size_t size,size_t n,FILE *fp);

成功返回读写的对象个数;出错时返回EOF。既可以读写文本文件,也可以读写数据文件效率高。

Int fflush(FILE *fp);

成功时返回0;出错时返回EOF

将流缓冲区中的数据写入实际的文件

Linux下只能刷新输出缓冲区,输入缓冲区丢弃

Long ftell(FILE *stream);

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

Void rewind(FILE *stream);

Ftell()成功时返回流的当前读写位置,出错时返回EOF

Fseek()定位一个流,成功时返回0,出错时返回EOF

Whence参数:SEEK_SET/SEEK_CUR/SEEK_END;

offset参数:偏移量,可正可负

Rewind()将流定位到文件开始位置

读写流时,当前读写位置自动后移

Int ferror(FILE *stream);

Int feof(FILE *stream);

Ferror()返回1表示流出错;否则返回0

Feof()返回1表示文件已到末尾;否则返回0

Int printf(const char *fmt,...);

Int fprintf(FILE *stream,const char *fmt,...);

Int sprintf(char *s,const char *fmt,...);

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

格式化输入:

Int fscanf(FILE *stream,const char *format,...);

Int sscanf(const char *str,const char *format,...);

Time()用来获取系统时间(秒数)

Localtime()将系统时间转换成本地时间

Sleep()实现程序睡眠

什么是文件I/O?

Posix(可移植操作系统接口)定义的一组函数

不提供缓冲机制,每次读写操作都引起系统调用

核心概念是文件描述符

访问各种类型文件

Linux下,标准IO基于文件IO实现

每个打开的文件都对应一个文件描述符

文件描述符是一个非负整数。Linux为程序中每个打开的文件分配一个文件描述符

文件描述符从0开始分配,依次递增

文件IO操作通过文件描述符来完成

Open函数用来创建或打开一个文件:

#include

Int open(const char *path,int oflag,...);

成功时返回文件描述符;出错时返回EOF

打开文件时使用两个参数

创建文件时第三个参数指定新文件的权限

只能打开设备文件

Close函数用来关闭一个打开的文件:

#include

Int close(int fd);

成功时返回0;出错时返回EOF

程序结束时自动关闭所有打开的文件

文件关闭后,文件描述符不再代表文件

read函数用来从文件中读取数据:

#include

Ssize_t read(int fd,void *buf,size_t count);

成功时返回实际读取的字节数;出错时返回EOF;

读到文件末尾时返回0;

Buf是接收数据的缓冲区

Count不应超过buf大小

Write函数用来向文件写入数据:

#include

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

成功时返回实际写入的字节数;出错时返回EOF

Buf是发送数据的缓冲区

Count不应超过buf大小

Lseek函数用来定位文件

#include

Off_t lseek(int fd,off_t offser,intt whence);

成功时返回当前的文件读写位置;出错时返回EOF

参数offset和参数whence同fseek完全一样

访问目录-opendir

Opendir函数用来打开一个目录文件:

#include

DIR *opendir(const char *name)

DIR是用来描述一个打开的目录文件的结构体类型

成功时返回目录流指针;出错时返回NULL

访问目录-readdir

Readdir函数用来读取目录流中的内容:

#include

Struct dirent *readdir(DIR *dirp)

Struct dirent是用来描述目录流中一个目录项的结构体类型

包含成员char d_name[256] 参考帮助文档

成功时返回目录流dirp中下一个目录项

出错或到末尾时返回NULL

访问目录-closedir

Closedir函数用来关闭一个目录文件:

#include

Int closedir(DIR *dirp)

成功时返回0,出错时返回EOF

修改文件访问权限-chmod/fchmod

Chmod/fchmod函数用来修改文件的访问权限:

#include

Int chmod(const char *path,mode_t mode);

Int fchmod(int fd,mode_t mode);

成功时返回0;出错时返回EOF

Root和文件所有者能修改文件的访问权限

获取文件属性-stat/lstat/fstat

Stat/lstat/fstat函数用来获取文件属性:

#include

Int stat(const chat *path,struct stat *buf);

Int lstat(const char *path,struct stat *buf);

Int fstat(int fd,struct stat *buf);

成功时返回0,出错时返回EOF;

如果path是符号链接stat获取的是目标文件的属性;而lstat获取的是链接文件的属性

文件属性-struct stat

Struct stat是存放文件属性的结构体类型:

Mode_t st_mode:类型和访问权限

Uid_t st_uid;所有者id

Uid_t st_gid;用户组id

Off_t st_size;文件大小

Time_t st_mtime;最后修改时间

库是一个二进制文件,包含的代码可被程序调用

标准C库,数学库,线程库...

库有源码,可下载后编译;也可以直接安装二进制包

/lib /usr/lib

库是实现编译好的,可以复用的代码

在OS上运行的程序基本上都要使用库。使用库可以提高开发效率

Windows和Linux下库文件的格式不兼容

Linux下包含静态库和共享库

编译(链接)时把静态库中相关代码复制到可执行文件中

程序中已包含代码,运行时不再需要静态库

程序运行时无需加载库,运行速度快

占用更多磁盘和内存资源

静态库升级后,程序需要重新编译链接

静态库的创建

  1. 确定库中函数的功能、接口
  2. 编写库源码hello.c

#include

Void hello(void){

Printf(“hello worldn”);

Return;

}

  1. 编译生成目标文件

$gcc -c hello.c -Wall

  1. 创建静态库hello

$ar crs libhello.a hello.o

  1. 查看库中符号信息

$nm libhello.a

链接动态库

编写应用程序test.c

#include

Void hello(void);

Int main(){

Hello();

Return 0;

}

编译test.c并链接静态库libhello.a

$gcc -o test test.c -L. -lhello

$./test

Hello word

共享库的特点

编译(链接)时仅记录用到哪个共享库中的哪个符号,不复制共享库中相关代码

程序不包含库中代码,尺寸小

多个程序可共享同一个库

程序运行时需要加载库

库升级方便,无需重新编译程序

使用更加广泛

共享库创建

  1. 确定库中函数的功能、接口
  2. 编写库源码hello.c bye.c

#include

Void hello(void){

Printf(“hello worldn”);

Return;

}

  1. 编译生成目标文件

$gcc -c -fPIC hello.c bye.c -Wall

创建共享库common

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

为共享库文件创建链接文件

$ln -s libcommon.so.1 libcommon.so

符号链接文件命名规则

Lib<库名>.so

如何找到共享库

为了让系统能找到要加载的共享库,有三种方法:

把库拷贝到/usr/lib和lib目录下

在LD_LIBRARY_PATH环境变量中添加库所在路径

添加/etc/ld.so.conf.d/*.conf文件,执行ldconfig刷新

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/996410.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号