文件操作

//c语言中的一些文件操作以及文件操作函数

#include <stdio.h>//内有FILE结构体
#include <assert.h>

void FileCopy(const char*des,const char *src)//将src文件的内容拷贝到des文件,src文件可以是文本文件,也可以是二进制文件
{
     FILE *fr = fopen(src,"rb");
     FILE *fw = fopen(des,"wb");
     assert(fr!=NULL && fw!=NULL);

     char buf[1024];
     int len;

      while((len=fread(buf,1,1024,fr))>0)
     {
         fwrite(buf,1,len,fw);//读取多少写多少
      }  

        fclose(fr);
        fclose(fw);
}

int main()
{
	FILE*p, *p1, *p2;

	p = fopen("a.txt", "w+");
	p1 = fopen("a.cpp", "wb+");
	p2 = fopen("b.txt", "w+");

	if (p == NULL || p1 == NULL || p2== NULL)
		printf("Open error!");

	char  buf[128]={"dddkivgfhdhyjfhccfgdddddddddddfefwefew"};
	fwrite(buf,1,20,p);
	
	char res[128]={0};
	int  len1=fread(res,1,25,p);

	printf("len1=%d,%s\n",len1,res);

	fclose(p);
	fclose(p1);
	fclose(p2);
	
	FileCopy("a.cpp","a.txt");
	
	return 0;
}


//补充一个例题并介绍一个好用的函数:将1.txt中的前10个字符重复读取和输出5 次

/*
   fseek函数调用的几个例子:
   (1)移到文件开头的第十个字节后
       fseek (fp,10, SEEK_SET);

   (2)移到文件当前位置的后50个字节处
       fseek (fp,50, SEEK_CUR); 

  (3)移到文件倒数第10个字节处
       fseek (fp,-10, SEEK_END);
*/

按二进制只读方式打开文件;利用fseek将文件位置标记指向文件的结尾;利用ftell获取文件的位置根据返回值就能得到
   FILE *fr = fopen(“1.cpp","rb");
   fseek(fr,0,SEEK_END);
   long sz = ftell(fr);
   printf("该文件一个%ld个字节\n",sz);
   fclose(fr);

强制使文件位置标记指向指定的位置;用ftell函数测定文件位置标记的当前位置,ftell函数的作用是得到流式文件中文件位置标记的当前位置。
   char buf[100] = "";
   FILE *fr = fopen("1.txt","r");
   assert(fr != NULL);
   for(int i=0;i<5;i++)
   {
     fread(buf,sizeof(char),10,fr);
     printf("%s\n",buf);
     memset(buf,0,100);//清空buf
     fseek(fr,0,SEEK_SET);//文件标记跳到开头
   }
   fclose(fr);
*/
//linux下的一些文件操作以及文件操作函数

/*
*描述:利用文件操作函数实现普通文件的拷贝,拷贝的源文件和目标文件由主函数参数传递此处处理四种情况:
*          1 、正常使用 
*          2 、传递的文件是不是同一个文件
*          3 、拷贝的是不是普通文件
*          4 、将文件是否只拷贝一份
*/

/*
  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 file system I/O */ 包含该文件的磁盘块的大小   
    blkcnt_t  st_blocks;  /* number of 512B 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 */ 最后一次改变该文件状态的时间   
 };
    st_mode 的结构:

    st_mode 主要包含了 3 部分信息:

    (1)15-12 位保存文件类型

    (2)11-9 位保存执行文件时设置的信息

    (3)8-0 位保存文件访问权限
	
    S_IFMT   0170000    文件类型的位遮罩
    S_IFSOCK 0140000    套接字
    S_IFLNK 0120000     符号连接
    S_IFREG 0100000     一般文件
    S_IFBLK 0060000     区块装置
    S_IFDIR 0040000     目录
    S_IFCHR 0020000     字符装置
    S_IFIFO 0010000     先进先出
​
    S_ISUID 04000     文件的(set user-id on execution)位
    S_ISGID 02000     文件的(set group-id on execution)位
    S_ISVTX 01000     文件的sticky位
​
    S_IRUSR(S_IREAD) 00400     文件所有者具可读取权限
    S_IWUSR(S_IWRITE)00200     文件所有者具可写入权限
    S_IXUSR(S_IEXEC) 00100     文件所有者具可执行权限
​
    S_IRGRP 00040             用户组具可读取权限
    S_IWGRP 00020             用户组具可写入权限
    S_IXGRP 00010             用户组具可执行权限
​
    S_IROTH 00004             其他用户具可读取权限
    S_IWOTH 00002             其他用户具可写入权限
    S_IXOTH 00001             其他用户具可执行权限
​
    上述的文件类型在POSIX中定义了检查这些类型的宏定义:
    S_ISLNK (st_mode)    判断是否为符号连接
    S_ISREG (st_mode)    是否为一般文件
    S_ISDIR (st_mode)    是否为目录
    S_ISCHR (st_mode)    是否为字符装置文件
    S_ISBLK (s3e)        是否为先进先出
    S_ISSOCK (st_mode)   是否为socket

*/


#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <sys/stat.h>//包含文件操作函数的头文件
#include <fcntl.h>//
#include <sys/types.h>//
#include <unistd.h>//

// 1、正常传参的文件拷贝 
int main(int argc, char *argv)
{
	if(argc < 2)
	{
		printf("参数不够,请重新输入\n");
		exit(0);
	}

	int fd1 = open(argv[1], O_RDONLY);
	assert(fd1 != -1);

	int fd2 = open(argv[2], O_WRONLY | O_CREAT |O_TRUNC, 0664);
	assert(fd2 != -1);

	while(1)  // 由于文件大小无法预测,所以此处使用死循环来处理
	{
		char buff[128] = {0};
		int n = read(fd1, buff, 127);
		if(n <= 0)  // 当读取到文件末尾时,直接退出死循环
		{
			break;
		}

		write(fd2, buff, n);
	}

	close(fd1);
	close(fd2);

	exit(0);
}
// 2 、传递的文件是同一个文件,依靠文件信息结构体stat中的st_ino索引节点号来判断,一个文件对应一个inode节点;软连接不生成副本;

int main(int argc, char *argv[])
{
	if(argc < 2)
	{
		printf("参数不够,请重新输入\n");
		exit(0);
	}
	//判断传递的文件是否是同一个文件
	struct stat st1, st2;

	int res = stat(argv[1], &st1);
	assert(res != -1);

	res = stat(argv[2], &st2);
	assert(res != -1);

	if(st1.st_ino == st2.st_ino)
	{
		printf("不能拷贝同一份文件\n");
		exit(0);
	}
	//end

	int fd1 = open(argv[1], O_RDONLY);
	assert(fd1 != -1);

	int fd2 = open(argv[2], O_WRONLY | O_CREAT |O_TRUNC, 0664);
	assert(fd2 != -1);

	while(1)  // 由于文件大小无法预测,所以此处使用死循环来处理
	{
		char buff[128] = {0};
		int n = read(fd1, buff, 127);
		if(n <= 0)  // 当读取到文件末尾时,直接退出死循环
		{
			break;
		}

		write(fd2, buff, n);
	}

	close(fd1);
	close(fd2);

	exit(0);
}

// 3 、拷贝的是不是普通文件
int main(int argc, char *argv[])
{
	if(argc < 2)
	{
		printf("参数不够,请重新输入\n");
		exit(0);
	}
	//判断传递的文件是否是同一个文件
	struct stat st1, st2;

	int res = stat(argv[1], &st1);
	assert(res != -1);

	res = stat(argv[2], &st2);
	assert(res != -1);

	if(st1.st_ino == st2.st_ino)
	{
		printf("不能拷贝同一份文件\n");
		exit(0);
	}
	//end

	// 判断是否是普通文件
	
	if(!S_ISREG(st1.mode) || !S_ISREG(st2.mode))
	{
		printf("源文件或者目标文件不是普通文件\n");
		exit(0);
	}
	// end
	int fd1 = open(argv[1], O_RDONLY);
	assert(fd1 != -1);
	
	int fd2 = open(argv[2], O_WRONLY | O_CREAT |O_TRUNC, 0664);
	assert(fd2 != -1);

	while(1)  // 由于文件大小无法预测,所以此处使用死循环来处理
	{
		char buff[128] = {0};
		int n = read(fd1, buff, 127);
		if(n <= 0)  // 当读取到文件末尾时,直接退出死循环
		{
			break;
		}

		write(fd2, buff, n);
	}
	close(fd1);
	close(fd2);

	exit(0);
}
// 4 、将文件不只拷贝一份
void  FileCopy(char *file1, char *file2)
{
	//判断传递的文件是否是同一个文件
	struct stat st1, st2;

	int res = stat(file1, &st1);
	assert(res != -1);

	res = stat(file2, &st2);
	assert(res != -1);

	if(st1.st_ino == st2.st_ino)
	{
		printf("不能拷贝同一份文件\n");
		exit(0);
	}
	//end

	// 判断是否是普通文件
	if(!S_ISREG(st1.mode) || !S_ISREG(st2.mode))
	{
		printf("源文件或者目标文件不是普通文件\n");
		exit(0);
	}
	// end
	int fd1 = open(file1, O_RDONLY);
	assert(fd1 != -1);
	
	int fd2 = open(file2, O_WRONLY | O_CREAT |O_TRUNC, 0664);
	assert(fd2 != -1);

	while(1)  // 由于文件大小无法预测,所以此处使用死循环来处理
	{
		char buff[128] = {0};
		int n = read(fd1, buff, 127);
		if(n <= 0)  // 当读取到文件末尾时,直接退出死循环
		{
			break;
		}

		write(fd2, buff, n);
	}
	close(fd1);
	close(fd2);
}

int main(int argc, char *argv[])
{
	if(argc < 2)
	{
		printf("参数不够,请重新输入\n");
		exit(0);
	}

	int i = 0; 
	for(i = 2; i < argc; ++i)
	{
		CopyFile(argv[1], argv[i]);
	}
	
	exit(0);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值