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
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.
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();
}
}
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.)
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());
}
)
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);
Related
I'm using the following lines of code in order to write credentials of users to a text file. It's supposed to create the directory inside AppData (which it does) but it doesn't write the credentials to the text file, it leaves it blank!
public void RegisterUserCreds()
{
string[] creds = { Username.Text, Password.Text };
string roaming = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
if (!Directory.Exists(roaming + "/Launcher"))
Directory.CreateDirectory(roaming + "/Launcher");
string specificFolder = roaming + "/Launcher/user_info.txt";
var fs = File.Open(specificFolder, FileMode.OpenOrCreate, FileAccess.ReadWrite);
var sw = new StreamWriter(fs);
sw.WriteLine(Username.Text);
fs.Close();
}
What's the problem? Thanks!
Just use the using statement when operating on streams:
public static void RegisterUserCreds()
{
string[] creds = { Username.Text, Password.Text };
string roaming = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
if (!Directory.Exists(roaming + "/Launcher")) Directory.CreateDirectory(roaming + "/Launcher");
string specificFolder = roaming + "/Launcher/user_info.txt";
using (var fs = File.Open(specificFolder, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var sw = new StreamWriter(fs))
{
sw.WriteLine(Username.Text);
}
}
}
In your code you were closing the file stream before the stream writer was able to flush the changes you want to write so the file was created empty.
You're closing the wrong stream. When you create new stream objects and pass an existing stream to the constructor, that new stream now "owns" the old stream. When you dispose of the newer stream it will automatically dispose of the older one.
In your situation, you're closing the "fs" stream, but the "sw" stream might not have actually written to it yet (it has it's own internal buffer). If you were to close the "sw" stream instead, it would flush it's buffer (into the "fs" stream), and then it would call fs.Dispose() for you to make sure it did the same thing.
There's a much better way, that would help you avoid doing things out-of-order like this, as well as make sure you're calling Dispose() even if exceptions get thrown (streams implement IDisposable, so you're supposed to always call their Dispose() method when you're done with them so they can internally "clean up"). The using statement is perfect for this, since it will call Dispose() even if an exception is thrown (it's a shortcut for wrapping the code with try/finally blocks):
using (var fs = File.Open(specificFolder, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var sw = new StreamWriter(fs))
{
sw.WriteLine(Username.Text);
}
}
This is the same as this:
try
{
var fs = File.Open(specificFolder, FileMode.OpenOrCreate, FileAccess.ReadWrite);
try
{
var sw = new StreamWriter(fs);
sw.WriteLine(Username.Text);
}
finally
{
sw.Dispose();
}
}
finally
{
fs.Dispose();
}
Even though sw.Dispose() will call fs.Dispose() for you, there is no harm in calling fs.Dispose() again. Why is it important to call Dispose()? Let's say an exception was thrown during sw.WriteLine() (e.g. out of disk space, I/O error, etc.)... the file would stay open until your app terminated. The using (or the try/catch version) would make sure the file was closed no matter what.
(side note: with streams, Dispose() and Close() do the same thing, you don't need to call both. Close() just calls Dispose() -- MS included a method called Close() because that was what people were used to with a file API, but the .NET IDisposable interface uses a method called Dispose())
(another side note: starting with .NET 4.5, many of the stream classes have an additional constructor that has a new "leaveOpen" parameter... passing true would tell that stream to NOT dispose of the original stream automatically)
So I File.Create a txt and then try to write a line on it like so:
StreamWriter.WriteLine("string");
but it just skips right past it like the line doesn't exist without any messages, warnings, or errors.
This is how to use streamwriter.
using (StreamWriter writetext = new StreamWriter("C:\\sample.txt", false))
{
writetext.WriteLine("Header");
}
using (StreamWriter writetext = new StreamWriter("C:\\sample.txt", true))
{
foreach (var data in _data)
{
writetext.WriteLine("Sample");
}
}
Notice the boolean (true or false) in the second parameter of StreamWriter class
new StreamWriter("C:\\sample.txt", true)
True: Append in file if exists
False: Overwrite file if exists
this is a bit of a long answer and example. But when I am writing commands to my digital assistant this is how I use StreamWriter.
StreamWriter sw;
StreamReader sr;
then in the code you do this
Settings.Default.ShellC = #"C:\Users\" + userName + "\\Documents\\Alexis Custom Commands\\Shell Commands.txt";
scpath = Settings.Default.ShellC;
if (!File.Exists(scpath))
{ sw = File.CreateText(scpath); sw.Write("My Documents"); sw.Close(); }
the textbox is the ShellC design name. you would add that to your properties then, in your using statements add the properties. then if you wanted to read them back then you would use
StreamReader
and then ference the file as
ArrayShellCommands = File.ReadAllLines(scpath);
I have an array list which contains 100 lines.
When i try to export it into a text file (txt), the output is only 84 lines and it stops in the middle of the 84th line.
When I looked at the file size it showed exactly sharp 4.00KB as if there is some kind of a limit to the stream writer. I tried using different parameters etc. but it kept happening.
Here is the code:
FileStream fs = new FileStream(path, FileMode.Create);
StreamWriter sw = new StreamWriter(fs);
ArrayList chartList = GetChart(maintNode);
foreach (var line in chartList)
{
sw.WriteLine(line);
}
fs.Close();
Console.WriteLine("Done");
Thanks for the help!
You need to call StreamWriter.Flush or set StreamWriter.AutoFlush to true. That said, if you use using statment, everything should work fine.
using(StreamWriter sw = new StreamWriter(fs))
{
ArrayList chartList = GetChart(maintNode);
foreach (var line in chartList)
{
sw.WriteLine(line);
}
}
Using statement calls Dispose which will flush the buffer to the FileStream and also closes the file stream. So you don't need to close it manually.
Then I recommend List<T> over ArrayList. ArrayList shouldn't be used, it is not type safe and should be avoided if you're in .Net2.0 or greater.
Also consider using File.WriteAllLines method, so that you don't need these many lines of code. Everything is managed by WriteAllLines method itself.
Here is my code. :
FileStream fileStreamRead = new FileStream(pathAndFileName, FileMode.OpenOrCreate, FileAccess.Read, FileShare.None);
FileStream fileStreamWrite = new FileStream(reProcessedFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
StreamWriter sw = new StreamWriter(fileStreamWrite);
int readIndex = 0;
using (StreamReader sr = new StreamReader(fileStreamRead))
{
while (!sr.EndOfStream) {
Console.WriteLine("eof" + sr.EndOfStream);
readIndex++;
Console.WriteLine(readIndex);
string currentRecord = "";
currentRecord = sr.ReadLine();
if (currentRecord.Trim() != "")
{
Console.WriteLine("Writing " + readIndex);
sw.WriteLine(currentRecord);
}
else {
Console.WriteLine("*******************************************spaces ***********************");
}
}
It is cutting off 2 lines with one test file and half a line, and then 1 line and half a line with the other test file I am running it against.
I am not a streamreader/writer expert you can probably see.
Any ideas or suggestions would be greatly appreciated as this is driving me batty. I am sure it is me using these incorrectly.
You are missing Flush/Close or simply using for your writer.
using(FileStream fileStreamWrite =
new FileStream(reProcessedFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
{
using(StreamWriter sw = new StreamWriter(fileStreamWrite))
{
// .... write everything here
}
}
Right after the closing brace of the using statement, do this:
sw.Flush();
sw.Close();
There, that should do it.
You need to Flush your StreamWriter. A StreamWriter has a buffer, and it writes to disk only when the buffer is full. By flushing at the end you make sure all the text in the buffer is written to the disk.
In addition to other answers (use using, and/or flush/close), would say that they do not actually respond to the question: "why it may cut several lines."
I have an idea on subject that it is related to a fact that you use StreamReader and call EndOfStream twice: in a while loop header, and another inside it.
The only possible way of understanding if the stream ends is try to read some data from it. So I suspect EnfOfStream does it, and reading it twice, may create a problem in stream processing.
To resolve an issue:
Or use simple TextReader, considering that you are reading text file (seems to me)
Or change your logic to call only once, so no more call to Console.WriteLine("eof" + sr.EndOfStream);
Or change your logic, so do not use EndOFStream at all, but read line by line till the line is null.
You're not using StreamWriter properly. Also, since you're always reading lines, I would use a method that already does all that for you (and manages it properly).
using (var writer = new StreamWriter("path"))
{
foreach(var line in File.ReadLines("path"))
{
if (string.IsNullOrWhiteSpace(line))
{ /**/ }
else
{ /**/ }
}
}
... or ...
/* do not call .ToArray or something that will evaluate this _here_, let WriteAllLines do that */
var lines = File.ReadLines("path")
.Select(line => string.IsNullOrWhiteSpace(line) ? Stars : line);
var encoding = Encoding.ASCII; // whatever is appropriate for you.
File.WriteAllLines("path", lines, encoding);
My code in C# (asp.net MVC)
StreamWriter tw = new StreamWriter("C:\\mycode\\myapp\\logs\\log.txt");
// write a line of text to the file
tw.Write("test");
The file is created but is empty. No exception is thrown. I have never seen this before and I am stuck here; I just need to write some debugging output.
Please advise.
StreamWriter is buffered by default, meaning it won't output until it receives a Flush() or Close() call.
You can change that by setting the AutoFlush property, if you want to. Otherwise, just do:
StreamWriter tw = new StreamWriter("C:\\mycode\\myapp\\logs\\log.txt");
// write a line of text to the file
tw.Write("test");
tw.Close(); //or tw.Flush();
You need to either close or flush the StreamWriter after finishing writing.
tw.Close();
or
tw.Flush();
But the best practice is to wrap the output code in a using statement, since StreamWriter implements IDisposable:
using (StreamWriter tw = new StreamWriter("C:\\mycode\\myapp\\logs\\log.txt")){
// write a line of text to the file
tw.Write("test");
}
Neither flushed nor closed nor disposed.
try this
using (StreamWriter tw = new StreamWriter(#"C:\mycode\myapp\logs\log.txt"))
{
// write a line of text to the file
tw.Write("test");
tw.Flush();
}
or my preference
using (FileStream fs = new FileStream( #"C:\mycode\myapp\logs\log.txt"
, FileMode.OpenOrCreate
, FileAccess.ReadWrite) )
{
StreamWriter tw = new StreamWriter(fs);
tw.Write("test");
tw.Flush();
}
Use
System.IO.File.WriteAllText(#"path\te.txt", "text");
FileStream fs = new FileStream("d:\\demo.txt", FileMode.CreateNew,
FileAccess.Write);
StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.ASCII);
int data;
sw.Write("HelloWorld");
sw.Close();
fs.Close();
The problem is when StreamWriter Object is created with reference of FileStream Object , SW object will be always expecting some data till SW object is Closed.
So After using sw.Close();
Your Opened File will get closed and get ready for showing Output.
Ya in VB.net this was not needed but it seems with CSharp you need a Writer.Flush call to force the write. Of course Writer.Close() would force the flush as well.
We can also set the AutoFlush Property of the StreamWriter instance:
sw.AutoFlush = true;
// Gets or sets a value indicating whether the StreamWriter
// will flush its buffer to the underlying stream after every
// call to StreamWriter.Write.
From: http://msdn.microsoft.com/en-us/library/system.io.streamwriter.autoflush(v=vs.110).aspx
an alternative
FileStream mystream = new FileStream("C:\\mycode\\myapp\\logs\\log.txt",
FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter tw = new StreamWriter(mystream);
tw.WriteLine("test");
tw.close();
Try to close the file or add \n to the line such as
tw.WriteLine("test");
tw.Close();