基本文件的输入输出

目录操作

标准I/O函数库

1. 基本文件输入输出

(1) 验证三个已打开的标准输入、标准输出和标准错误输出
// exam6-1.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define BUFSIZ 200
int main() 
{
   char buf[BUFSIZ];
   int n;         
    while((n= read(STDIN_FILENO, buf , BUFSIZ)) > 0) 
       write(STDOUT_FILENO, buf , n); 
   exit(0); 
}

编译执行上述代码

$ gcc -o exam1 exam1.c //编辑并链接
# ./exam1 //执行
(2) 利用基本输入输出函数复制文件
// exam2.c
#include <stdio.h>
#include <fcntl.h>
#define PMODE 0644 // 权限的定义为 rw-r--r--
int  main(int  argc, char *argv[] ){
        int fdin, fdout, n;
        char buf[BUFSIZ];
         if(argc !=3) {
                fprintf(stderr, "Usage: %s filein fileout\n",argv[0]);
                exit(1);
         }
       if((fdin = open(argv[1],O_RDONLY)) == -1) {
                perror(argv[1]);
                exit(2);
        }
        if((fdout = open(argv[2],O_WRONLY | O_CREAT | 
                        O_TRUNC, PMODE)) == -1) {
                perror(argv[2]);
                exit(3);
        }
        
        while((n = read(fdin, buf, BUFSIZ)) > 0)
                write(fdout,buf, n);
        exit(0);
}

编译并执行上述程序

$ gcc -o exam2 exam2.c  //编译并链接
$ ./exam2  exam2.c  exam2.bak  //备份exam2.c文件
(3) 显示文件属性信息
//exam3.c
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
//显示文件类型和文件存取权限
prntmode(struct stat *stbuf)
{
	switch(stbuf->st_mode & S_IFMT) {
	case S_IFDIR:
		printf("directory\t");
		break;
	case S_IFCHR:
		printf("character special file\t");
		printf("special device: %d\t",stbuf->st_rdev);
		break;
	case S_IFBLK:
		printf("block special file\t");
		printf("special device: %d\t",stbuf->st_rdev);
		break;
	case S_IFREG:
		printf("regular file\t");
		break;
	case S_IFIFO:
		printf("named pipe\t");
		break;
	}
	if(stbuf->st_mode & S_ISUID)  printf("setuid\t");
	if(stbuf->st_mode & S_ISGID)  printf("setgid\t");
	if(stbuf->st_mode & S_ISVTX)  printf("sticky\t");
	printf("permissions: %o\n",stbuf->st_mode & 0777);
}
//显示文件的属主用户和用户组
prntuser(struct stat *stbuf)
{
	struct passwd *pw, *getpwuid();
	struct group  *grp,*getgrgid();

	pw = getpwuid(stbuf->st_uid);
	printf("user ID: %d name: %s\t",stbuf->st_uid,pw->pw_name);
	grp = getgrgid(stbuf->st_gid);
	printf("group ID: %d group: %s\n",stbuf->st_gid,grp->gr_name);
}
// 显示文件与时间相关的属性
prntimes(struct stat *stbuf)
{
	char *ctime();

	printf("last access: \t\t%s", ctime(&stbuf->st_atime));
	printf("last modification: \t%s", ctime(&stbuf->st_mtime));
	printf("last status change: \t%s", ctime(&stbuf->st_ctime));
}

main(int argc,char *argv[])
{
	struct stat stbuf;
	if(stat(argv[1],&stbuf) == -1) {
		perror(argv[1]);
		exit(1);
	}
	printf("file name: %s\t\t",argv[1]);
	printf("device: %d\t",stbuf.st_dev);
	printf("i-number: %u\n",stbuf.st_ino);
	prntmode(&stbuf);
	printf("links: %d\t",stbuf.st_nlink);
	printf("file size: %ld\n",stbuf.st_size);
	prntuser(&stbuf);
	prntimes(&stbuf);

	exit(0);
}

编译并运行上述代码

$ gcc -o  exam3  exam3.c //编译并链接
$ ./exam3 exam2.c  //显示文件exam2.c的属性

2. 目录操作

下列程序用于显示当前目录下的所有文件名

// exam4.c
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <dirent.h> 
#include <errno.h>
int  main(int argc, char *argv[])
{
  DIR *dirp;
  struct dirent  *direntp;

if((dirp = opendir(argv[1])) == NULL) {
   fprintf(stderr,"error message: %s\n",strerror(errno)); // 显示错误信息
    exit(1);
  }
while((direntp = readdir(dirp)) != NULL)
   printf("%s\n", direntp->d_name);
closedir(dirp);
exit(0);
}

编译并执行上述代码

$ gcc -o exam4 exam4.c
$ ./exam4

3. 标准I/O函数库

(1) 验证标准I/O函数库的内部缓存机制
//exam5.c
#include <stdio.h>
main()
{
int i;
for (i=0; i<5; i++)
  {
  printf("i=%d ",i);	
  sleep(2);		
  }
}

编译并执行上述代码

$ gcc -o exam5  exam5.c 
# ./exam5 //经过若干秒后显示运行结果
(2) 演示标准I/O函数库与毕本I/O函数间关系
// exam6.c
#include <stdio.h>
int main()
{
    printf("h");
    printf("e");
    printf("l");
    printf("l");
    printf("o");
    printf("\n");
    fflush(stdout);
    exit(0);
}

编译并执行上述代码

$ gcc -o exam6 exam6.c
$ strace exam6  //跟踪最终实现

4. 思考题

(1) 思考pwd命令的实现原理

(2) 标准I/O函数库的特点