基于 BinaryReader 的高效切割TXT文件

日常工作中免不了要面对一些文件的操作..

但是如果是日志文件..动辄上G的..处理起来就不那么轻松随意了..

尤其文件还很多的时候..

这个时候就会用到大文件切割..

下边贴出的示例是实验了一个 10G 的TXT文件来做的..效果还可以..全部切割成50M的文件大概用了一分多钟..

下面是代码..具体的流程在注释里都有..自己看..

要实验嘛..先做一个大文件出来..不用找了..跑这两行代码弄一个..

StreamWriter writer=new StreamWriter (@"E:FTPSdata.csv");
for (int i = 0; i < int.MaxValue; i++)
{
    writer.WriteLine(i.ToString()+"	    'fsdjklfjsdl','sdfsdlfjlsdjf','f123双方的dffdsfsdf','f发斯蒂芬sdjklfjsdl','sd地方fsdlfjlsdjf','f1发斯蒂芬2312dffdsfsdf'");
}
writer.Dispose();

前边有行号..方便切割之后看看数据完整性.

然后是干货..

            //源文件
            string sourceFile = @"E:FTPSdata.csv";
            //拆分后文件输出目录
            string splitFileDirf = @"E:FTPS";
            //每个文件的基本大小
            long splitFileSize = 1024 * 1024 * 50;
            //开始位置
            long readStart = 0;
            //拆分的文件名称序号
            int SplitFileNum = 1;
            try
            {
                FileStream stream = new FileStream(sourceFile, FileMode.Open);
                long FileTotalLength = stream.Length;
                //创建二进制读取
                using (BinaryReader reader = new BinaryReader(stream,Encoding.UTF8))
                {
                    //直接将开始读取的位置设定到基础大小的字节上
                    //下面要做的是往后找到这一行的结束
                    reader.BaseStream.Position = splitFileSize - 1;
                    //判断当前位置不超过文件总大小
                    while (reader.BaseStream.Position <= FileTotalLength)
                    {
                        //往后挨个儿字符找换行
                        //这里要说明的是  reader.ReadByte() 方法执行时会自动将 reader.BaseStream.Position 的值向后+1
                        //网上有些例子执行了 ReadByte 另外还做 Position++  明显是有字符隔掉的
                        while (reader.BaseStream.Position < FileTotalLength && reader.ReadByte() != 13) { }

                        //对输出的文件地址创建流
                        FileStream fileStreamOut = new FileStream(splitFileDirf + SplitFileNum + ".csv", FileMode.Create);
                        //创建二进制写入
                        using (BinaryWriter binaryWriter = new BinaryWriter(fileStreamOut, Encoding.UTF8))
                        {
                            //这里获得现在找到换行的那个字节上的位置到这次遍历开始的位置中间的字节数量
                            //+1 是为了把找到的那个换行符也带上
                            int readWrodCountNow = (int)(reader.BaseStream.Position - readStart + 1);
                            //把读取的起始位置重置到这次查询的开始位置
                            reader.BaseStream.Position = readStart;
                            //把这次读取的内容写入到新文件
                            binaryWriter.Write(reader.ReadBytes(readWrodCountNow));
                        }

                        //将这次读取到的位置作为下次的起始位置
                        readStart = reader.BaseStream.Position;
                        //下次的验证开始位置  从这里开始验证换行
                        reader.BaseStream.Position = readStart + splitFileSize - 1;
                        //输出文件名
                        SplitFileNum++;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.WriteLine("Complete");
            //Console.ReadKey();

好啦..代码都在这里了..

说明白啊..网上有的代码有问题..在注释里说过问题在哪里..

核心代码就是这样了.. 要优化的可以包装一下..

比如隔断符号自定义..文件大小自定义什么的..自己弄吧..

原文地址:https://www.cnblogs.com/iiwen/p/5486160.html