StreamWriter 只写一行

StreamWriter only writes one line

我正在尝试从 .csv 文件写入新文件。

每次StreamWriter写入,都会写入新文件的第一行。然后它用下一个字符串覆盖该行,并继续这样做直到 StreamReader 达到 EndOfStream.
有没有人经历过这个?你是如何克服它的?

这是我在学校作业要求之外的第一个解决方案。原始文件中的行数未知。 .csv 文件的每一行只有 17 列。我只需要按照下面代码片段中的顺序编写其中的三个。
在编码 StreamWriter 之前,我使用 Console.WriteLine() 来确保每一行的顺序都是正确的。

这是代码片段:

{
    string path = @ "c:\directory\file.csv";
    string newPath = @ "c:\directory\newFile.csv"

    using(FileStream fs = new FileStream(path, FileMode.Open))
    {
        using(StreamReader sr = new StreamReader(fs))
        {
            string line;
            string[] columns;
            while ((line = sr.ReadLine()) != null)
            {
                columns = line.Split(',');
                using(FileStream aFStream = new FileStream(
                    newPath, 
                    FileMode.OpenOrCreate, 
                    FileAccess.ReadWrite))
                using(StreamWriter sw = new StreamWriter(aFStream))
                {
                    sw.WriteLine(columns[13] + ',' + columns[10] + ',' + columns[16]);
                    sw.Flush();
                    sw.WriteLine(sw.NewLine);
                }
            }
        }
    }
}

首先,您要为每一行创建并关闭写入同一文件的流。这意味着文件每一行都会被覆盖。你想把你的 using 块放在 while 循环之外;但是,如果您坚持为每一行打开和关闭写入流,那么您需要使用 FileMode.Append

{
  string path=@"c:\directory\file.csv";
  string newPath=@"c:\directory\newFile.csv"
  using(StreamReader sr = new StreamReader(new FileStream(path, FileMode.Open))) // no need for 2 usings
  using (FileStream aFStream = new FileStream (newPath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
  {
    string line;
    string[] columns;
    {
      while((line = sr.ReadLine()) != null)
      {
        columns = line.Split(',');
        using (StreamWriter sw = new StreamWriter(aFStream))
        {
          sw.WriteLine(columns[13] + ',' + columns[10] + ',' + columns[16]);
          sw.Flush();
          sw.WriteLine(sw.NewLine);
        }
      }
    }
  }
}

您应该在与打开源相同的范围内打开目标,而不是在循环中这样做,这将导致您每次使用 FileMode 选项 OpenOrCreate 覆盖文件.

var path = @"c:\directory\file.csv";
var newPath = @"c:\directory\newFile.csv"

using(var sr = new StreamReader(new FileStream(path, FileMode.Open)))
using(var sw = new StreamWriter(new FileStream(newPath, FileMode.OpenOrCreate, FileAccess.ReadWrite)))
{
    while(!sr.EndOfStream)
    {
        string line = sr.ReadLine();
        var columns = line.Split(',');
        sw.WriteLine(columns[13] + ',' + columns[10] + ',' + columns[16]);
        sw.WriteLine(sw.NewLine);
    }
    sw.Flush();
}

我也希望您对 CSV 间距有把握,因为您正在对代码中的位置进行硬编码。

要正确修复您的代码,您需要构建更多结构:

public void CopyFileContentToLog()
{
     var document = ReadByLine();
     WriteToFile(document);
}

public IEnumerable<string> ReadByLine()
{
     string line;
     using(StreamReader reader = File.OpenText(...))
          while ((line = reader.ReadLine()) != null)
              yield return line;
}

public void WriteToFile(IEnumerable<string> contents)
{
     using(StreamWriter writer = new StreamWriter(...))
     {
          foreach(var line in contents)
              writer.WriteLine(line);

          writer.Flush();
     }
}

您显然可以定制并使其更加灵活。但这应该可以证明并解决您在循环和流中遇到的一些问题。