【问题标题】:writing to text file does not alway work/save写入文本文件并不总是有效/保存
【发布时间】:2012-08-21 23:17:26
【问题描述】:

我有这段代码可以比较两个文本文件并将差异写入日志文件,但由于某种原因,log.txt 文件有时是空白的,即使在测试某些以 * 开头的行时,这些也不总是写入完成写作后我是否必须保存文本文件,尽管这不能解释为什么有时它会起作用,任何帮助都会很棒

private void compare()
{
  string FilePath = @"c:\snapshot\1.txt";
  string Filepath2 = @"c:\snapshot\2.txt";
  int counter = 0;
  string line;
  string line2;

  var dir = "c:\\snapshot\\log.txt";

  using (FileStream fs = File.Create(dir))
  {
    fs.Dispose();
  }

  StreamWriter dest = new StreamWriter(dir);

  if (File.Exists(FilePath) & File.Exists(Filepath2))
  {
    // Read the file and display it line by line.
    using (var file = File.OpenText(FilePath))
    using (var file2 = File.OpenText(Filepath2))
    {
      while (((line = file.ReadLine()) != null & (line2 = file2.ReadLine()) != null))
      {
        if (line.Contains("*"))
        {
          dest.WriteLine(line2);
        }
        else if (!line.Contains(line2))
        {
          dest.WriteLine(line2);
        }
        counter++;
      }
    }
  } 
  dest.Close();
}

【问题讨论】:

  • 粗略一瞥,在我看来,您的行可能会不同步,因为您正在读取具有不同数据的两个文件。如果文件不大,您可能希望将它们加载到列表中并进行更正式的比较。
  • 你的代码有点乱,如果你使用“using”,你不需要调用dispose,为什么你不使用StreamWriter的“using”,为什么使用FileStream和做什么都没有...
  • 顺便说一句,using 语句的全部要点,它会为你调用 Dispose,所以在 using 块中调用 Dispose,充其量是不需要的。
  • 使用&&,而不是&。单个& 是按位算术,最终可能会做你想做的事,但通常在这里你的意思是&&
  • 我是 C# 新手,编程只是自学并获得论坛提示,因此在使用“使用”时不需要使用 dispose 来添加其他内容

标签: c# filewriter


【解决方案1】:

一旦您点击 StreamReader 上的关闭语句,缓冲区中剩余的所有内容都应该被写出。如果你丢失了东西,那么可能是因为某种原因你没有到达那条线(即你崩溃了)。此外,如果您在写入文件时(即程序仍在运行时)尝试查看文件,您不一定会看到所有内容(因为它尚未关闭)。

通常,最好在 StreamReader 中使用 using 语句。这应该确保它总是被关闭。

【讨论】:

  • 将两个文本文件加载到列表然后比较列表的最佳方法是什么?
  • 注意,如果您已经使用了 StreamReader 的输入,例如一个 Filestream,然后在 StreamReader 上也放一个,当 FileStream 实例超出范围时,将给您一个已经处理的错误。
【解决方案2】:
private void compare()
{
  string FileName1 = @"c:\snapshot\1.txt";
  string FileName2 = @"c:\snapshot\2.txt";
  string FileNameOutput = @"c:\snapshot\log.txt"; //dir ???
  int counter = 0; // um what's this for you aren't using it.

  using (FileStream fso = new FileStream(FileNameOutput, FileMode.Create, FileAccess.Write))
  {
    TextWriter dest = new StreamWriter(fso);
    using(FileStream fs1 = new FileStream(FileName1, FileMode.Open, FileAccess.Read))
    {
      using (FileStream fs2 = new FileStream(FileName2, FileMode.Open, FileAccess.Read))
      {
        TextReader firstFile = new StreamReader(fs1);
        TextReader secondFile = new StreamReader(fs2);
        while (((line1 = firstFile.ReadLine()) != null & (line2 = secondFile.ReadLine()) != null))
        {
          if ((line1.Contains("*") || (!line1.Contains(line2)))
          {
            dest.Write(line2); // Writeline would give you an extra line?
          }
          counter++; // 
        }
      }
    }
  fso.Flush();
}

我向您推荐 FileStream 的重载。按照我的方式进行操作,如果运行它的用户没有所有必需的权限,则代码将在您实例化流时崩溃。这是一个很好的方式来展示你想要什么,你不想要什么。

PS 你知道 contains 区分大小写和文化吗?

【讨论】:

  • 我认为你不需要手动刷新:stackoverflow.com/questions/7710661/…
  • 嗯,我知道它说你不应该,但我已经看到它以一种皮带和大括号的方式解决了好几次问题。我不相信它会发生,所以我现在称之为自卫。
【解决方案3】:

不确定我是否理解您的比较逻辑,但只要我将比较与整个代码分开,您就可以根据自己的需要进行调整:

    public static void WriteDifferences(string sourcePath, string destinationPath, string differencesPath)
    {
        var sourceLines = File.ReadAllLines(sourcePath).ToList();
        var destinationLines = File.ReadAllLines(destinationPath).ToList();            

        // make lists equal size
        if (sourceLines.Count > destinationLines.Count)
        {
            destinationLines.AddRange(Enumerable.Range(0, sourceLines.Count - destinationLines.Count).Select(x => (string)null));
        } 
        else
        {
            sourceLines.AddRange(Enumerable.Range(0, destinationLines.Count - sourceLines.Count).Select(x => (string)null));
        }

        var differences = sourceLines.Zip(destinationLines, (source, destination) => Compare(source, destination));

        File.WriteAllLines(differencesPath, differences.Where(x => x != null));
    }

    private static string Compare(string source, string destination)
    {
        return !source.Contains(destination) || source.Contains("*") ? destination : null;
    }

【讨论】:

  • 不确定我是否热衷于你的假设,即有足够的内存在无所事事地保存文件和差异......
  • 视情况而定。如果我确定,该文件永远不会超过 1mb,我会更喜欢易于维护的代码,如果不是 - 确定,通过逐行读取和比较编写没有问题,这可能会比当前方法慢(不确定 io 缓存如何可以逐行阅读)。
  • 如果我知道文件很小,我就没有问题。看到我们不知道,只是想我会提到这个问题,对于那些不喜欢间歇性 OOM 的人是他们的代码 :(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-24
  • 2011-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多