C++笔记--Linux编程-linux文件和输入输出 文件和目录操作

Posted xiangjai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++笔记--Linux编程-linux文件和输入输出 文件和目录操作相关的知识,希望对你有一定的参考价值。

目录

Linux文件概念

Linux系统上的文件部分类型说明

文件描述符

使用文件描述符

打开和关闭文件描述符

示例

读写文件描述符

read函数例子

write函数例子

使用fstat获取文件信息

文件和目录操作

库函数和系统调用

打开和关闭文件

mode说明

读写文件

fread函数例子

fwrite函数例子

格式化输入和输出调用

fprintf函数例子

fscanf函数例子

行输入和输出调用

fgets函数例子

fputs函数例子

文件删除和改名

writelog函数

remove函数例子

rename函数例子

找到当前目录

获得目录列表

获取目录列表例子


Linux文件概念

Linux系统上的文件部分类型说明

普通文件。

        就是储存到磁盘上大家所操作的各种数据文件;

管道文件。

        是一个从一端发送数据,从另一端接收数据的通道;

目录

        也叫目录文件,是包含了保存在目录中文件的列表;

设备文件

        是一种特殊文件,提供了大多数物理设备的接口;

符号链接

        包含了到另一个人文件的连接,类似于windows的快捷方式;

套接口

        套接口更像管道文件,但可以让处于不同机器上的进程通讯

文件描述符

        文件描述符是个很小的正整数,它是一个索引值,指向内核为每个进程所维护的该进程打开文件的记录表。

        例如:每个进程启动时都打开3个文件:

                标准输入文件(stdin)

                标准输出(stdout)

                标准出错(stderr)

        这三个文件分别对应文件描述符0、1、2,实际上,你可能已经用过基于描述的I/O操作,但却没有意识到。编程中应该使用<unistd.h>中定义的STDIN_FILENO、 STDOUT_FILENO、 STDERR_FILENO代替数字0、1、2

        说明:

        基于文件描述符的I/O操作兼容POSIX标准,所以移植性比较好。 许多Linux、Unix系统都依赖于文件描述符。 尤其是TCP/IP操作只能通过文件描述符执行输入输出。 在Linux上几乎每样东西都是一个文件。 这样大量资源,比如内存,磁盘空间,进程间通讯,声卡,鼠标都有了一个统一的编程接口。

使用文件描述符

打开和关闭文件描述符

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int open(const char *pathname, int flags);
int close(int fd);

1. open试图打开参数pathname中的一个文件(引入#include <fcntl.h>)

2. 参数flags指定访问该文件的方式。

3. 必须把flags设置为O_RDONLY、O_WRONLY、O_RDWR、O_CREAT、O_APPEND分别表示只读、只写、读写、如果文件不存在就创建、追加。

4. open成功后会返回一个文件描述符。

5. open失败后会返回-1,并设置errno变量(需引入#include "errno.h")

示例

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

int main()
{
	char s[] = "abc.txt";
	int fd = open(s, O_RDONLY);
	if (fd == -1)
	{
		printf("error is %s\\n", strerror(errno));		
	}
	else
	{
		printf("success fd=%d\\n", fd);
	}
	return 0;
}

open试图打开一个不存在的文件,返回-1。

如果想知道更加详细的错误描述,请使用errno和strerror函数

在一个文件描述符用完后一定要用close()函数关闭它,这样才能保证该进程对文件所有加的锁全部被释放

读写文件描述符

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

read用于从文件描述符对应的文件读取数据,调用成功返回读出的字节数(引入#include<unistd.h>)

参数fd必须是用open调用返回的有效文件描述符。

参数buf为读出数据的缓冲区,count指定读出的字节数。

成功返回读取字节数,如果遇到EOF,返回0,出错返回-1

read函数例子

int main()
{
	char s[] = "abc.txt";
	int fd = open(s, O_RDONLY);
	if (fd == -1)
	{
		printf("error is %s\\n", strerror(errno));
	} else
	{
		printf("success fd=%d\\n", fd);
		char buf[100];
		memset(buf, 0, sizeof(buf));
		int i = read(fd, buf, sizeof(buf));
		printf("%s\\n", buf);
		close(fd);
	}
	return 0;
}

write函数例子

int main()
{
	char s[] = "abc.txt";
	int fd = open(s, O_RDWR | O_APPEND);
	if (fd == -1)
	{
		printf("error is %s\\n", strerror(errno));		
	}
	else
	{
		printf("success fd=%d\\n", fd);
		char buf[100];
		memset(buf, 0, sizeof(buf));
		strcpy(buf, “hello world\\n");
		int i = write(fd, buf, strlen(buf));
		close(fd);	
	}
	return 0;

使用fstat获取文件信息

int fstat(int fd, struct stat *buf)

参数fd必须是用open调用返回的有效文件描述符。

使用stat获取文件信息。

int stat(const char *path, struct stat *buf);

参数path是路径加文件名的字符串(引入#include "sys/stat.h")

Struct stat定义如下:

struct stat {
              dev_t     st_dev;     /* ID of device containing file */
              ino_t     st_ino;     /* inode number */
              mode_t    st_mode;    /* protection */
              nlink_t   st_nlink;   /* number of hard links */
              uid_t     st_uid;     /* user ID of owner */
              gid_t     st_gid;     /* group ID of owner */
              dev_t     st_rdev;    /* device ID (if special file) */
              off_t     st_size;    /* total size, in bytes */
              blksize_t st_blksize; /* blocksize for filesystem I/O */
              blkcnt_t  st_blocks;  /* number of blocks allocated */
              time_t    st_atime;   /* time of last access */
              time_t    st_mtime;   /* time of last modification */
              time_t    st_ctime;   /* time of last status change */
          };

 为了正确解释文件类型,有一套宏能够计算stat接口的st_mod成员。              


              S_ISREG(m)  is it a regular file?
              S_ISDIR(m)  directory?
              S_ISCHR(m)  character device?
              S_ISBLK(m)  block device?
              S_ISFIFO(m) FIFO (named pipe)?
              S_ISLNK(m)  symbolic link? (Not in POSIX.1-1996.)
              S_ISSOCK(m) socket? (Not in POSIX.1-1996.)

fstat函数例子

int main()
{
	char s[] = "abc.txt";
	int fd = open(s, O_RDONLY);
	if (fd == -1)
	{
		printf("error is %s\\n", strerror(errno));
	}
	else
	{
		printf("success\\n");
		struct stat buf;
		fstat(fd, &buf);
		if (S_ISREG(buf.st_mode))
		{
			printf("%s is charfile\\n", s);
		}
		close(fd);
	}
	return 0;
}

stat函数例子

int main()
{
        struct stat t;
        memset(&t, 0, sizeof(t));
        if (stat("a.txt", &t) == 0)
        {
                printf("%d\\n", t.st_size);
        }
        else
        {
                printf("open failed %s\\n", strerror(errno));
        }
        return 0;
}

文件和目录操作

库函数和系统调用

本内容介绍的函数是库函数,而不是系统调用

库函数和系统调用的区别在于系统调用能够让你直接访问linux内核提供的服务,比如上面的函数就是基于系统调用的函数

系统调用函数存在与内核空间,库函数都是用户模式,所以系统调用不当可能会破坏系统,但库函数调用风险就要小很多。

库函数对I/O操作进行缓冲,减少了系统调用开销,同时可移植性也更好。

打开和关闭文件

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

int fclose(FILE *stream);

fopen以mode模式打开名为path的文件

fopen返回一个文件指针。

出现错误,fopen返回NULL,并把errno设置为恰当的值。

mode说明

         r      Open text file for reading.  The stream is positioned at the beginning of the file.        

         r+     Open for reading and writing.  The stream is positioned at the beginning of the file.                w      Truncate  file  to  zero  length or create text file for writing.  The stream is positioned at the  beginning of the file.        

         w+     Open for reading and writing.  The file is created if it does not exist,  otherwise  it  is  trun-cated.  The stream is positioned at the beginning of the file.        

          a      Open  for  appending  (writing  at  end  of file).  The file is created if it does not exist.  The  stream is positioned at the end of the file.        

           a+    Open for reading and appending (writing at end of file).  The file  is  created  if  it  does  not  exist.   The  initial  file  position  for  reading is at the beginning of the file, but output is               always appended to the end of the file.

读写文件

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);

参数说明:

        1.参数ptr指向缓冲区保存或读取的数据。

        2.参数size控制记录大小。

        3.参数nmemb为记录数。

        4.函数返回读取或回写的记录数

fread函数例子

int main()
{
	char s[] = "abc.txt";
	FILE *p = fopen(s, "r+");
	if (p == NULL)
	{
		printf("error is %s\\n", strerror(errno));
	}
	else
	{
		printf("success\\n");
		char buf[100];
		memset(buf, 0, sizeof(buf));
		fread(buf,sizeof(buf),1, p);
		printf("%s\\n", buf);
		fclose(p);
	}
	return 0;
}

fwrite函数例子

int main()
{
	char s[] = "abc.txt";
	FILE *p = fopen(s, "r+");
	if (p == NULL)
	{
		printf("error is %s\\n", strerror(errno));
	}
	else
	{
		printf("success\\n");
		char buf[100];
		memset(buf, 0, sizeof(buf));
		sprintf(buf, "hello world\\n", "%s");
		fwrite(buf,strlen(buf),1, p);
		fclose(p);
	}
	return 0;
}

格式化输入和输出调用

int fprintf(FILE *stream, const char *fromat,…);
int fscanf(FILE *stream, const char *fromat,…);

fprintf函数例子

int main()
{
	char s[] = "abc.txt";
	FILE *p = fopen(s, "r+");
	if (p == NULL)
	{
		printf("error is %s\\n", strerror(errno));
	}
	else
	{
		printf("success\\n");
		char buf[100];
		memset(buf, 0, sizeof(buf));
		sprintf(buf, "hello world");
		fprintf(p, "%s\\n", buf);
		fclose(p);
	}
	return 0;
}

fscanf函数例子

int main()
{
	char s[] = "abc.txt";
	FILE *p = fopen(s, "r+");
	if (p == NULL)
	{
		printf("error is %s\\n", strerror(errno));
	}
	else
	{
		printf("success\\n");
		char buf[100];
		memset(buf, 0, sizeof(buf));
		while (fscanf(p, "%s", buf) != EOF)
		{
			printf("%s\\n", buf);
		}
		fclose(p);
	}
	return 0;
}

行输入和输出调用

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

fgets从文件中读取一行,返回EOF代表文件结尾。

fputs向文件中写入一行

fgets函数例子

int main()
{
	char s[] = "abc.txt";
	FILE *p = fopen(s, "r+");
	if (p == NULL)
	{
		printf("error is %s\\n", strerror(errno));
	}
	else
	{
		printf("success\\n");
		char buf[100];
		memset(buf, 0, sizeof(buf));
		while (fgets(buf, sizeof(buf),p) != NULL)
		{
			printf("%s", buf);
		}
		fclose(p);
	}
	return 0;
}

fputs函数例子

int main()
{
	char s[] = "abc.txt";
	FILE *p = fopen(s, "a+");
	if (p == NULL)
	{
		printf("error is %s\\n", strerror(errno));
	}
	else
	{
		printf("success\\n");
		char buf[100];
		memset(buf, 0, sizeof(buf));
		sprintf(buf, “hello world\\n");
		fputs(buf, p);
		fclose(p);
	}
	return 0;
}

文件删除和改名

int remove(const char *pathname);
int rename(const char *oldpath, const char *newpath);

remove函数删除pathname指向的文件名。

Rename函数修改文件名称。

执行成功返回0,失败返回-1,错误码保存在变量errno中

writelog函数

程序在运行过程中有时需要记录log,writelog函数例子

void writelog(const char *log)
{
	time_t tDate;
	struct tm *eventTime;
	time(&tDate);
	eventTime = localtime(&tDate);
	int iYear = eventTime->tm_year + 1900;
	int iMon = eventTime->tm_mon + 1;
	int iDay = eventTime->tm_mday;
	int iHour = eventTime->tm_hour;
	int iMin = eventTime->tm_min;
	int iSec = eventTime->tm_sec;
	char sDate[16];
	sprintf(sDate, "%04d-%02d-%02d", iYear, iMon, iDay);
	char sTime[16];
	sprintf(sTime, "%02d:%02d:%02d", iHour, iMin, iSec);
	char s[1024];
	sprintf(s, "%s %s %s\\n", sDate, sTime, log);
	FILE *fd = fopen("my.log", "a+");
	fputs(s, fd);
	fclose(fd);

remove函数例子

int main()
{
	char s[] = "abc.txt";
	int i = remove(s);
	if (i == -1)
	{
		printf("error is %s\\n", strerror(errno));
	}
	else
	{
		printf("success\\n");
	}
	return 0;
}

rename函数例子

int main()
{
	char s[] = "abc.txt";
	int i = rename(s,"aaa.txt");
	if (i == -1)
	{
		printf("error is %s\\n", strerror(errno));
	}
	else
	{
		printf("success\\n");
	}
	return 0;
}

找到当前目录

char *getcwd(char *buf,size_t size);

getcwd函数把当前工作目录的绝对路径名复制到buf中,size指示buf的大小。

如果buf不够大,不能装下整个路径名,getcwd返回NULL

获得目录列表

用opendir函数打开目录文件

用readdir函数读出目录文件内容

 用closedir函数关闭目录文件

这些函数都在<dirent.h>中声明

DIR *opendir(const char *pathname);
struct dirent *readdir(DIR *dir);
int closedir(DIR *dir);

Opendir函数打开pathname指向的目录文件,如果错误返NULL

获取目录列表例子

int main(int argc, char *argv[])
{
	if (argc < 2)
		return 0;
	DIR *dp;
	struct dirent *dirp;
	dp = opendir(argv[1]);
	if (dp == NULL)
	{
		printf("error is %s\\n", strerror(errno));
		return 0;
	}
	while((dirp = readdir(dp)) != NULL)
	{
		printf("%s\\n", dirp->d_name);
	}
	closedir(dp);
	return 0;
}

以上是关于C++笔记--Linux编程-linux文件和输入输出 文件和目录操作的主要内容,如果未能解决你的问题,请参考以下文章

C++笔记--Linux编程(11)-进程通信

C++笔记--Linux编程-gcc gbb make

C++笔记--Linux编程(14)-线程同步

C++笔记--Linux编程(12)-信号

C++笔记--Linux编程(13)-守护进程-线程

Linux用vim进行C++编程的配置和操作入门