2010-06-14 15 views
1

Je vois un comportement étrange en utilisant l'écriture classe StreamWriter données supplémentaires à un fichier en utilisant ce code:StreamWriter ajoute des données aléatoires

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(); 
     } 
    } 
} 

Le fichier produit contient un ensemble d'enregistrements sur chaque ligne 0 à N, pour exemple:

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

Toutefois, le fichier produit contient des enregistrements NULL ou incomplets à partir du fichier ajouté à la fin. Par exemple:

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

ou

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

Cela se produit également dans des morceaux de code qui utilisent également la classe StreamWriter. De plus, les fichiers produits ont tous des tailles qui sont des multiples de 1024. J'ai été incapable de reproduire ce comportement sur une autre machine et j'ai essayé de recréer l'environnement. Les versions précédentes de l'application ne présentaient pas ce comportement malgré le même code pour les méthodes en question.

EDIT: Ajout de code supplémentaire.

+3

Veuillez ajouter un code d'écriture fonctionnel (par exemple, comment écrire des octets dans 'StreamWriter'). – Richard

+0

Je suis d'accord avec Richard, tout ce traitement d'exception est hors de propos. Tout le code pertinent est dans '[Write to stream]'. –

+0

Êtes-vous capable de parcourir le code dans le débogueur sur la machine affectée? A quoi ressemble le journal que vous écrivez dans la machine concernée et en quoi est-il différent (pour les mêmes données d'entrée) sur d'autres machines qui ne sont pas affectées? –

Répondre

3

Il y a deux scénarios qui sautent à l'esprit quand on parle de déchets à la fin d'un cours d'eau:

  1. pas tronquer quand sur l'écriture: si vous écrasez un fichier, mais écrire moins de données, vous devez tronquer il. Il y a une surcharge à faire lors de l'ouverture du fichier, ou vous pouvez utiliser theStream.SetLength.
  2. remplissage de tampon d'écriture; en particulier, l'erreur la plus courante est lorsque vous utilisez MemoryStream - vous devez soit utilisation .ToArray() (pour obtenir le nombre correct d'octets), ou utilisation .GetBuffer()mais seule copie .Length octets de la mémoire tampon (quoi que ce soit passé est poubelle)

Je suppose que "1" s'applique ici?

+0

streamWriter = new StreamWriter (nom de fichier); utilise FileMode.Create. Cela tronquera toujours le fichier. Connaissez-vous un scénario où cela pourrait ne pas être vrai? –

+0

Je ne suis pas d'accord avec @zespri.Extrait des docs, dans le constructeur de StreamWriter (String): Si le fichier existe, il est écrasé; sinon, un nouveau fichier est créé. – Timores

+0

@Timores - une vérification rapide semble montrer qu'elle est écrasée et (correctement) tronquée. Alors grattez cette idée. –