1.文件描写叙述符:每次我们打开一个文件,就会得到一个相应于该文件的较小的整数,这个整数就是这个文件的文件描写叙述符。

在shell操作中,0,1,2这三个文件描写叙述附总是打开的。一般是指向shell执行所在的终端。0相应于标准输入,1相应于标准输出,2相应于标准错误。由于0,1,2这三个文件描写叙述符总是打开的。所以一般我们打开一个文件时。该文件所相应的文件描写叙述符为3,再打开一个文件时,新打开的文件描写叙述符为4,以此类推...

举例:

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;
int main()
{
int fd1, fd2, fd3;
fd1 = open("1.txt", O_RDONLY); //open the first file
fd2 = open("2.txt", O_RDONLY); //open the second file
fd3 = open("3.txt", O_RDONLY); //open the third file
cout << fd1 << endl; //the first file describe
cout << fd2 << endl; //the second file describe
cout << fd3 << endl; //the third file describe
return 0;
}

执行结果:

liu@liu:~$ ./fd
3
4
5

通过上述结果。能够得知,新打开的文件的文件描写叙述符从3開始,依次为3,4,5,6...等等。

2.与文件I/O相关最经常使用的系统调用:

open()

write()

read()

close()

详细使用方法使用 man 2 open, man 2 write等详细查看。



3.文件I/O实例:

源代码:

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
using namespace std;
int main()
{
int sourceFd, desFd;
ssize_t sizeRead, sizeWrite;
char buf[80];
sourceFd = open("source.txt", O_RDONLY); //以仅仅读方式打开source.txt
desFd = open("des.txt", O_RDWR|O_TRUNC); //以读写方式打开des.txt,而且清空des.txt中的内容
sizeRead = read(sourceFd, buf, sizeof(buf)); //读取source.txt中的内容
sizeWrite = write(desFd, buf, sizeRead); //将读取的内容写入des.txt中
close(sourceFd);
close(desFd);
}

运行之前:

liu@liu:~$ cat source.txt
......
liu@liu:~$ cat des.txt
......
lllllllll
kkkkkkkkkk

运行之后:

liu@liu:~$ cat source.txt
......
liu@liu:~$ cat des.txt
......

4.文件偏移量

对于每一个打开的文件,系统内核都会记录其文件偏移量,文件偏移量是仅仅下一个read()或write()操作文件的起始     位置。文件偏移量通过lseek()改变或获取。

lseek()并不适用于全部类型的文件,不同意将lseek()应用于管道、FIFO、socket或者终端。

文件空洞:假设程序的文件偏移量已经跨越了文件结尾,从文件结尾到新写入数据间的这段空间被称为文件空洞。

lseek()使用实例:

cur = lseek(fd, 0, SEEK_CUR); //获取当前文件偏移量
lseek(fd, 0, SEEK_SET); //将文件偏移量移到文件开头

lseek()实例:

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
using namespace std;
int main()
{
int fd;
char buffer[10] = "hahaha"; //待写入的字符串
fd = open("source.txt", O_RDWR); //打开source.txt
lseek(fd, 5, SEEK_END); //SEEK_SET表示从头開始定位。10表示向后10位
write(fd, buffer, sizeof(buffer)); //将buffer中的内容写入source.txt中
close(fd);
}

代码运行前:

liu@liu:~$ cat source.txt
fuck you.

代码运行后:

liu@liu:~$ cat source.txt
fuck you.
hahaha

5.以上所述为通用文件I/O操作。除通用I/O操作之外,还有ioctl(),须要用到时自己查阅。

6.原子操作:全部的系统调用都是以原子操作方式运行的。也就是说。在系统调用运行期间。该系统调用不会被其它进程或者线程所中断。

7.设置或获取文件的訪问模式和状态标记:使用fcntl()

实例:

#include <iostream>
#include <unistd.h>
#include <fcntl.h>
using namespace std;
int main()
{
int fd, flags, accessMode;
fd = open("source.txt", O_RDWR); //以可读可写的方式打开source.txt //打开文件失败
if(-1 == fd)
cout << "open file error." << endl; //打开文件成功,通过fcntl获取source.txt的状态标记
flags = fcntl(fd, F_GETFL); //第二个參数设为F_GETFL,表示此时fcntl系统调用用于获取source.txt的状态标记
if(-1 == flags) //获取source.txt的状态标记失败
cout << "can't get the configure of source.txt" << endl;
if(flags & O_SYNC) //假设open source.txt时设置了O_SYNC
cout << "writes are synchronized." << endl;
else //假设open source.txt时没有设置O_SYNC
cout << "writes are not synchronized." << endl; //通过fcntl设置source.txt的訪问模式
accessMode = flags & O_ACCMODE;
if(accessMode == O_WRONLY || accessMode == O_RDWR)
cout << "source.txt is writable." << endl; //通过fcntl设置source.txt的状态标记,此处给sourge.txt加入O_APPEND标记
flags |= O_APPEND;
if(-1 == fcntl(fd, F_SETFL, flags)) //加入O_APPEND状态失败
cout << "config error" << endl;
else //加入O_APPEND状态成功
cout << "add the O_APPEND status success." << endl;
}

运行结果:

liu@liu:~$ ./fcntl1
writes are not synchronized.
source.txt is writable.
add the O_APPEND status success.



7.文件描写叙述符和打开文件之间的关系:

  • 两个不同的文件描写叙述符,若指向同一个打开文件句柄。则共享同一文件偏移量
  • 文件描写叙述符标志(即close-on-exec)为进程和文件描写叙述符全部私有

8.拷贝文件描写叙述符:使用dup(), dup2(), fcntl() 都能够完毕

 

dup使用实例: 

<span style="font-family:SimSun;font-size:14px;">#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
using namespace std;
int main()
{
int oldFd, newFd;
oldFd = open("1.txt", O_RDWR);
newFd = dup(oldFd); //拷贝文件描写叙述符,使oldFd,newFd都指向1.txt
cout << oldFd << " " << newFd << endl;
}</span>

运行结果:

liu@liu:~$ ./dup
3 4

dup2()使用实例:

<span style="font-size:14px;">#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;
int main()
{
int oldFd, newFd;
oldFd = open("1.txt", O_RDWR);
newFd = dup2(oldFd, 10); //拷贝文件描写叙述符为10
cout << "old file describe: " << oldFd << endl;
cout << "new file describe: " << newFd << endl;
}</span>

     执行结果:

liu@liu:~$ ./dup2
old file describe: 3
new file describe: 10

使用fcntl()拷贝文件描写叙述符实例:

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;
int main()
{
int oldFd, newFd;
oldFd = open("1.txt", O_RDWR);
newFd = fcntl(oldFd, F_DUPFD, 12); //拷贝文件描写叙述符,从12開始取最小整数作为文件描写叙述符
cout << "old file describe: " << oldFd << endl;
cout << "new file describe: " << newFd << endl;
}

执行结果:

liu@liu:~$ ./fcntl
old file describe: 3
new file describe: 12

9.在文件特定偏移量处进行读写:使用pread()和pwrite()

   pwrite()使用实例:

<span style="font-size:14px;">#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
using namespace std;
int main()
{
int fd, curPos;
char buf[80] = "i love china.";
fd = open("1.txt", O_RDWR);
curPos = lseek(fd, 0, SEEK_CUR);
cout << curPos << endl; //获取当前位置偏移量
pwrite(fd, buf, sizeof(buf), 50); //在指定位置第50个字节处进行读写
}</span>

执行之前:

<span style="font-family:SimSun;">liu@liu:~$ cat 1.txt
fuck you. what a big fuck!
i love beijing.</span>

    执行之后:

liu@liu:~$ cat 1.txt
fuck you. what a big fuck!
i love beijing.
i love china.

10.分散输入和集中输出:readv()和writev()

     readv()是将一个文件读到几个分散的地方,即读到buf1, buf2处

writev()是将几个分散的地方的内容连续的写到一个文件里去

readv()和writev()使用实例:

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <unistd.h>
using namespace std;
int main()
{
int fd1, fd2;
int wsize, rsize;
char buf1[10], buf2[5];
struct iovec iov[2];
fd1 = open("a.txt", O_RDWR);
if(-1 == fd1)
cout << "open error." << endl; iov[0].iov_base = buf1;
iov[0].iov_len = sizeof(buf1);
iov[1].iov_base = buf2;
iov[1].iov_len = sizeof(buf2); rsize = readv(fd1, iov, 2); //将a.txt中的内容按序分别读出到buf1和buf2中,即buf1中写入a.txt的前10个字符,buf2中写入a.txt接着的5个字符
cout << "read size : " << rsize << endl; //输出从a.txt中读到的字符总数 fd2 = open("b.txt", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
if(fd2 < 0)
cout << "open error." << endl;
wsize = writev(fd2, iov, 2); //将buf1和buf2中的内容写到b.txt中
cout << "write size : " << wsize << endl; close(fd1);
close(fd2);
}

执行结果:

liu@liu:~$ ./readv
read size : 15
write size : 15

11.将文件大小设置为指定的值:truncat(), ftruncate()

原型: int truncate(const char *path, off_t length);

                 int ftruncate(int fd, off_t length);

将文件大小设为 length 指定的值。假设文件的大小比指定的值大,则截去末尾的一部分;假设文件的大小比指定的值小,则在文件加入一系列空字节或一个文件空洞。

12.大文件的读写:

在32位的体系结构中,文件的大小被限定在2GB之内; 然而磁盘驱动器的容量早已超过了这一限制。因此时常有处理超过2GB文件的需求。

处理大文件I/O最经常使用的方法:

在源文件加入

#define _FILE_OFFSET_BITS 64

13.创建暂时文件:mkstemp(), tmpfile()

 

mkdtemp原型: char *mkdtemp(char *template);

为了保证暂时文件名称的唯一,template的最后六位一定要是XXXXXX

maktemp使用实例:

<span style="font-size:14px;">#include <iostream>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
int main()
{
int fd;
char temp[] = "/tmp/somestringXXXXXX";
fd = mkstemp(temp);
if(-1 == fd)
cout << "create template file fail." << endl;
cout << "Generated file name is " << temp << endl
if(-1 == close(fd))
cout << "close fail." << endl;
} </span>

执行结果:

<span style="font-size:14px;">liu@liu:~$ ./temp
Generated file name is /tmp/somestringG5ruj9</span>

tmpfile使用实例:

<span style="font-size:14px;">#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
FILE *temp;
temp = tmpfile();
if(temp)
cout << "template file created." << endl;
else
cout << "template file created fail." << endl;
}</span>

执行结果:

<span style="font-size:18px;">liu@liu:~$ ./temp2
template file created.</span>

Linux----文件I/O的更多相关文章

  1. Linux实战教学笔记08:Linux 文件的属性(上半部分)

    第八节 Linux 文件的属性(上半部分) 标签(空格分隔):Linux实战教学笔记 第1章 Linux中的文件 1.1 文件属性概述(ls -lhi) linux里一切皆文件 Linux系统中的文件 ...

  2. Linux文件查找.md

    Linux 文件查找 在Linux系统的查找相关的命令: which 查看可执行文件的位置 whereis 查看文件的位置 locate 配合数据库查看文件位置 find 实际搜寻硬盘查询文件名称 w ...

  3. Linux 文件压缩与归档

    .note-content { font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeit ...

  4. Linux文件类型

    1.windows系统和Linux系统的区别 windows通过问价扩展名来区分文件类型,例如*.txt是一个文本文件, linux系统文件的扩展名和文件类型没有关系 为了容易区分文件类型,linux ...

  5. 修改linux文件权限

    Linux系统中的每个文件和目录都有访问许可权限,用它来确定谁可以通过何种方式对文件和目录进行访问和操作. 文件或目录的访问权限分为只读,只写和可执行三种.以文件为例,只读权限表示只允许读其内容,而禁 ...

  6. Linux文件和目录权限详细讲解

    转载请标明出处: http://www.cnblogs.com/why168888/p/5965180.html 本文出自:[Edwin博客园] Linux文件和目录权限解读 如何设置Linxu文件和 ...

  7. linux 文件系统结构及命令

    1.linux 文件系统结构 / 根目录 root |--mnt/ | |--sdcard/  挂载点 | |--usb0 | |--cdrom |--home | |--soft01 <- 用 ...

  8. linux 文件权限、类型、命名规则

    文件权限 -rwxr-x--t        文件类型 用户权限 组权限 其他用户权限 umask是一个掩码,设置文件的默认权限,会屏蔽掉不想授予该安全级别的权限,从对象的全权权限中减掉:对文件全权权 ...

  9. linux文件权限查看及修改(实用)

    查看Linux文件的权限:ls -l 文件名称 查看linux文件夹的权限:ls -ld 文件夹名称(所在目录) 修改文件及文件夹权限: sudo chmod -(代表类型)×××(所有者)×××(组 ...

  10. Linux文件权限查看及修改命令chmod

    查看权限 Linux文件访问权限分为可读,可写和可执行三种. 可用ls -l命令查看,例: ls -l或者 ll 显示为 -r--r--r--. 1 root root 21 Jan 5 23:02 ...

随机推荐

  1. HDU5312 Sequence

    题意:t组数据,每组数据给个m.问m最少能由几项形如3*n*(n-1)+1的数表示 eg 7=1(n=1)+1(n=1)+1(n=1)+1(n=1)+1(n=1)+1(n=1)+1(n=1);     ...

  2. 【Linux】apt-get install 怎么阻止弹出框,使用脚本默认自动安装?

    You can do a couple of things for avoiding this. Setting the DEBIAN_FRONTEND variable to noninteract ...

  3. [Functional Programming ADT] Combine Multiple State ADT Based Redux Reducers

    Redux provides a convenient helper for combining many reducers called combineReducer, but it focuses ...

  4. 30个iPhone健康应用帮助你保持身体健康

    来源:GBin1.com 技 术进步的最大缺陷是,现在大部分人花费大量时间在他们的电脑前和移动设备上.他们没有任何时间锻炼和顾及他们的健康.这些科技产品让我们变得慵 懒,甚至 让我们愿意花费闲暇的时间 ...

  5. mysql中select distinct的使用方法

    在使用mysql时,有时须要查询出某个字段不反复的记录,尽管mysql提供有distinct这个keyword来过滤掉多余的反复记录仅仅保留一条,但往往仅仅用它来返回不反复记录的条数,而不是用它来返回 ...

  6. Swift的String与OC的NSString的区别

    Swift的String类型是值类型.如果你创建了一个新的字符串值,那么当其进行常量.变量赋值操作或在函数/方法中传递时,会进行值拷贝. 在不同的情况下,都会对已有字符串值创建新的副本,并对该新副本进 ...

  7. Bootstrap学习 进度条

    本文将介绍Bootstrap进度条,在本文中你将看到如何使用Bootstrap创建加载,重定向或动作状态的进度条 bootstrap进度条使用CSS3过渡和动画来获得该效果.Internet Expl ...

  8. PHP连接Azure Redis

    概述 Azure Redis缓存基于流行的开源Redis缓存,可以通过各种Redis客户端进行访问,这些客户端适用于许多编程语言.每个客户端有自身的API,用于通过Redis命令调用Redis缓存实例 ...

  9. C#7.0之元组数据

    static (string,string,string) LookupName(int a) { return ("","",""); } ...

  10. linux 环境下git的安装与配置

    git是一个分布式的版本控制工具 1.安装git相关的依赖 yum install curl-devel expat-devel gettext-devel openssl-devel zlib-de ...