I am still newbie to C# and I'm making a test program that writes the DateTime.Now every second. I tried using this and it worked:
StreamWriter sw = new StreamWriter("D:\Hello.txt", true);
sw.WriteLine(DateTime.Now);
sw.Close();
However, when I tried including a FileStream, it didn't work. What seems to be the problem? Here's my code:
FileStream fs = new FileStream(#"D:\Hello.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(DateTime.Now);
sw.Close();
fs.Close();
Note: I am using a timer, it executes the code every second..
Update:
I tried placing the code(the one that has the filestream) inside a button (w/out timer). Whenever I clicked the button, it just replaces the line in the textfile.. This is a code that appends a text to the textfile:
StreamWriter sw = new StreamWriter("D:\Hello.txt", true);
How will I do it in a filestream? I cannot use FileMode.Append in FileStream because it required=s the FileAccess to be write-only.
Since you are executing the code every second then its not a good idea to create FileStream and StreamWriter object everytime, because sometimes the file will remain under lock condition and the filestream will miss to acquire the handle.
As you are writing to single file its good to initialize a FileStream and subsequent StreamWriter in the constructor while leaving the refrence to them in class scope;then calling it every second on a thread for sw.WriteLine(DateTime.Now); should help.
And further never miss try catch in a filestream. They help a lot to locate the discrepancies.
May be try to use File?
File.AppendAllText(#"D:\Hello.txt", DateTime.Now.ToString());
or
File.WriteAllText(#"D:\Hello.txt", DateTime.Now.ToString());
to overwrite
You should use something like this because it works fine for me. If it does not work for you, you have to add more details
using (var fs = new FileStream("path", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
{
fs.Seek(0, SeekOrigin.End);
using (StreamWriter sw = new StreamWriter(fs) { AutoFlush = true })
{
sw.WriteLine("my text");
}
}
But remember I would not create it every second. Why don t you store a Streamwriter object as field when you call Timer.Start?
So you would not have to create it every second. (rememer to dispose it when you stop the timer)
Should work:
FileStream fs = new FileStream(#"D:\Hello.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(DateTime.Now);
sw.Flush();
sw.Close();
fs.Close();
I already solved it.. :) I just have to use FileMode.Append, FileAccess.Write as an argument in the filestream. Reason for not doing FileMode.Append earlier is because it needs FileAccess to be Write only. I thought switching the FileAcess to Write only will prevent the user from reading the file. So stupid of me.. This is my code:
private void timer1_Tick(object sender, EventArgs e)
{
FileStream fs = new FileStream(#"D:\Hello.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(DateTime.Now);
lbTimer.Items.Add(DateTime.Now);
sw.Close();
fs.Close();
}
Last question, what is setting the FileAccess to Write only for when you can still read it?
Try calling StreamWriter.Flush() before StreamWriter.Close().
You might wanna look here
How to: Write to a Text File (C# Programming Guide)
http://msdn.microsoft.com/en-us/library/8bh11f1k.aspx
Related
It's like that that right now I'm trying to open my file with FileStream where I saw a little further into the code to use streamwriter compared to writing it into the file every time it goes through Streamwriter.
When it runs through the first time then do it without any problems but as soon as I run it through the second lap. then it fails where it then writes "Stream was not writable"
int count = 0;
using (FileStream fs = new FileStream(#"C:\jpe\Projekt\Utilities\Icons\Icons/WriteLines.txt", FileMode.Append, FileAccess.Write))
{
foreach (SPSite tmpSite in tmpRootColl)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(string.Format("Title {0}", tmpSite.RootWeb.Title));
//Enumerate through each sub-site
foreach (SPWeb tmpWeb in tmpSite.AllWebs)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(string.Format("Title {0}", tmpWeb.Title));
//Enumerate through each List
foreach (SPList tmpList in tmpWeb.Lists)
{
if (tmpList.BaseTemplate == SPListTemplateType.DocumentLibrary)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(string.Format("Title {0}", tmpList.Title));
using (StreamWriter outputFile = new StreamWriter(fs)) //Errors come here when it runs the second round through.
{
await outputFile.WriteLineAsync($"{tmpSite.RootWeb.Title} - {tmpList.Title} {count}");
}
count++;
}
}
}
Console.WriteLine("__________________________________________________");
}
}
What I want to achieve with this is that it has to insert text into the file every time it runs through StreamWriter. It should not first make it to the last when it is finished.
i have read:
https://stackoverflow.com/a/7306243/18055701
C# how to update file(leave old data)
Currently you're creating a StreamWriter, writing to it, and disposing it for every list, this is what's causing the issue. Internally the Dispose method closes the underlying stream causing the exception. To solve this we can do one of 2 things
Tell our StreamWriter to not close the underlying stream.
Not dispose our StreamWriter until we're also done with the underlying stream.
Here's how to do #1:
Simply replace your call to the constructor with this
using (StreamWriter outputFile = new StreamWriter(fs, leaveOpen: true))
Here's how to do #2:
Move the using (StreamWriter ... block up to be "one level deeper" than the using (FileStream ... block
using (FileStream fs = new FileStream("..."))
{
using (StreamWriter outputFile = new StreamWriter(fs))
{
// Your foreach loops here
}
}
Personally I'd go with #2 as I'm not a fan of creating and disposing objects in a loop
Assuming you are using at least .NET framework 4.5.
The StreamWriter closes the base stream in its Dispose() method. You can adjust that behavior by using another construcor: https://learn.microsoft.com/en-us/dotnet/api/system.io.streamwriter.-ctor?view=netcore-3.1#system-io-streamwriter-ctor(system-io-stream-system-text-encoding-system-int32-system-boolean)
I used the following code to write on *.txt file, but nothing happens. Even, there is no exception.
FileStream fs = new FileStream(#"D:\file.txt",FileMode.OpenOrCreate,FileAccess.Write,FileShare.None); //Creating a stream with certain features to a file
StreamWriter writer = new StreamWriter(fs); //Use the fs to write
// writer.WriteLine(Text.Text); none of the following methods works
writer.Write("aaaaaaaaaaaa");
fs.Close();
Thanks
Try to enclose it in a using block like this:
using ( FileStream fs = new FileStream(#"D:\file.txt",FileMode.OpenOrCreate,FileAccess.Write,FileShare.None))
using (StreamWriter fw = new StreamWriter(fs))
{
fw.Write("aaaaaaaaaaaa");
}
A StreamWriter buffers data before writing it to the underlying stream. You need to flushes the buffer by disposing the StreamWriter
Is there anything wrong with this piece of code ? It's opening the file , yet it doesn't write on it.
fl = new FileStream(path, FileMode.OpenOrCreate);
sw = new StreamWriter(fl);
sw.WriteLine("Hello ");
The proper way of doing this would be:
using (StreamWriter sw = new StreamWriter(new FileStream(path, FileMode.OpenOrCreate)))
sw.WriteLine("Hello ");
This will call sw.Flush(), sw.Close() and sw.Dispose().
StreamReader uses a buffer. You can force the output by using Flush(), but in most cases you should just make sure you use using() which will call Dispose at the end and flush all remaining data.
Have you tried to call Flush method?
sw.Flush();
I'm not sure if it's possible. I usually create txt files like this:
FileStream fs = new FileStream("c:\\textFile.txt", FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
but instead of using "c:\textFile.txt" I want to create a file using a string name. Is there a way to do it?
Of course. The first argument to the FileStream constructor takes a string. You've just passed it a string literal (defined in your source code file). It sounds like you want to pass a string variable instead:
string path = // get string from somewhere. A file save dialog, maybe?
FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
May I suggest that you spend some time with a C# tutorial? Microsoft has some good tutorials and samples. With all due respect, and we were all there once, you've got some holes in your knowledge that will trip you up.
I'm not sure I'm following what you're asking for. You just asked if u could do that:
string filename = "c:\\textFile.txt";
FileStream fs = new FileStream(filename, FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
or as you specified
FileStream fs = new FileStream(YourTextBox.Text, FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
I have a windows service that writes out log file entries to an XML log file. I maintain a handle to the log file while the service is operational, and close, flush and dispose of it when the service is stopped. The file write operations are by the service only, and I have the filestream open in FileAccess.ReadWrite while sharing is set to FileShare.Read. I would like to be able to open and view this file with an XmlRead() call by another application, but I get an error stating the file is being used by another process. I had read another post on this and was under the impression this was possible: Other Thread.
The writer in use is flushed, closed, and disposed of, and each write the filestream is flushed. Is this just not possible in .Net, or have I perhaps done something wrong? A cutdown version of the code follows:
if (_logFS == null)
_logFS = new FileStream(_fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
if (!initFile)
{
_logFS.Seek(-13, SeekOrigin.End);
}
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
using (XmlWriter writer = XmlWriter.Create(_logFS, settings))
{
if (initFile)
{
writer.WriteRaw("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n");
writer.WriteStartElement("Entries", "http://www.abcdefg.com);
}
writer.WriteStartElement("Exception");
// write out some stuff here.
writer.WriteEndElement();
writer.Flush();
writer.Close();
}
_logFS.Flush();
The file opening code is now as follows:
_LogDS = new XmlLogFile();
using (FileStream logFS = new FileStream(_fileName, FileMode.Open, FileAccess.Read)
{
_LogDS.ReadXml(logFS);
}
You also need to close the FileStream. At a minimum, you need to close it when your service exits, or when the FileStream would go out of the application's scope.
You should be able to open it as ReadOnly from another application either way, but you have to specify that, it's not a default.
In your service you need to enable the file sharing:
FileStream fs = new FileStream("path", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
And in your reader application:
FileStream fs = new FileStream("path", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Without the FileShare.Read, all requests to open the file for reading fail. Any other application requesting to open the file for writing will still fail, for write-enabled sharing you'd use FileShare.ReadWrite. The default option for FileShare is None.