c#大文件分割过程
需求:
在项目开发中,我们会遇到单个文件大小超过1TB的文件,这样的文件只能进行单文件读取,往往会造成读取完成耗时过长,导致客户在使用体验过程中不满意。
为了解决提升大文件的解析速度,我想到了先分割大文件为小文件,之后进行并行多个文件同时解析入库方案。
那么,怎么才可以把一个大文件分割为多个小文件呢?
如果我按照大小来控制分割出来的小文件,会造成文件的丢失问题,如果按照行数来分割,一行一行进行读取务必会造成分割文件耗时过长。
讨论:如果一个1TB的文件,我们按照大小来控制文件个数,假设每个分割出来的文件大小为200M,这样的话1TB分割出来约5200个文件,这样子的话最多造成约10000行信息被破坏,可以忽略不计。
所以我们为了减少分割文件带来的耗时时间长度,采取分割方案采用定长控制分割出来的文件大小。
- 实现方案1:一次性读取1M,直到读取到200M为止,开始写入下一个分割文件。
using (FileStream readerStream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
// 如果大于1GB
using (BinaryReader reader = new BinaryReader(readerStream))
{
int fileCursor = ;
int readerCursor = ;
char[] buffer = new char[ * ];
int length = ; NextFileBegin:
string filePath = string.Format(splitFileFormat, fileCursor); Console.WriteLine("开始读取文件【{1}】:{0}", filePath, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
using (FileStream writerStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
using (BinaryWriter writer = new BinaryWriter(writerStream))
{
while ((length = reader.Read(buffer, , buffer.Length)) > )
{
readerCursor++; writer.Write(buffer, , length); if (readerCursor >= splitFileSize)
{
Console.WriteLine("结束读取文件【{1}】:{0}", filePath, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); readerCursor = ;
fileCursor++; goto NextFileBegin;
}
}
}
}
}
}
- 实现方案2:一次性读取200M,立即写入分割文件,开始下一个分割文件操作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Configuration; namespace BigFileSplitTest
{
class Program
{
static void Main(string[] args)
{
/*
* <!--是否开启大文件分隔策略-->
<add key="BigFile.Split" value="true"/>
<!--当文件大于这个配置项时就执行文件分隔,单位:GB -->
<add key="BigFile.SplitMinFileSize" value="10" />
<!--当执行文件分割时,每个分隔出来的文件大小,单位:MB -->
<add key="BigFile.SplitFileSize" value="200"/>
* <add key="BigFile.FilePath" value="\\172.x1.xx.xx\文件拷贝\xx\FTP\xx\2016-04-07\x_20160407.txt"/>
<add key="BigFile.FileSilitPathFormate" value="\\172.x1.xx.xx\文件拷贝\liulong\FTP\xx\2016-04-07\x_20160407{0}.txt"/>
*/ string file = ConfigurationManager.AppSettings.Get("BigFile.FilePath");
string splitFileFormat = ConfigurationManager.AppSettings.Get("BigFile.FileSilitPathFormate");
int splitMinFileSize = Convert.ToInt32(ConfigurationManager.AppSettings.Get("BigFile.SplitMinFileSize")) * * * ;
int splitFileSize = Convert.ToInt32(ConfigurationManager.AppSettings.Get("BigFile.SplitFileSize")) * * ; FileInfo fileInfo = new FileInfo(file);
if (fileInfo.Length > splitMinFileSize)
{
Console.WriteLine("判定结果:需要分隔文件!");
}
else
{
Console.WriteLine("判定结果:不需要分隔文件!");
Console.ReadKey();
return;
} int steps = (int)(fileInfo.Length / splitFileSize);
using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(fs))
{
int couter = ;
bool isReadingComplete = false;
while (!isReadingComplete)
{
string filePath = string.Format(splitFileFormat, couter);
Console.WriteLine("开始读取文件【{1}】:{0}", filePath, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); byte[] input = br.ReadBytes(splitFileSize);
using (FileStream writeFs = new FileStream(filePath, FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(writeFs))
{
bw.Write(input);
}
} isReadingComplete = (input.Length != splitFileSize);
if (!isReadingComplete)
{
couter += ;
}
Console.WriteLine("完成读取文件【{1}】:{0}", filePath, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
}
}
} Console.WriteLine("分隔完成,请按下任意键结束操作。。。");
Console.ReadKey(); }
}
}
从实验结果发现:方案一的性能较方案二的性能约耗时10倍。
具体原因为什么?
请你思考下:
一次性读取1M,直到读取到200M为止,开始写入下一个分割文件。
一次性读取200M,立即写入分割文件,开始下一个分割文件操作。
c#大文件分割过程的更多相关文章
- android下大文件分割上传
由于android自身的原因,对大文件(如影视频文件)的操作很容易造成OOM,即:Dalvik堆内存溢出,利用文件分割将大文件分割为小文件可以解决问题. 文件分割后分多次请求服务. //文件分割上传 ...
- PHP + JS 实现大文件分割上传
服务器上传文件会有一定的限制.避免内存消耗过大影响性能,在 php.ini 配置文件中,有几个影响参数: upload_max_filesize = 2M //PHP最大能接受的文件大小 post_m ...
- Linux大文件分割splite
/********************************************************************** * Linux大文件分割splite * 说明: * 编 ...
- Html5 突破微信限制实现大文件分割上传
先来前端代码 <!DOCTYPE html> <html> <head> <meta name="viewport" content=&q ...
- c# 大文件分割 复制 Filestream 进度条
大文件分割复制,每次复制100M 也可以复制别的较大数值. 小于1G的小文件就直接复制得了.代码里没写 ,但是很简单 直接写进去就好了,难得是分割复制 所以没写. 好吧 我还是改了 改成小文件也可以复 ...
- 大文件分割、命令脚本 - Python
日志文件分割.命名 工作中经常会收到测试同学.客户同学提供的日志文件,其中不乏几百M一G的也都有,毕竟压测一晚上产生的日志量还是很可观的,xDxD,因此不可避免的需要对日志进行分割,通常定位问题需要针 ...
- Linux中split大文件分割和cat合并文件
当需要将较大的数据上传到服务器,或从服务器下载较大的日志文件时,往往会因为网络或其它原因而导致传输中断而不得不重新传输.这种情况下,可以先将大文件分割成小文件后分批传输,传完后再合并文件. 1.分割 ...
- FileStrem大文件分割复制
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- formdata方式上传文件,支持大文件分割上传
1.upload.html <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/html"> <h ...
随机推荐
- NOIp 2014 #1 生活大爆炸版石头剪刀布 Label:模拟
题目描述 石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头.如果两个人出拳一样,则不分胜负.在<生活大爆炸>第二季第8 集中出现了一种石头剪刀布的升级版游戏. 升级版游戏在传统的 ...
- Android -- 服务组件的使用(1)
1. 效果图
- ajax操作时用于提高用户体验的两段备用代码
<div id="msgBoxDIV" style="position: absolute; width: 50%; padding-top: 2px; heigh ...
- linux下搭建svn代码库
1.安装svn客户端 2.创建svn代码库 1.安装svn客户端 1.1.使用命令安装 1)CentOS $ yum install subversion 2)ubuntu sudo apt-get ...
- 油田 Oil Deposits
油田 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=84562#problem/L 题意: 输入一个m行n列的字符矩形,统计字符 ...
- nginx资源定向 css js路径问题
今天玩玩项目,学学nginx发现还不错,速度还可以,但是CSS JS确无法使用,原来Iginx配置时需要对不同类型的文件配置规则,真是很郁闷,不过想想也还是很有道理.闲暇之际,把配置贴上来.#user ...
- C语言中指针的使用
什么是指针:指针就是一个变量,是一个存放内容的内存空间.指针存放的内容是另一个内存空间的起始地址.不同于一般变量存放的就是变量值.取值操作符*对于指针的作用是取得指针变量存放的内存地址里面的值,不加* ...
- 关于android端的json传输
比较通用的传输方法 import java.util.ArrayList; import java.util.List; import org.apache.http.HttpEntity; impo ...
- Daily Scrum 11.3
今天开发人员的任务都还行,测试的同学要开始辛苦了. 下面是今天的Task统计:
- javascript对象的一点理解
<script type="text/javascript"> /* js对象:对象的职责是调用属性和调用方法 */ //1.对象的创建的三种方式 var obj = ...