【问题标题】:StreamWriter appends random dataStreamWriter 附加随机数据
【发布时间】:2011-03-03 10:32:19
【问题描述】:

我看到使用 StreamWriter 类使用此代码将额外数据写入文件的奇怪行为:

public void WriteToCSV(string filename)
{
    StreamWriter streamWriter = null;
    try
    {
        streamWriter = new StreamWriter(filename);
        Log.Info("Writing CSV report header information ... ");
        streamWriter.WriteLine("\"{0}\",\"{1}\",\"{2}\",\"{3}\"", ((int)CSVRecordType.Header).ToString("D2", CultureInfo.CurrentCulture), m_InputFilename, m_LoadStartDate, m_LoadEndDate);

        int recordCount = 0;

        if (SummarySection)
        {
            Log.Info("Writing CSV report summary section ... ");
            foreach (KeyValuePair<KeyValuePair<LoadStatus, string>, CategoryResult> categoryResult in m_DataLoadResult.DataLoadResults)
             {
                streamWriter.WriteLine("\"{0}\",\"{1}\",\"{2}\",\"{3}\"", ((int)CSVRecordType.Summary).ToString("D2", CultureInfo.CurrentCulture), categoryResult.Value.StatusString, categoryResult.Value.Count.ToString(CultureInfo.CurrentCulture), categoryResult.Value.Category);
                recordCount++;
             }
        }

        Log.Info("Writing CSV report cases section ... ");
        foreach (KeyValuePair<KeyValuePair<LoadStatus, string>, CategoryResult> categoryResult in m_DataLoadResult.DataLoadResults)
        {
            foreach (CaseLoadResult result in categoryResult.Value.CaseLoadResults)
            {
                if ((LoadStatus.Success == result.Status && SuccessCases) ||
                    (LoadStatus.Warnings == result.Status && WarningCases) ||
                    (LoadStatus.Failure == result.Status && FailureCases) ||
                    (LoadStatus.NotProcessed == result.Status && NotProcessedCases))
                {
                    streamWriter.Write("\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\"", ((int)CSVRecordType.Result).ToString("D2", CultureInfo.CurrentCulture), result.Status, result.UniqueId, result.Category, result.ClassicReference);
                    if (RawResponse)
                    {
                        streamWriter.Write(",\"{0}\"", result.ResponseXml);
                    }
                    streamWriter.WriteLine();
                    recordCount++;
                }
            }
        }

        streamWriter.WriteLine("\"{0}\",\"{1}\"", ((int)CSVRecordType.Count).ToString("D2", CultureInfo.CurrentCulture), recordCount);

        Log.Info("CSV report written to '{0}'", fileName);
    }
    catch (IOException execption)
    {
        string errorMessage = string.Format(CultureInfo.CurrentCulture, "Unable to write XML report to '{0}'", fileName);
        Log.Error(errorMessage);
        Log.Error(exception.Message);
        throw new MyException(errorMessage, exception);
    }
    finally
    {
        if (null != streamWriter)
        {
            streamWriter.Close();
        }
    }
}

生成的文件在每行0到N包含一组记录,例如:

[Record Zero]
[Record One]
...
[Record N]

但是,生成的文件要么包含空值,要么包含文件末尾附加的不完整记录。例如:

[Record Zero]
[Record One]
...
[Record N]
[Lots of nulls]

[Record Zero]
[Record One]
...
[Record N]
[Half complete records]

这也发生在也使用 StreamWriter 类的单独代码段中。此外,生成的文件的大小都是 1024 的倍数。我无法在任何其他机器上重现此行为,并尝试重新创建环境。尽管相关方法的代码相同,但该应用程序的早期版本并未表现出此行为。

编辑:添加了额外的代码。

【问题讨论】:

  • 请添加工作写入代码(例如,您如何将字节写入StreamWriter)。
  • 我同意理查德的观点,所有的异常处理都是无关紧要的。所有相关代码都在[Write to stream].
  • 您能否在受影响的机器上单步调试调试器中的代码?您正在写入的日志在受影响的机器上看起来如何?在其他未受影响的机器上(对于相同的输入数据)有何不同?
  • 我想知道;这里有线程吗?
  • @Marc Gravell:有效的关注。一方面 streamWriter = new StreamWriter(filename);使用 FileShare.Read,从而锁定文件以进行写入,因此即使在多线程场景中,我们也不应该看到不完整的数据。另一方面,我在多线程场景中看到了很多一开始并不明显的奇怪现象。基于此,我承认如果这里存在多线程,那么如果它会影响所描述的行为,则值得仔细研究。

标签: c# windows windows-server-2008 .net-3.5 streamwriter


【解决方案1】:

在讨论流末尾的垃圾时,有两种情况会浮现在脑海中:

  1. 覆盖时不截断:如果覆盖文件但写入的数据较少,则必须截断它。打开文件时执行此操作会过载,或者您可以使用theStream.SetLength
  2. 写入缓冲区填充;特别是,最常见的错误是在使用MemoryStream 时 - 您必须要么 使用.ToArray()(以获得正确的字节数),要么 使用.GetBuffer() 但是只将.Length 字节复制出缓冲区(过去的任何内容都是垃圾)

我猜“1”在这里适用?

【讨论】:

  • streamWriter = new StreamWriter(filename);使用 FileMode.Create。这将始终截断文件。你知道这可能不是真的场景吗?
  • 我不同意@zespri。取自文档,在 StreamWriter(String) 的构造函数中:如果文件存在,则将其覆盖;否则,将创建一个新文件。
  • @Timores - 快速检查似乎表明它已被覆盖并(正确)截断。所以放弃这个想法。
猜你喜欢
  • 1970-01-01
  • 2015-10-02
  • 2016-12-22
  • 1970-01-01
  • 2012-02-09
  • 1970-01-01
  • 2014-09-27
  • 2016-02-26
  • 1970-01-01
相关资源
最近更新 更多