电话号码归属地查询——分割较大的文本文件成若干小文件

来源:互联网 发布:国内免费数据库 编辑:程序博客网 时间:2024/05/06 02:20
---------------------- android培训、java培训、期待与您交流! ----------------------

       本文是为参加传智播客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;        }

通过测试,这个程序      运行结果基本符合预期。但并不是完美的,由于文本文件中的数据一行就是一条完整记录。如下图:

而FileStream基于      数据流进行操作的,因此会造成有些行被分割了。上半条数据在一个文件的尾部,下半条数据在一个文件的开头。如下如所示:


      如果在往数据库写数据时,读取到这样的数据将发生异常。想了很久,都无法解决这个问题。如果有哪位高手要知道怎么做,欢迎给出解决办法,不胜感激。
---------------------- android培训、java培训、期待与您交流! ----------------------

原创粉丝点击