本文是为参加传智播客asp.net黑马班写的第二篇asp.net技术文章。主题是将一个比较大的文本文件分割成若干个体积较小的小文件。
题目来源:上次我有提到要做个基于数据库的电话号码归属地查询程序,单线程导入数据到数据库中比较费时,效率低下。所以,我就希望做成多线程导入资料,于是就有了上一文章主题:验证多线程同时往一个数据表中插入数据。通过上次文章知道,MS sqlserver是支持多线程同时往一个数据表中写数据的。解决了写数据的问题,那么还有读数据的问题,即如何用多线程将数据读出来?
由于我下的号段资料是在一个比较大的文本文件中(10.3M),若用多线程同时读一个文件,除不知道是否可行外,也不太好控制,不知道各个线程分别该读哪些内容。于是我就想将大文件分割成数个体积相对较小的文件,然后让一个线程读取一个文件的内容,读完后再独立的往数据库中写数据。因此,接下来就得想方法将一个文件分割分若干份小文件。
我们知道,操作一个文件肯定要用操作文件相关的IO类。通过查看帮助文档,发现对于有以下几个类可能能用到:
File:提供了很多静态方法操作文件;
FileStream:提供有丰富的读写文件的方法;
Directory:扫描目录,获取文件;
Path:操作文件路径;
好了,准备工作完成,开始写代码,如下:
private void button2_Click(object sender, EventArgs e)
{
if (SplitFiles())
{
MessageBox.Show("分割完成!");
}
else
{
MessageBox.Show("分割失败!");
}
}
/// <summary>
/// 分割文件
/// </summary>
/// <returns>成功:true;失败:false</returns>
bool SplitFiles()
{
FolderBrowserDialog filePath = new FolderBrowserDialog();
if (filePath.ShowDialog() != DialogResult.OK)
{
return false;
}
string path = filePath.SelectedPath;//得到用户选择的路径
string[] files = Directory.GetFiles(path, "*.txt", SearchOption.TopDirectoryOnly);//得到路径下的所有文本文件
foreach (var file in files)//遍历目录下的文件
{
int i = 0;
int readLength =0;
byte[] bytesRead;
int getBytes = 0;
int writeLength = 1024 * 100;//新文件的大小:100K
//开始读文本数据
using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
{
readLength = (int)fs.Length;
bytesRead = new byte[readLength];
while (readLength > 0)
{
int n = fs.Read(bytesRead, getBytes, bytesRead.Length);
if (n == 0)
{
break;
}
getBytes += n;
readLength -= n;
}
}
//建立保存新文件的目录
string newPath = path + @"\" + Path.GetFileNameWithoutExtension(file) + @"\";
if (Directory.Exists(newPath) == false)
{
Directory.CreateDirectory(newPath);
}
//开始将数据写入小文件中
while (getBytes > 0)
{
i++;
string newfile = newPath + i.ToString() + ".txt";
using (FileStream fw = new FileStream(newfile, FileMode.Create, FileAccess.Write))
{
if (getBytes < writeLength)
{
fw.Write(bytesRead, readLength, getBytes);
}
else
{
fw.Write(bytesRead, readLength, writeLength);
}
}
readLength += writeLength;
getBytes -= writeLength;
}
}
return true;
}
通过测试,这个程序 运行结果基本符合预期。但并不是完美的,由于文本文件中的数据一行就是一条完整记录。如下图:
![](http://hi.csdn.net/attachment/201112/6/0_1323170304dgLZ.gif)
而FileStream基于 数据流进行操作的,因此会造成有些行被分割了。上半条数据在一个文件的尾部,下半条数据在一个文件的开头。如下如所示: