How to discard changes of FileStream? - c#

I have a simple question. I may be right but I want you people to ensure it since I am new at .NET.
StreamWriter SW = new StreamWriter(strFile);
SW.writeline("Hello");
SW.writeline("How are you?");
But in the middle, I don't want to save the data present in the SW variable, so what should I do? Should I use delete or detach?
Would reassigning memory to SW again cause any problems?

The StreamWriter class writes directly to the file.
Once you call WriteLine, it's too late to go back.

delete and detach do not undo changes. WriteLine writes directly to the file. You might be interested in using StringWriter for this purpose though.
StringWriter SW = new StringWriter();
SW.writeline("Hello");
SW.writeline("how r u");
if (commit == true)
File.WriteAllText (strFile, SW.ToString());
// else simply discard SW
Out of curiosity, why you would want to write something and then later discard it?

Related

File already being accessed error

I have a few files in \AppData\Roaming that my app is writing to. I create the files when the application starts like this:
private void Form1_Load(object sender, EventArgs e)
{
DirectoryInfo _File = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), #"MyApp\myfile.txt"));
}
Later, when I write to the file with a button click, I get an error saying that the file is already in use and cannot be accessed. How would I fix this?
The code to write to the file is correct because when I remove the code above and make the files myself, the application writes to them without any issues. Therefore, I dont think the problem is with the code I use to write to the files. But, here it is for reference:
var myfile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), #"MyApp\myfile.txt"));
StreamWriter sw = new StreamWriter(myfile);
sw.WriteLine(textBox1.text);
sw.Close();
Thanks in advance for any help!
There are a few concepts at play here and I am not sure that we have enough information to definitively address the root problem, but I will give you a few pointers.
You need to be aware of the FileMode, FileAccess and FileShare enumerations.
The first, FileMode, specifies what you intend to do with regard to the file's existence. There are various options, documented in the link above. mI don't think that you have a problem here, but it bears mentioning.
The second, FileAccess, concerns your intended interaction with the file (read, write, or both). If you ask for access to read, then anyone else who opens the file or had it open already (including that web browser control) must have allowed sharing with other readers.
The final one, FileShare, defines who you are willing to share access to the file with. You can specify that others can read it, others can write to it, both, or neither.
The code that you are using is accessing the file using the very simplest defaults, which may be incompatible with the WebBrowser's access mode. Here's what I'd suggest instead:
var myfile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), #"MyApp\myfile.txt"));
using (var fs = new FileStream(myfile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite)) {
using (var sw = new StreamWriter(fs)) {
// You probably want to move to the end of the file before writing...
fs.Seek(0, SeekOrigin.End);
sw.WriteLine(textBox1.text);
sw.Close();
}
}
This very clearly expresses your intent, as well as the fact that you are willing to share with others who might read or write (we know the webbrowser will not write to the file, but for some reason maybe it is trying to open it with write intent anyway).
For file operations (as well as anytime your are accessing unmanaged resources) your best bet is to only grab a handle to the file long enough to perform the operation you want and then release it.
In your case, you are opening the resource, then trying to open it again later. Change this. Don't create the files until you are actually going to do something with it. Also, look into the USING clause. You want to release it as soon as you are done reading or writing from it.
Try to Access the FileInfo object to create/append/write files as follows, the file is already been taken by FileInfo class,
use as following,
FileInfo fi1 = new FileInfo(path);
//Create a file to write to.
using (StreamWriter sw = fi1.CreateText())
{
sw.WriteLine("Hello");
sw.WriteLine("And");
sw.WriteLine("Welcome");
}
//Open the file to read from.
using (StreamReader sr = fi1.OpenText())
{
string s = "";
while ((s = sr.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
Try using using.
using (StreamWriter sw = new StreamWriter(myfile))
{
sw.Write(textBox1.text);
}

writing data to a file with the result is not as expected

I use this code to write a string to a file.
var fs = File.Open(path, FileMode.OpenOrCreate, FileAccess.Write);
var sw = new StreamWriter(fs, Encoding.UTF8);
sw.Write(dataString);
fs.Flush();
sw.Flush();
sw.Close();
When I debug it, I see the dataString correct. However, after writing to a file, there are some strings have wrong orders. Should I add a thread Sleep after writing data to the file because right after writing data to the file, I read it back for other process.
OR probably there is better way to write a string to a file?
Thanks in advance.
OR probably there is better way to write a string to a file?
Yes, there's a simpler way. Use File.WriteAllText or File.AppendAllText.
File.WriteAllText("output.txt", text, Encoding.UTF8);
Apart from being more concise, another advantage is that the file will be correctly closed even if there is an exception. However, I doubt that it will change the order in which the data is written to the file.

C# add text to text file without rewriting it?

Let's say I have the following code:
StreamWriter sw = new StreamWriter(File.OpenWrite(Path));
sw.Write("Some stuff here");
sw.Dispose();
This code replaces the contents of the file with "Some stuff here," however I would like to add text to the file rather than replacing the text. How would I do this?
You could use the File.AppendAllText method and replace the 3 lines of code you have with:
File.AppendAllText(Path, "blah");
This way you don't have to worry about streams and disposing them (even in the event of an exception which by the way you are not doing properly) and the code is pretty simple and straightforward to the point.
You need to tell the StreamWriter you want to append:
var sw = new StreamWriter(path, true);
File.OpenWrite doesn't support appending.
Check out System.IO.File.AppendAllText
http://msdn.microsoft.com/en-us/library/ms143356.aspx
You can do what you want doing something like
File.AppendAllText(path, text);
There is a StreamWriter constructor which takes a bool as the 2nd parameter, which instructs the writer to append if true.
Use the append parameter:
StreamWriter sw = new StreamWriter(Path, true);
http://msdn.microsoft.com/en-us/library/36b035cb.aspx
To append text to a file, you can open it using FileMode.Append.
StreamWriter sw = new StreamWriter(File.Open(Path, System.IO.FileMode.Append));
This is just one way to do it. Although, if you don't explicitly need the StreamWriter object, I would recommend using what others have suggested: File.AppendAllText.

Stream StringBuilder to file

I need to create a large text document. I currently use StringBuilder to make the document and then call File.WriteallText(filename,sb.ToString). Unfortunately, this is now starting to throw out of memory exceptions.
Is there a better way to stream a StringBuilder to file or is there some other technique I should be using?
Instead of using StringBuilder, try using TextWriter (which has a broadly similar API, but which can write to a number of underlying destinations, including files) - i.e.
using(TextWriter writer = File.CreateText(path))
{
// loop etc
writer.Write(...);
}
More generally, it is worth separating the code that knows about files from the code that knows about how to write the data, i.e.
using(var writer = File.CreateText(path))
{
Serialize(writer);
}
...
void Serialize(TextWriter writer)
{
...
}
this makes it easier to write to different targets. For example, you can now do in-memory too:
var sw = new StringWriter();
Serialize(sw);
string text = sw.ToString();
The point being: your Serialize code didn't need to change to accomodate a different target. This could also be writing directly to a network, or writing through a compression/encryption stream. Very versatile.
Just use a StreamWriter that writes to a FileStream:
using (StreamWriter writer = new StreamWriter("filename.txt")) {
...
}
This will of course mean that you can't change the text that is already written, like you can do in a StringBuilder, but I assume that you are not using that anyway.
Why not streaming directly into the stream?
You could use the TextWriter.
You can use StreamWriter and write to the file directly.

StreamWriter, FileStream and windows file locks

I am writting a small app to export and import data from database using .NET DataSets and XML and as part of that I am doing the following.
StreamWriter sw = new StreamWriter(file);
sw.Write(xml.OuterXml);
sw.Close();
The problem is that the close method closes the FileStream (file parameter passed to constructor) but doesn't release the file lock. The file is one that the program I have written creates so I know nothing else is locking it.
Is there something I am doing wrong or is this a windows bug?
EDIT
Yes 'file' is a FileStream object and I naively assumed that calling close() on the stream that wraps the files stream would also cleanup and dispose the underlying file stream by calling the FileStream.close method. But i'm not sure about that any more.
Wrapping this in a using block still has the same effect.
One extra note is that the filestream object is created in a different method but that shouldn't make any difference
Try using this instead:
using (StreamWriter sw = new StreamWriter(file))
sw.Write(xml.OuterXml);
(or try to call sw.Dispose() manually)
Would it help to wrap the file stream in a using or simply use the overloaded method for creating the stream writer:
using (FileStream fs = new FileStream("path", FileMode.Append))
using (StreamWriter sw = new StreamWriter(fs))
{
sw.Write(xml.OuterXml);
sw.Close();
}
or:
using (StreamWriter sw = new StreamWriter("path"))
{
sw.Write(xml.OuterXml);
sw.Close();
}
I suspect the problem is in the code creating or using the FileStream. Perhaps you could elaborate on how you use the FileStream object you create.

Categories