小何讲Linux: 基本文件操作和实例

文件操作的基本概念参见博客: 小何讲Linux: 底层文件I/O操作

1.  函数说明

  • open()函数:是用于打开或创建文件,在打开或创建文件时可以指定文件的属性及用户的权限等各种参数。

    所谓打开文件实质上是在进程与文件之间建立起一种连接,而“文件描述符”唯一地标识着这样一个连接

  • close()函数:是用于关闭一个被打开的文件。当一个进程终止时,所有被它打开的文件都由内核自动关闭,很多程序都使用这一功能而不显示地关闭一个文件。
  • read()函数:是用于将从指定的文件描述符中读出的数据放到缓存区中,并返回实际读入的字节数。若返回0,则表示没有数据可读,即已达到文件尾。读操作从文件的当前指针位置开始。当从终端设备文件中读出数据时,通常一次最多读一行。
  • write()函数:是用于向打开的文件写数据,写操作从文件的当前指针位置开始。对磁盘文件进行写操作,若磁盘已满或超出该文件的长度,则write()函数返回失败。
  • lseek()函数:是将文件指针定位到相应的位置。它只能用在可定位(可随机访问)文件操作中。管道、套接字和大部分字符设备文件是不可定位的,所以在这些文件的操作中无法使用lseek()调用。

2.  open()函数语法要点

所需头文件

#include <sys/types.h> /* 提供类型pid_t 的定义*/

#include <sys/stat.h>    /*记录文件状态头文件*/

#include <fcntl.h>         /*文件的控制,文件访问方式,读写权限的改变*/

函数原型

int open(const char *pathname, int flags, int perms)

在操作文件之前,首先必须打开文件。open函数的打开原理就是将进程files_struct结构体和文件对象file相关联。

函数原型

int open(const char *pathname, int flags, int perms)

pathname :被打开的文件名(可包括路径名)。

flags :文件打开的方式(用下列一个或多个常数进行或运算构成定义,这些常数在fcntl.h 中定义)

O_RDONLY :以只读方式打开文件

O_WRONLY:以只写方式打开文件

O_RDWR:      以读写方式打开文件

O_CREAT:如果该文件不存在,就创建一个新的文件,并用第三个参数为其设置权限

O_EXCL:如果使用O_CREAT时文件已存在,则返回错误消息。这一参数可测试文件是否存在。此时open是原子操作,防止多个进程同时创建同一个文件

O_NOCTTY:使用本参数时,若文件为终端,则不将此设备分配作为此进程的控制终端

O_TRUNC:若文件已经存在,那么会删除文件中的全部原有数据,并且设置文件大小为0。

O_APPEND:以添加方式打开文件,在打开文件的同时,文件指针指向文件末尾,即将写入的数据添加到文件的末尾。

O_NONBLOCK 如果pathname指的是一个FIFO、一个块特殊文件或一个字符特殊文件,则该选项将此文件的本次打开操作和后续的I/O操作设置非阻塞方式。

O_SYNC 使每次write都等到物理I/O操作完成

flag参数可通过“| ”组合构成,但前3个标志常量(O_RDONLY、O_WRONLY 以及O_RDWR)不能相互组合。

perms被创建文件的存取权限(仅当创建新文件时才使用)

可以用一组宏定义:S_I(R/W/X)(USR/GRP/OTH)

其中R/W/X分别表示读/写/执行权限

USR/GRP/OTH分别表示文件所有者/文件所属组/其他用户

perms 是文件的存取权限,既可以用宏定义表示法,也可以用八进制表示法。

例如,S_IRUSR | S_IWUSR表示设置文件所有者的可读可写属性。八进制表示法中600也表示同样的权限

S_IRWXU-设置文件所有者具有全部权限。

函数返回值

成功:返回文件描述符(返回的文件描述符一定是最小的未用描述符数字)

失败:-1

3.  close()函数语法要点

所需头文件

#include <unistd.h>

函数原型

int close(int fd)

函数输入值

fd:文件描述符

函数返回值

0:  成功

-1:出错

4.  read()函数语法要点

所需头文件:#include <unistd.h>

函数原型:ssize_t read(int fd, void *buf, size_t count)

参数:

fd:文件描述符

buf:指向存放读出数据的缓冲区的指针

count:指定读出的字节数

函数返回值

成功:读到的字节数

0:已到达文件尾

-1:出错(如以非阻塞方式打开的文件上无数据可读时)

注意:

  • 有多种情况可使实际读到的字节数少于要求读的字节数:

  • 读普通文件时,在读到要求字节数之前已到达了文件尾端。例如,若在到达文件尾端之前还有30个字节,而要求读100个字节,则read返回30,下一次再调用read时,它将返回0 (文件尾端)。

  • 当从终端设备读时,通常一次最多读一行。

  • 当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。

  • 某些面向记录的设备,例如磁带,一次最多返回一个记录。

  • 读操作从文件的当前位移量处开始,在成功返回之后,该位移量增加实际读得的字节数。

5.  write()函数语法要点

所需头文件:#include <unistd.h>

函数原型:ssize_t write(int fd, void *buf, size_t count)

参数:

fd:文件描述符

buf:指向存放待写入数据的缓冲区的指针

count:指定希望读出的字节数

函数返回值

成功:已写的字节数

出错:-1

在写普通文件时,写操作从文件的当前指针位置开始。

6.  lseek()函数语法要点

每个打开文件都有一个与其相关联的“当前文件位移量”。它是一个非负整数,对应从文件开始处计算的字节数,通常,读、写操作都从当前文件位移量处开始,并使位移量增加所读或写的字节数。系统默认:当打开一个文件时,除非指定O_APPEND选择项,否则该位移量被设置为0。

所需头文件

#include <unistd.h>

#include <sys/types.h>

函数原型:off_t lseek(int fd, off_t offset, int whence)

参数

fd:文件描述符

offset:偏移量,需要移动的距离,单位是字节,可正可负(向前移,向后移)

函数原型off_t lseek(int fd, off_t offset, int whence)

参数:

whence:基准位置

  • SEEK_SET:基准位置为文件的开头,新位置为偏移量的大小

  • SEEK_CUR:基准位置为文件指针的当前位置,新位置为当前位置加上偏移量

  • SEEK_END:基准位置为文件的结尾,新位置为文件的大小加上偏移量的大小

函数返回值

成功:文件的当前位移,该位移量用于下一个读或写操作。

出错:-1

lseek操作并不引起任何I/O操作,只是修改内核中的记录(修改的是已打开文件对象的f_pos字段)

7.  实例基本功能:

从一个文件(源文件)中读取最后10KB数据并到另一个文件(目标文件);

在实例中源文件是以只读方式打开;

目标文件是以只写方式打开(可以是读写方式);

若目标文件不存在,可以创建并设置权限的初始值为644,即文件所有者可读可写,文件所属组和其他用户只能读。

/*将文件src_file中的后10个字节的数据拷贝到dest_file文件中去,前提是src_file中已经准备好了数据*/

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

#define BUFFER_SIZE 15 	/* 每次读写缓存大小,影响运行效率*/
#define SRC_FILE_NAME "src_file" 	/* 源文件名*/
#define DEST_FILE_NAME "dest_file" 	/* 目标文件名文件名*/
#define OFFSET 10 		  /* 复制的数据大小*/

int main()
{
	int src_file, dest_file;
	unsigned char buff[BUFFER_SIZE];
	int real_read_len;	

	/* 以只读方式打开源文件*/
	src_file = open(SRC_FILE_NAME, O_RDONLY);
	if (src_file < 0 )
	{
		printf("SRC_FILE  Open  error\n");
		exit(1);
	}

	/* 以只写方式打开目标文件,若此文件不存在则创建该文件, 访问权限值为644 */
	dest_file = open(DEST_FILE_NAME,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);

	if (dest_file < 0)
	{
		printf("DEST_FILE_NAME Open error\n");
		exit(1);
	}

	/* 将源文件的读写指针移到最后10KB的起始位置*/
	lseek(src_file, -OFFSET, SEEK_END);
	/* 读取源文件的最后10KB数据并写到目标文件中,每次读写1KB */
	while ((real_read_len = read(src_file, buff, sizeof(buff))) > 0)
	{
		write(dest_file, buff, real_read_len);
	}

	close(dest_file);
	close(src_file);

	return 0;
}

首先编写源文件,在源文件中输入一串字符:(大于10个字节)

在终端中编译运行源程序:

在终端中使用cat命令输出目标文件中的内容:

打印变量real_read_len,显示的是10个字节:

读者可以看见,此处只从源文件拷贝了9个字节的内容到目标文件,我觉得应该是文件末尾的结束符eof占了一个字节,所以导致只显示了9个字节的数据,文件结束符eof为不可打印字符,未显示出来。

本人学识浅薄,如果大家知道其中的原因,还望不惜赐教。

时间: 2024-10-12 07:46:10

小何讲Linux: 基本文件操作和实例的相关文章

qt ui程序使用Linux的文件操作open、close (转)

原文地址:qt ui程序使用Linux的文件操作open.close 作者:kjpioo 提出这个问题是因为在qt的QWidget类型的对象中,close()函数会和QWidget::close()冲突,如果在类函数实现时直接用close(),在程序编译时会提示提示错误(具体什么错误不记得了). 错误原因是QWidget::close()与stdio.h中的文件关闭标准函数close()产生了歧义.所以可以参考下文链接中的解决方案. http://bytes.com/topic/c/answer

Linux删除文件夹命令实例

linux删除文件夹命令 在用Linux的时分,有时分要删除一个文件夹,常常会提示次此文件非空,没法删除,这个时分,必需运用rm -rf命令.关于一些小白用户常常在运用Linux命令,会十分当心,以免搞出一些事情,下面小编将教细致教大家如何运用linux命令删除文件夹,需求的请珍藏. linux删除文件夹命令实例: rm -rf /var/log/httpd/access 将会删除/var/log/httpd/access目录以及其下所有文件.文件夹 linux删除文件命令实例: rm -f /

C#使用iTextSharp封装的PDF文件操作类实例

本文实例讲述了C#使用iTextSharp封装的PDF文件操作类.分享给大家供大家参考.具体分析如下: 这个C#代码主要讲iTextSharp中用于操作PDF文件的方法进行了再次封装,可以更加方便的访问PDF文档,可以动态生成PDF文件.添加内容.设置段落.设置字体等. using System.IO; using iTextSharp.text; using iTextSharp.text.pdf; namespace DotNet.Utilities { /// <summary> ///

C#封装的常用文件操作类实例

本文实例讲述了C#封装的常用文件操作类.分享给大家供大家参考.具体如下: 这个C#类封装了我们经常能用到的文件操作方法,包括读写文件.获取文件扩展名.复制文件.追加内容到文件.删除文件.移动文件.创建目录.递归删除文件及目录.列目录.列文件等,不可多得. using System; using System.Text; using System.Web; using System.IO; namespace DotNet.Utilities { public class FileOperate

Linux C 文件操作 -- 系统调用(open(),read()...) 和 标准I/O库(fopen(),fread()...)

一.什么是文件 在讲述文件操作之前,我们首先要知道什么是文件.看到这个问题你可能会感觉到可笑,因为对于用过计算机的人来说,文件是最简单不过的概念了,例如一个文本是一个文件,一个work文档是一个文件等.但是在Linux中,文件的概念还远不止于这些,在Linux中,一切(或几乎一切)都是文件.文件包括很多的内容,例如:大家知道的普通文件是文件,目录也是一个文件,设备也是一个文件,管道也是一个文件等等.对于目录.设备这些的操作也可以完全等同于对纯文本文件的操作,这也是Linux非常成功的特性之一吧.

linux程序设计——文件操作(第三章)

第三章    文件操作 3.1 linux文件结构 与UNIX一样,linux环境中的文件具有特别重要的意义,因为它们为操作系统服务和设备提供了一个简单而一致的接口.在linux中,一切都是文件. 这意味着,通常程序可以像使用文件那样使用磁盘文件.串行口.打印机等等. 目录也是文件,但它是一种特殊类型的文件.在现代UNIX(包括linux)版本中,即使是超级用户可能也不再被允许直接对目录进行写左操作了.所有用户通常都使用上层的opendir/readdir接口来读取目录,而无需了解特定系统中目录

【大话QT之五】Windows与Linux下文件操作监控的实现

一.需求分析: 随着渲染业务的不断进行,数据传输渐渐成为影响业务时间最大的因素.究其原因就是因为数据传输耗费较长的时间.于是,依托于渲染业务的网盘开发逐渐成为迫切需要解决的需求.该网盘的实现和当前市场上网盘实现有一些的不同,主要在客户端与服务器端的操作需要双向进行,即:用户在客户端的操作需要及时同步到服务器端:在服务器端作业渲染生成的文件要及时同步到客户端.即:用户不在需要单独的下载数据,而是在作业运行的同时,渲染就过就会自动同步到客户端,大大缩短了等待时间.当然,无论是在客户端还是在服务端都面

【Linux】文件操作系统调用

一. 文件描述符 在Linux下使用文件描述符来表示设备文件和普通文件.文件描述符是一个整型的数据,所有对文件的操作都通过文件描述符实现.文件描述符的范围是0~OPEN_MAX,系统中有3个已经分配的文件描述符,即标准输入.标准输出.和标准错误,他们的文件描述符的值分别为0.1.2. 文件描述符是文件系统中连接用户空间和内核空间的枢纽.当打开一个或者创建一个文件时,内核空间创建相应的结构,并生成一个整型的变量传递给用户空间的对应进程,进程用这个文件描述符来对文件进行操作. 二. 打开.创建文件o

Windows与Linux下文件操作监控的实现

一.需求分析: 随着渲染业务的不断进行,数据传输渐渐成为影响业务时间最大的因素.究其原因就是因为数据传输耗费较长的时间.于是,依托于渲染业务的网盘开发逐渐成为迫切需要解决的需求.该网盘的实现和当前市场上网盘实现有一些的不同,主要在客户端与服务器端的操作需要双向进行,即:用户在客户端的操作需要及时同步到服务器端:在服务器端作业渲染生成的文件要及时同步到客户端.即:用户不在需要单独的下载数据,而是在作业运行的同时,渲染就过就会自动同步到客户端,大大缩短了等待时间.当然,无论是在客户端还是在服务端都面