-2

I am using the StreamWriter to create a file and to write some text to that file. In some cases I have no text to write via StreamWriter, but the file was already created when StreamWriter was initialized.

using (StreamWriter sw = new StreamWriter(@"C:\FileCreated.txt"))
{

}

Currently I am using the following code, when StreamWriter is closed, to check if the FileCreated.txt content is empty, if it is delete it. I am wondering if there is a more elegant approach than this (an option within StreamWriter perhaps)?

if (File.Exists(@"C:\FileCreated.txt"))
{
   if (new FileInfo(@"C:\FileCreated.txt").Length == 0)
   {
      File.Delete(@"C:\FileCreated.txt");
   }
}

By the way, I must open a stream to write before I can check if there is any text because of some other logic in the code.

jadrijan
  • 1,438
  • 4
  • 31
  • 48
  • where is the source of the text that you want to write? – Sam I am says Reinstate Monica Jul 18 '14 at 20:31
  • 1
    why don't you set a boolean flag to true? – Daniel A. White Jul 18 '14 at 20:31
  • 1
    Is it not possible to determine if the file will have any contents before creating the `StreamWriter`? – CodingGorilla Jul 18 '14 at 20:31
  • 1
    Can you put an if statement to check if there is any data before you enter the using clause – cup Jul 18 '14 at 20:33
  • This answer is interesting too: http://stackoverflow.com/a/18125193/103167 although comments indicate it isn't as robust as the direct Win32 approach. – Ben Voigt Jul 18 '14 at 21:21
  • 1
    I don't exactly see why this is a duplicate, the question is not "how to delete a file". Anyway, another solution would be to introduce a "NonemptyFileStreamWriter" class that overrides 'Dispose(bool disposing)', flushes the stream and BaseStream, checks the BaseStream.Length == 0, then deletes the file if empty after the call to base.Dispose(disposing). This avoids the need to buffer the entire file in memory. – dbc Jul 18 '14 at 22:00

3 Answers3

2

If you want to take input from the user bit by bit, you can make your source a StringBuilder, and then just commit to disk when you're done

StringBuilder SB = new StringBuilder();
...
SB.AppendLine("text");
...
if(SB.Length > 0)
    File.WriteAllLines(SB.ToString());
  • 3
    Quoting the author of the question: `By the way, I must open a stream to write before I can check if there is any text because of some other logic in the code.` – Barak Itkin Jul 18 '14 at 20:34
  • 1
    It's not wrong to point out a likely mistaken assumption that the given approach is correct. The OP's approach probably ISN'T correct. – Iucounu Jul 18 '14 at 20:39
  • @LightningIsMyName The op also probably edited that into his question within the grace period. Probably in responce to comments left by me and others – Sam I am says Reinstate Monica Jul 18 '14 at 20:43
  • You are all correct, but the answer you have given me is not what I am looking for. Lets assume that the StreamWriter MUST BE opened prior to checking whether there is text to be written, is there another approach than the one I gave? – jadrijan Jul 18 '14 at 20:44
  • 1
    @jadrijan Why must the stream-writer be opened? – Sam I am says Reinstate Monica Jul 18 '14 at 20:44
  • @Sam I am The info was not edited within the grace period. It was there from start as I knew that some would answer as you did. – jadrijan Jul 18 '14 at 20:45
  • Opening a File is relatively costly, I would try to avoid that. – H H Jul 18 '14 at 20:52
1

Delaying opening the file until the first output would solve this problem, but it might create a new one (if there's a permission error creating the file, you won't find out until later, maybe when the operator is no longer at the computer).

Your current approach is decent. I don't see the need to test File.Exists, though, if you just closed a stream to it. Also consider the race condition:

  1. You find that the file is zero-length
  2. Another process writes to the file
  3. You delete the file

Also consider that you might have permission to create a file, and not to delete it afterwards!

Doing this correctly requires using the raw Win32 API, as I described in a previous answer. Do note that a .NET stream could be used for the first file handle, as long as you specify the equivalent of FILE_SHARE_WRITE.

Community
  • 1
  • 1
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 2
    This seems a like its addressing a symptom instead of the cause. The real issue seems to be that the file should never have been created (I realize the user says they must do it this way, but that's hard to believe). – Michael Jul 18 '14 at 20:40
  • @Michael: So my parenthetical note wasn't clear, or wasn't convincing? – Ben Voigt Jul 18 '14 at 20:45
  • @BenVoight Yes, you're right. I responded prematurely. – Michael Jul 18 '14 at 20:56
0

Revisit your assumptions, i.e. that you must open the stream before checking for content. Simply reorganize your logic.

Iucounu
  • 1,630
  • 1
  • 20
  • 31