C# 大文件切割(按文件行数,单个文件大小,切割数量)
前提
近期做项目,有了一个新需求,要求快速的读取CSV,text文档里面的数据,刚刚开始的时候以为是个小问题~就是普通读取一下文件,然后解析做两个算法罢了,玩玩没想到需求方扔给我一个145M,八万多列的CSV文档,WPF和OFFICE干脆就打不开,所以只能写了一个小程序,将其分割,然后存储到数据库中。在此留个备份
抽象类
public abstract class CutApartFile
{
public abstract void FileCut( string sourcePath , string targetFolder , long size );
}
按行切割
public class CutFileByRows : CutApartFile
{
public override void FileCut( string sourcePath , string targetFolder , long row )
{
if ( row <= 0 )
{
return;
}
FileInfo fileInfo = new FileInfo( sourcePath );
string fileName = fileInfo.Name.Replace( fileInfo.Extension , "" );
string lineData = "";
StreamReader sr = new StreamReader( sourcePath );
StreamWriter sw = null;
long readEowIndex = 1, index = 1;
while ( ( lineData = sr.ReadLine() ) != null )
{
if ( sw == null || readEowIndex >= row )
{
sw?.Close();
sw?.Dispose();
string _fileName = Path.Combine( targetFolder , $"{fileName}_{index}{fileInfo.Extension}" );
sw = new StreamWriter( _fileName );
readEowIndex = 1;
index++;
}
if ( row >= readEowIndex )
{
sw.WriteLine( lineData );
sw.Flush();
readEowIndex++;
}
}
sw?.Close();
sw?.Dispose();
sr?.Close();
sr.Dispose();
}
}
按文件大小切割
public class CutFileBySize : CutApartFile
{
public override void FileCut( string sourcePath , string targetFolder , long fileSize )
{
if ( fileSize <= 0 )
{
return;
}
FileInfo fileInfo = new FileInfo( sourcePath );
string fileName = fileInfo.Name.Replace( fileInfo.Extension , "" );
FileStream fsRead = new FileStream( sourcePath , FileMode.Open , FileAccess.Read , FileShare.Read );
BinaryReader br = new BinaryReader( fsRead );
int defaultBurrerLength = 1024 * 1024;
long fileSizeLength = fileSize * defaultBurrerLength;
byte[] buffer = new byte[ defaultBurrerLength ];
int readLength = 0;
int fileIndex = 1;
long fileLength = fileInfo.Length;
long readFileLength = 0;
while ( readFileLength < fileLength )
{
string writeFile = Path.Combine( targetFolder , $"{fileName}_{fileIndex}{fileInfo.Extension}" );
FileStream fsWrite = new FileStream( writeFile , FileMode.CreateNew , FileAccess.Write );
BinaryWriter bw = new BinaryWriter( fsWrite );
long singleFileLength = 0;
while ( ( readLength = br.Read( buffer , 0 , buffer.Length ) ) > 0 )
{
bw.Write( buffer , 0 , readLength );
readFileLength += readLength;
singleFileLength += readLength;
if ( singleFileLength >= fileSizeLength )
{
bw?.Close();
bw?.Dispose();
fsWrite?.Close();
fsWrite?.Dispose();
break;
}
}
bw?.Close();
bw?.Dispose();
fsWrite?.Close();
fsWrite?.Dispose();
fileIndex++;
}
br?.Close();
br?.Dispose();
fsRead?.Close();
fsRead.Dispose();
}
}
按文件个数切割
public class CutFileByFileCount : CutApartFile
{
public override void FileCut( string sourcePath , string targetFolder , long fileCount )
{
if ( fileCount <= 0 )
{
return;
}
FileInfo fileInfo = new FileInfo( sourcePath );
string fileName = fileInfo.Name.Replace( fileInfo.Extension , "" );
long fileLength = fileInfo.Length;
FileStream fsRead = new FileStream( sourcePath , FileMode.Open , FileAccess.Read , FileShare.Read );
BinaryReader br = new BinaryReader( fsRead );
int defaultBurrerLength = 1024 * 1024;
long fileSizeLength = Convert.ToInt64( ( Math.Ceiling( fileLength / Convert.ToDouble( fileCount ) ) ) );
byte[] buffer = new byte[ defaultBurrerLength ];
int readLength = 0;
int fileIndex = 1;
long readFileLength = 0;
while ( readFileLength < fileLength )
{
string writeFile = Path.Combine( targetFolder , $"{fileName}_{fileIndex}{fileInfo.Extension}" );
FileStream fsWrite = new FileStream( writeFile , FileMode.CreateNew , FileAccess.Write );
BinaryWriter bw = new BinaryWriter( fsWrite );
long singleFileLength = 0;
while ( ( readLength = br.Read( buffer , 0 , buffer.Length ) ) > 0 )
{
bw.Write( buffer , 0 , readLength );
readFileLength += readLength;
singleFileLength += readLength;
if ( singleFileLength >= fileSizeLength )
{
bw?.Close();
bw?.Dispose();
fsWrite?.Close();
fsWrite?.Dispose();
break;
}
}
bw?.Close();
bw?.Dispose();
fsWrite?.Close();
fsWrite?.Dispose();
fileIndex++;
}
br?.Close();
br?.Dispose();
fsRead?.Close();
fsRead.Dispose();
}
}