文件拆分

时间:2017-01-03 16:48:44

标签: c# csv

我正在编写一个程序,它将CSV文件分成四个几乎相等的部分。

我使用2000行CSV输入文件作为示例,在查看输出文件时,第一个文件中缺少行,并且还有不完整的行没有意义,因为我正在写行按行。代码如下:

using System.IO;
using System;
class MainClass {
  public static void Main(string[] args){

    string line; 
    int linesNumber = 0, linesEach = 0, cont = 0;

    StreamReader r = new StreamReader("in.csv");
    StreamWriter w1 = new StreamWriter("out-1.csv");
    StreamWriter w2 = new StreamWriter("out-2.csv");
    StreamWriter w3 = new StreamWriter("out-3.csv");
    StreamWriter w4 = new StreamWriter("out-4.csv");

    while((line = r.ReadLine()) != null)
      ++linesNumber;

    linesEach = linesNumber / 4;

    r.DiscardBufferedData();
    r.BaseStream.Seek(0, SeekOrigin.Begin);
    r.BaseStream.Position = 0;

    while((line = r.ReadLine()) != null){
      ++cont;
      if(cont == 1){
        //fisrt line must be skipped
        continue;
      }
      if(cont < linesEach){
        Console.WriteLine(line);
        w1.WriteLine(line);
      }
      else if(cont < (linesEach*2)){
        w2.WriteLine(line);
      }
      else if(cont < (linesEach*3)){
        w3.WriteLine(line);
      }
      else{
        w4.WriteLine(line);
      }
    }
  }
}

为什么写作部分出错了?我该如何解决?

谢谢大家的帮助。

3 个答案:

答案 0 :(得分:1)

这不是你问题的直接答案,只是另一种选择。

Linq可用于创建更短的代码

int inx = 0;
var fInfo = new FileInfo(filename); 

var lines = File.ReadAllLines(fInfo.FullName);
foreach (var groups in lines.GroupBy(x => inx++ / (lines.Length / 4)))
{
    var newFileName = $"{fInfo.DirectoryName}\\{fInfo.Name}_{groups.Key}{fInfo.Extension}";
    File.WriteAllLines(newFileName, groups);   
}

答案 1 :(得分:1)

您可以使用Partitioner和一些LINQ来简化您的方法。它还具有一次打开两个文件句柄的好处,而不是每个输出文件加上原始输入文件的1个。

using System.Collections.Concurrent;
using System.IO;
using System.Linq;

namespace FileSplitter
{
    internal static class Program
    {
        internal static void Main(string[] args)
        {
            var input = File.ReadLines("in.csv").Skip(1);

            var partitioner = Partitioner.Create(input);
            var partitions = partitioner.GetPartitions(4);

            for (int i = 0; i < partitions.Count; i++)
            {
                var enumerator = partitions[i];

                using (var stream = File.OpenWrite($"out-{i + 1}.csv"))
                {
                    using (var writer = new StreamWriter(stream))
                    {
                        while (enumerator.MoveNext())
                        {
                            writer.WriteLine(enumerator.Current);
                        }
                    }
                }
            }
        }
    }
}

答案 2 :(得分:0)

谢谢大家的回答。

问题是,正如Jegan和Spender所建议的那样,StreamWriter需要包含在using条款中。那说,问题解决了。