31

I am trying to save a file using DialogResult and StringBuilder. After making the text, I am calling the following code to save the file:

 if (dr == DialogResult.OK) { StreamWriter sw = new StreamWriter(saveFileDialog1.FileName); sw.Write(sb.ToString()); sw.Close(); } 

I tried to add the second parameter to StreamWriter as Encoding.UTF8 but since the first argument is a string rather than a Stream, it does not compile it.

How can I convert that string to a stream to be able to pass the second parameter as Encoding?

The reason for this, is that somewhere in my text I have µ but when the file is saved it shows like μ so the µ is getting screwd!

Thanks

5 Answers 5

55

Just wrap it in a FileStream.

StreamWriter sw = new StreamWriter( new FileStream(saveFileDialog1.FileName, FileMode.Open, FileAccess.ReadWrite), Encoding.UTF8 ); 

If you want to append, use FileMode.Append instead.

You should also call Dispose() on a try/finally block, or use a using block to dispose the object when it exceeds the using scope:

using( var sw = new StreamWriter( new FileStream(saveFileDialog1.FileName, FileMode.Open, FileAccess.ReadWrite), Encoding.UTF8 ) ) { sw.Write(sb.ToString()); } 

This will properly close and dispose the streams across all exception paths.

UPDATE:

As per JinThakur's comment below, there is a constructor overload for StreamWriter that lets you do this directly:

var sw = new StreamWriter(saveFileDialog1.FileName, false, Encoding.UTF8); 

The second parameter specifies whether the StreamWriter should append to the file if it exists, rather than truncating it.

Sign up to request clarification or add additional context in comments.

7 Comments

it works but adds an extra step. StreamWriter has already a constructor which accpets an enconding
@Inu - Yes, I'm using that constructor: StreamWriter(Stream, Encoding)
I don't think the FileStream will be disposed correctly, I think you need two nested using blocks.
@TimAbell When the StreamWriter wrapper is disposed, it calls Close() on the underlying stream, which implicitly disposes the child stream.
ah, okay, useful. :-)
|
14

There is a constructor for filename, appendMode, encoding.

With a proper using block it looks like:

if (dr == DialogResult.OK) { using (StreamWriter sw = new StreamWriter(saveFileDialog1.FileName, false, Encoding.UTF8)) { sw.Write(sb.ToString()); //sw.Close(); } } 

Comments

2

There is a StreamWriter(string path, bool append, Encoding encoding) constructor - you could just explicitly specify the append flag too?

I said you ought to wrap your StreamWriter in a using too, i.e.

if (dr == DialogResult.OK) { using(StreamWriter sw = new StreamWriter(saveFileDialog1.FileName, false, Encoding.UTF8)) { sw.Write(sb.ToString()); sw.Close(); } } 

although realistically this won't make any difference here. This effectively puts a try/finally around the code so that the StreamWriter will get cleaned up (it'll call sw.Dispose() even if an exception gets thrown in the meantime. (Some people will say this also means you no longer need the .Close since the Dispose will take care of that too but I prefer to have it anyway.)

9 Comments

Sorry I dont know what is wrapping! would be nice to see a bit of code please!
"although realistically this won't make any difference here" - this is incorrect. You may be able to open the file, but then find that the disk is full and the sw.Write throws an exception. There are other exceptional cases too. You should ALWAYS wrap any code that deals with IDisposable objects in a using or try/finally. You should also never call both Close and Dispose because it can result in a double-dispose, which will throw an ObjectDisposedException.
@Polynomial: I can understand dispose calling close but surely close shouldn't dispose of an object should it?
@Chris - The Close() method disposes the FileStream. I decompiled FileStream.Close() from mscorlib and got this: public virtual void Close() { Dispose(true); GC.SuppressFinalize(this); } Here's the full code: pastebin.com/n9d8TKns
@Polynomial I think Chris meant 'dispose' as in 'force GC'. That's what I meant by 'realistically' - it's only rare cases that will throw exceptions there (since StringBuilder.ToString() shouldn't) and in that case your app will have other problems - although I suppose that's why they're 'Exceptions'. No, the dispose documentation says a Dispose method must be callable multiple times without throwing an exception, and I've seen no documentation that says Close == Dispose always.
|
1

setting UTF8 encoding working with Arabic font is the best thing I did:

 using (var sw = new StreamWriter( new FileStream(temporaryFilePath, FileMode.Create, FileAccess.ReadWrite), Encoding.UTF8)) { sw.Write(sb.ToString()); } ) 

Comments

1

The easiest way is to use the right constructor.

StreamWriter(String, Boolean, Encoding) 

Initializes a new instance of the StreamWriter class for the specified file by using the specified encoding and default buffer size. If the file exists, it can be either overwritten or appended to. If the file does not exist, this constructor creates a new file.

C#

public StreamWriter (string path, bool append, System.Text.Encoding encoding); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.