Search code examples
c#csvstreamwriter

Why does the StreamWriter fail to write strings of a length less than or equal to 3 to .csv files?


_flagImageSources is a string array of 195 file paths to .png files of flags. Each file path is of the format C:\Users\user\someFolder\...\Flags\xx.png, where xx is a country-code top level domain (e.g. .uk for the United Kingdom).

When executing the code in "Code Snippet 1" the output to the initially empty output.csv file is as shown in "CSV File Output 1":

Code Snippet 1

_streamWriter = new StreamWriter("output.csv");

string str;
string outputText;
for (int i = 0; i < _flagImageSources.Length; i++)
{
  str = _flagImageSources[i];
  outputText = str.Substring(68, 6);
  _streamWriter.WriteLine(outputText);
}

CSV File Output 1

ae.png
af.png
⋮
zw.png

However, the moment I reduce the sub-string length from 6 to 3 (or less), I get the output the out put is an empty .csv file.

Code Snippet 2

_streamWriter = new StreamWriter("output.csv");

string str;
string outputText;
for (int i = 0; i < _flagImageSources.Length; i++)
{
  str = _flagImageSources[i];
  outputText = str.Substring(68, 3);
  _streamWriter.WriteLine(outputText);
}

CSV File Output 2: "an empty file"

I do not understand why I cannot write strings of a length of 3 (or less) to my .csv file. Does anyone understand why this is and how it can be solved?


Solution

  • Because you're not flushing the output or properly closing and then disposing the stream. You need to either set AutoFlush to true or manually call .Flush() and then .Close() and ultimately .Dispose().

    _streamWriter = new StreamWriter("output.csv");
    
    string str;
    string outputText;
    for (int i = 0; i < _flagImageSources.Length; i++)
    {
      str = _flagImageSources[i];
      outputText = str.Substring(68, 3);
      _streamWriter.WriteLine(outputText);
    }
    
    _streamWriter.Flush(); 
    _streamWriter.Close();
    // prev. two lines are redundant b/c dispose will accomplish this.
    _streamWriter.Dispose();
    

    All this will happen automatically if you use the Disposable pattern, which is the preferred approach:

    using (var sw = new StreamWriter("output.csv"))
    {
        for (int i = 0; i < _flagImageSources.Length; i++)
        {
          string str = _flagImageSources[i];
          string outputText = str.Substring(68, 3);
          sw.WriteLine(outputText);
        }   
    }