一、系统文件IO
1.利用分块
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define BUFF_SIZE 64
int main(int argc,char* argv[])
{
if(argc != 3)
{
printf("错误参数!\n");
return -1;
}
int input_fd = open(argv[1],O_RDONLY);
if(input_fd == -1)
{
perror("error");
}
int output_fd = open(argv[2],O_WRONLY|O_CREAT);
if(output_fd == -1)
{
perror("error");
}
int pos_end = lseek(input_fd,0,SEEK_END);
int pos_start = lseek(input_fd,0,SEEK_SET);
int len = pos_end-pos_start;
printf("%d\n",len);
char buff[BUFF_SIZE];
int count = len%BUFF_SIZE;
int loop = len/BUFF_SIZE;
int read_num = 0;
if(count == 0)
{
}
else
{
loop++;
}
for(int i = 0;i<loop;i++)
{
memset(buff,0,sizeof(buff));
read_num = read(input_fd,buff,sizeof(buff));
write(output_fd,buff,read_num);
}
}
2.利用双进程
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
int main(int argc,char* argv[])
{
if(argc != 3)
{
printf("输入格式:%s <src> <dst>\n",argv[0]);
exit(1);
}
//创建一个子线程
pid_t a = fork();
//父子进程都打开源文件和目标文件
int fd1 = open(argv[1],O_RDONLY);
int fd2 = open(argv[2],O_CREAT|O_RDWR|O_TRUNC,0644);
if(fd1 == -1 || fd2 == -1)
{
perror("error");
exit(1);
}
int size = lseek(fd1,0,SEEK_END);//获取文件的大小
if(a == 0)//在子线程中,将位置偏移量调整到中间位置(形成空洞)
{
lseek(fd1,size/2,SEEK_SET);
lseek(fd2,size/2,SEEK_SET);
}
else if(a>0)//在父进程中,将位置偏移量是调整到文件开头处
{
lseek(fd1,0,SEEK_SET);
}
char buf[100];
int nread;
while(1)
{
bzero(buf,100);
nread = read(fd1,buf,100);
if(nread == 0)
{
break;
}
if(a>0)
{
//在父进程中,查看当前偏移量是否已经到达中间位置
int n;
n = lseek(fd1,0,SEEK_CUR)-size/2;
if(n>=0)
{
//父进程从超过一半的地方开始写
write(fd2,buf,n);//写入未超过中间位置的字节
exit(0);//然后退出
}
}
//子进程在一半以前的地方写
write(fd2,buf,nread);
}
close(fd1);
close(fd2);
return 0;
二、标准文件IO
1.利用分块
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
./02 /home/harold/C_Linux/04day/work/02_input.txt /home/harold/C_Linux/04day/work/02_output.txt
*/
#define BUFF_SIZE 128
int main(int argc,char* argv[])
{
if(argc != 3)
{
printf("输入格式:%s <src> <dst>\n",argv[0]);
exit(1);
}
FILE* fd_input = fopen(argv[1],"r");
FILE* fd_output = fopen(argv[2],"w");
if(fd_input == NULL|| fd_output == NULL)
{
perror("error");
exit(1);
}
char buff[BUFF_SIZE+1] = {0};
while(!feof(fd_input))
{
fread(buff,BUFF_SIZE,1,fd_input);
fwrite(buff,strlen(buff),1,fd_output);
__bzero(buff,sizeof(buff));
}
fclose(fd_input);
fclose(fd_output);
}
2.利用双进程
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define BUFF_SIZE 128
int main(int argc, char *argv[])
{
if (argc != 3)
{
fprintf(stderr, "Usage: %s <src> <dst>\n", argv[0]);
exit(EXIT_FAILURE);
}
// 打开输入文件
FILE *input = fopen(argv[1], "rb");
if (!input)
{
perror("fopen input failed");
exit(EXIT_FAILURE);
}
// 获取文件大小
fseek(input, 0, SEEK_END);
long file_size = ftell(input);
rewind(input);
// 预创建输出文件
int fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1)
{
perror("open output failed");
exit(EXIT_FAILURE);
}
if (ftruncate(fd, file_size) == -1)
{
perror("ftruncate failed");
exit(EXIT_FAILURE);
}
close(fd);
pid_t pid = fork();
if (pid < 0)
{
perror("fork failed");
exit(EXIT_FAILURE);
}
// 各自独立打开输出文件
FILE *output = fopen(argv[2], "r+b");
if (!output)
{
perror("fopen output failed");
exit(EXIT_FAILURE);
}
if (pid == 0)
{ // 子进程处理后半部分
fseek(input, file_size / 2, SEEK_SET);
fseek(output, file_size / 2, SEEK_SET);
char buffer[BUFF_SIZE];
size_t total = 0;
size_t max_read = file_size - file_size / 2;
while (total < max_read)
{
size_t to_read = (max_read - total) > sizeof(buffer) ? sizeof(buffer) : (max_read - total);
size_t nread = fread(buffer, 1, to_read, input);
if (nread == 0)
break;
size_t nwritten = fwrite(buffer, 1, nread, output);
if (nwritten != nread)
{
perror("Child write failed");
exit(EXIT_FAILURE);
}
total += nwritten;
}
}
else
{ // 父进程处理前半部分
fseek(output, 0, SEEK_SET);
char buffer[BUFF_SIZE];
size_t total = 0;
size_t target = file_size / 2;
while (total < target)
{
size_t to_read = (target - total) > sizeof(buffer) ? sizeof(buffer) : (target - total);
size_t nread = fread(buffer, 1, to_read, input);
if (nread == 0)
break;
size_t nwritten = fwrite(buffer, 1, nread, output);
if (nwritten != nread)
{
perror("Parent write failed");
exit(EXIT_FAILURE);
}
total += nwritten;
}
}
fclose(input);
fclose(output);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define BUFF_SIZE 4096
int main(int argc, char* argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <src> <dst>\n", argv[0]);
exit(EXIT_FAILURE);
}
// 打开输入文件
FILE* input = fopen(argv[1], "r");
if (!input) {
perror("Input file open failed");
exit(EXIT_FAILURE);
}
// 获取文件大小
fseek(input, 0, SEEK_END);
long file_size = ftell(input);
rewind(input);
// 创建并初始化输出文件
FILE* output = fopen(argv[2], "w"); // 使用读写模式创建文件
if (!output) {
perror("Output file create failed");
exit(EXIT_FAILURE);
}
// 预分配空间(标准I/O方式)
fseek(output, file_size-1, SEEK_SET);
fputc('\0', output);
rewind(output);
pid_t pid = fork();
if (pid < 0) {
perror("Fork failed");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程处理后半部分
fseek(input, file_size/2, SEEK_SET);
fseek(output, file_size/2, SEEK_SET);
unsigned char buffer[BUFF_SIZE];
size_t remaining = file_size - file_size/2;
while (remaining > 0) {
size_t chunk = remaining > sizeof(buffer) ? sizeof(buffer) : remaining;
size_t nread = fread(buffer, 1, chunk, input);
if (nread == 0) break;
size_t nwritten = fwrite(buffer, 1, nread, output);
if (nwritten != nread) {
perror("Child write error");
exit(EXIT_FAILURE);
}
remaining -= nwritten;
}
} else { // 父进程处理前半部分
unsigned char buffer[BUFF_SIZE];
size_t remaining = file_size/2;
while (remaining > 0) {
size_t chunk = remaining > sizeof(buffer) ? sizeof(buffer) : remaining;
size_t nread = fread(buffer, 1, chunk, input);
if (nread == 0) break;
size_t nwritten = fwrite(buffer, 1, nread, output);
if (nwritten != nread) {
perror("Parent write error");
exit(EXIT_FAILURE);
}
remaining -= nwritten;
}
}
// 确保所有缓冲数据写入磁盘
fflush(output);
fsync(fileno(output));
fclose(input);
fclose(output);
return 0;
}