c#大文件分割过程

需求:

在项目开发中,我们会遇到单个文件大小超过1TB的文件,这样的文件只能进行单文件读取,往往会造成读取完成耗时过长,导致客户在使用体验过程中不满意。

为了解决提升大文件的解析速度,我想到了先分割大文件为小文件,之后进行并行多个文件同时解析入库方案。

那么,怎么才可以把一个大文件分割为多个小文件呢?

如果我按照大小来控制分割出来的小文件,会造成文件的丢失问题,如果按照行数来分割,一行一行进行读取务必会造成分割文件耗时过长。

讨论:如果一个1TB的文件,我们按照大小来控制文件个数,假设每个分割出来的文件大小为200M,这样的话1TB分割出来约5200个文件,这样子的话最多造成约10000行信息被破坏,可以忽略不计。

所以我们为了减少分割文件带来的耗时时间长度,采取分割方案采用定长控制分割出来的文件大小。

  • 实现方案1:一次性读取1M,直到读取到200M为止,开始写入下一个分割文件。
 1  using (FileStream readerStream = new FileStream(file, FileMode.Open, FileAccess.Read))
 2             {
 3                 // 如果大于1GB
 4                 using (BinaryReader reader = new BinaryReader(readerStream))
 5                 {
 6                     int fileCursor = 0;
 7                     int readerCursor = 0;
 8                     char[] buffer = new char[1024 * 1024];
 9                     int length = 0;
10
11                 NextFileBegin:
12                     string filePath = string.Format(splitFileFormat, fileCursor);
13
14                     Console.WriteLine("开始读取文件【{1}】:{0}", filePath, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
15                     using (FileStream writerStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write))
16                     {
17                         using (BinaryWriter writer = new BinaryWriter(writerStream))
18                         {
19                             while ((length = reader.Read(buffer, 0, buffer.Length)) > 0)
20                             {
21                                 readerCursor++;
22
23                                 writer.Write(buffer, 0, length);
24
25                                 if (readerCursor >= splitFileSize)
26                                 {
27                                     Console.WriteLine("结束读取文件【{1}】:{0}", filePath, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
28
29                                     readerCursor = 0;
30                                     fileCursor++;
31
32                                     goto NextFileBegin;
33                                 }
34                             }
35                         }
36                     }
37                 }
38             }
  • 实现方案2:一次性读取200M,立即写入分割文件,开始下一个分割文件操作。
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.IO;
 6 using System.Configuration;
 7
 8 namespace BigFileSplitTest
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             /*
15              *  <!--是否开启大文件分隔策略-->
16                 <add key="BigFile.Split" value="true"/>
17                 <!--当文件大于这个配置项时就执行文件分隔,单位:GB -->
18                 <add key="BigFile.SplitMinFileSize" value="10" />
19                 <!--当执行文件分割时,每个分隔出来的文件大小,单位:MB -->
20                 <add key="BigFile.SplitFileSize" value="200"/>
21              *  <add key="BigFile.FilePath" value="\\172.x1.xx.xx\文件拷贝\xx\FTP\xx\2016-04-07\x_20160407.txt"/>
22                 <add key="BigFile.FileSilitPathFormate" value="\\172.x1.xx.xx\文件拷贝\liulong\FTP\xx\2016-04-07\x_20160407{0}.txt"/>
23              */
24
25             string file = ConfigurationManager.AppSettings.Get("BigFile.FilePath");
26             string splitFileFormat = ConfigurationManager.AppSettings.Get("BigFile.FileSilitPathFormate");
27             int splitMinFileSize = Convert.ToInt32(ConfigurationManager.AppSettings.Get("BigFile.SplitMinFileSize")) * 1024 * 1024 * 1204;
28             int splitFileSize = Convert.ToInt32(ConfigurationManager.AppSettings.Get("BigFile.SplitFileSize")) * 1024 * 1024;
29
30             FileInfo fileInfo = new FileInfo(file);
31             if (fileInfo.Length > splitMinFileSize)
32             {
33                 Console.WriteLine("判定结果:需要分隔文件!");
34             }
35             else
36             {
37                 Console.WriteLine("判定结果:不需要分隔文件!");
38                 Console.ReadKey();
39                 return;
40             }
41
42             int steps = (int)(fileInfo.Length / splitFileSize);
43             using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
44             {
45                 using (BinaryReader br = new BinaryReader(fs))
46                 {
47                     int couter = 1;
48                     bool isReadingComplete = false;
49                     while (!isReadingComplete)
50                     {
51                         string filePath = string.Format(splitFileFormat, couter);
52                         Console.WriteLine("开始读取文件【{1}】:{0}", filePath, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
53
54                         byte[] input = br.ReadBytes(splitFileSize);
55                         using (FileStream writeFs = new FileStream(filePath, FileMode.Create))
56                         {
57                             using (BinaryWriter bw = new BinaryWriter(writeFs))
58                             {
59                                 bw.Write(input);
60                             }
61                         }
62
63                         isReadingComplete = (input.Length != splitFileSize);
64                         if (!isReadingComplete)
65                         {
66                             couter += 1;
67                         }
68                         Console.WriteLine("完成读取文件【{1}】:{0}", filePath, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
69                     }
70                 }
71             }
72
73
74             Console.WriteLine("分隔完成,请按下任意键结束操作。。。");
75             Console.ReadKey();
76
77         }
78     }
79 }

从实验结果发现:方案一的性能较方案二的性能约耗时10倍。

具体原因为什么?

请你思考下:

一次性读取1M,直到读取到200M为止,开始写入下一个分割文件。

一次性读取200M,立即写入分割文件,开始下一个分割文件操作。

时间: 2024-10-16 21:03:08

c#大文件分割过程的相关文章

android下大文件分割上传

由于android自身的原因,对大文件(如影视频文件)的操作很容易造成OOM,即:Dalvik堆内存溢出,利用文件分割将大文件分割为小文件可以解决问题. 文件分割后分多次请求服务. 1 //文件分割上传 2 public void cutFileUpload(String fileType,String filePath) 3 { 4 try 5 { 6 FileAccessI fileAccessI = new FileAccessI(filePath, 0); 7 Long nStartPo

日志解析(四) 大文件分割

将百兆大文件分割成几十M的小文件,按大小进行分割 package com.fenge; import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.IOException; public class fenge {    public static f

linux大文件分割 split命令

linux split 命令 功能说明:切割文件. 语 法:split [--help][--version][-<行数>][-b <字节>][-C <字节>][-l <行数>][要切割的文件][输出文件名] [前缀] 补充说明:split可将文件切成较小的文件,预设每1000行会切成一个小文件. 参 数: -<行数>或-l<行数> 指定每多少行就要切成一个小文件. -b<字节> 指定每多少字就要切成一个小文件.支持单位:

python学习——大文件分割与合并

在平常的生活中,我们会遇到下面这样的情况: 你下载了一个比较大型的游戏(假设有10G),现在想跟你的同学一起玩,你需要把这个游戏拷贝给他. 然后现在有一个问题是文件太大(我们不考虑你有移动硬盘什么的情况),假设现在只有一个2G或4G的优盘,该怎么办呢? 有很多方法,例如winrar压缩的时候分成很多小卷,这里不累述. 在学习python之后,我们自己就可以解决这个问题啦. 我们可以自己写一个脚本去分割合并文件,将文件分割成适合优盘大小的小文件,在拷贝,然后再合并. 下面是文件分割脚本: 1 im

js大文件分割上传

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN"> <head> <title>分割大文件上传<

记一次删除Git记录中的大文件的过程

app/test/target/ #查看大文件 git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')" #删除大文件或者目录 git filter-branch --force --index-filter 'git rm -rf --cached --ignore-unmatch app/

Linux大文件分割split和合并cat使用方法

本文主要介绍linux下两个命令:split和cat.其中,相信大家都熟悉cat命令,一般用来查看一个文件的内容,但是它还其它的功能,比如这里要介绍的文件合并功能,它可把多个文件内容合并到一个文件中.从split词义不拿理解,其为分割之意,常用于分割大文件.下面详细介绍. split命令 — 分割文件 语法:split [–help][–version][-][-l][-b][-C][-d][-a][要切割的文件][输出文件名] –version 显示版本信息 – 或者-l,指定每多少行切割一次

用java实现大文件分割、排序、合并

import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Collections; import java.util.Iterator; import java

Php处理大文件-分割和合并

分割文件 /* * 分割文件 * 默认大小 2M=10485760/5 */ function file_split($file,$block_size=10485760/5) { $block_info=array(); $size=filesize($file); $i=0; while($size>0){ $block_info[]=array( 'size'=>($size>=$block_size?$block_size:$size), 'file'=>str_repla