C# Text Writer writes at the start of the file - c#

My class which holds the constructor method of writing to a file
class Writer
{
public Writer(string filename, List<string> data)
{
FileStream ostrm;
StreamWriter writer;
TextWriter oldOut = Console.Out;
try
{
ostrm = new FileStream("C:/Users/kyle/Desktop/ConferenceSoftware/" + filename + ".txt", FileMode.OpenOrCreate, FileAccess.Write);
writer = new StreamWriter( ostrm );
}
catch (Exception e)
{
Console.WriteLine("Cannot open " + filename + ".txt for writing");
Console.WriteLine(e.Message);
return;
}
Console.SetOut(writer);
foreach (var _data in data)
{
Console.WriteLine( _data );
}
Console.SetOut(oldOut);
writer.Close();
ostrm.Close();
}
}
Inside my main method:
List<string> dataToAdd = new List<string>();
dataToAdd.Add("Example");
new Writer(Settings.ConferenceRoomName, dataToAdd);
However, if I already have text inside the file, instead appending to the file from the last line, it does it from the first line, ie:
Example // new added through method
Line that already exists // already in file
Line that already exists // already in file
// this is where I wanted it but it goes to the top
Any help would be appreciated, I don't see where I could target what line to start writing at.
Thanks in advance.

You need to use FileMode.Append instead of OpenOrCreate:
ostrm = new FileStream("C:/Users/kyle/Desktop/ConferenceSoftware/" +
filename + ".txt", FileMode.Append, FileAccess.Write);
See documentation (about FileMode.Append):
Opens the file if it exists and seeks to the end of the file, or creates a new file. This requires FileIOPermissionAccess.Append permission. FileMode.Append can be used only in conjunction with FileAccess.Write...
So it will also create the file if it does not exist.
If you don't want to create a non-existing file, you can check if it exists using File.Exists() before opening the stream.

When you create a new FileStream with FileMode.OpenOrCreate, it writes over the existing file. If you would like to append to the file, use FileMode.Append instead:
FileMode.Append: Opens the file if it exists and seeks to the end of the file, or creates a new file. This requires FileIOPermissionAccess.Append permission.
ostrm = new FileStream("C:/Users/kyle/Desktop/ConferenceSoftware/" + filename + ".txt", FileMode.Append, FileAccess.Write);

You want file mode Append instead of OpenOrCreate:
ostrm = new FileStream("C:/Users/kyle/Desktop/ConferenceSoftware/" + filename + ".txt", FileMode.Append, FileAccess.Write);
Both will create a new file if it doesn't exist, the difference is that OpenOrCreate starts writing at the beginning of the file and Append starts writing at the end of the file.
Reference: FileMode Enumeration

Related

Read and write to a file in the same stream

I'm trying to read and write to the same file in a way such that no other program can access the file in between:
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
StreamReader sr = new StreamReader(fs);
StreamWriter sw = new StreamWriter(fs);
newString = sr.ReadToEnd() + "somethingNew";
sw.Write(newString);
fs.Close();
The file is never written to. If I debug I can see that the reader manages to fetch the contents of the file, but the writer does not seem to be able to write to the file. Nothing happens.
I've been looking at this question which seems to be the same as mine. However I'm not able to get it to work.
Just Flush your changes to file, Have sw.Flush(); before closing the stream. like:
string filePath = "test.txt";
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
StreamReader sr = new StreamReader(fs);
StreamWriter sw = new StreamWriter(fs);
newString = sr.ReadToEnd() + "somethingNew";
sw.Write(newString);
sw.Flush(); //HERE
fs.Close();
You may see this post simultaneous read-write a file in C# (open multiple streams for reading and writing)
As mentioned above - just add the Flush() to force the data held in the stream to be written to the file. In a comment you mentioned that you had previously used a 'using' statement but this hadn't worked.
Briefly here's why:
A using statement automatically calls Flush() so you don't have
to.
When you dispose of a StreamReader (or StreamWriter) - like by using a 'using' statement - the inner stream object is also disposed and you lose the handle to the stream.
#EJS a simple static method that you can use to create a new file if it does not exist as well as write to the same file if it does exist
Simple usage
string path = #"C:\SomePath\Name.txt";
if (!System.IO.File.Exists(path))
{
WriteAndOrAppendText(path, "File Created");
}
else if (System.IO.File.Exists(path))
{
WriteAndOrAppendText(path, "New Boot.");
}
private static void WriteAndOrAppendText(string path, string strText)
{
if (!File.Exists(path))
{
using (StreamWriter fileStream = new StreamWriter(path, true))
{
fileStream.WriteLine(strText);
fileStream.Flush();
fileStream.Close();
}
}
else
{
using (StreamWriter fileStream2 = new StreamWriter(path, true))
{
fileStream2.WriteLine(strText);
fileStream2.Flush();
fileStream2.Close();
}
}
}
For being able to create a file, append to it, and read the data in it while still allowing an application to write to it, as I believe you are trying to do, here's a set up I created:
string path = #"C:\SomePath\MyLogFile.txt";
public static string Log(string Message)
{
try
{
if (File.Exists(path) == false)
File.Create(path).Close(); // need this .Close()!!!
logCounter++;
string logString = logCounter + " " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString() + ": " + Message + Environment.NewLine;
using (FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
{
using (StreamWriter sw = new StreamWriter(fs))
{
sw.Write(logString);
}
}
return logString; // only necessary so we can return an error in the Exception block
}
catch (Exception ex)
{
return "Logger: Cannot log data. " + ex.ToString();
}
}
It's actually required to use FileAccess.Write if you do FileMode.Append - instead of being able to use FileAccess.ReadWrite - but I found that didn't matter because whatever had been written would have been closed and flushed to the file, and I could still open the file and read it (it wouldn't be locked & blank) using these. I have sw.Write() because I have Environment.NewLine that I added into my logString, but I could've done sw.WriteLine() and removed that, if I had wanted to.
One caveat: File.Exists() has issues if the path is long - can't remember the limit, but just know that there is one, so don't put your file you're writing to several layers deep. Less is always better.

The process cannot access the file because it is being used by another process (File is created but contains nothing)

using System.IO;
class test
{
public static void Main()
{
string path=#"c:\mytext.txt";
if(File.Exists(path))
{
File.Delete(path);
}
FileStream fs=new FileStream(path,FileMode.OpenOrCreate);
StreamWriter str=new StreamWriter(fs);
str.BaseStream.Seek(0,SeekOrigin.End);
str.Write("mytext.txt.........................");
str.WriteLine(DateTime.Now.ToLongTimeString()+" "+DateTime.Now.ToLongDateString());
string addtext="this line is added"+Environment.NewLine;
File.AppendAllText(path,addtext); //Exception occurrs ??????????
string readtext=File.ReadAllText(path);
Console.WriteLine(readtext);
str.Flush();
str.Close();
Console.ReadKey();
//System.IO.IOException: The process cannot access the file 'c:\mytext.txt' because it is //being used by another process.
// at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
}
}
Try This
string path = #"c:\mytext.txt";
if (File.Exists(path))
{
File.Delete(path);
}
{ // Consider File Operation 1
FileStream fs = new FileStream(path, FileMode.OpenOrCreate);
StreamWriter str = new StreamWriter(fs);
str.BaseStream.Seek(0, SeekOrigin.End);
str.Write("mytext.txt.........................");
str.WriteLine(DateTime.Now.ToLongTimeString() + " " +
DateTime.Now.ToLongDateString());
string addtext = "this line is added" + Environment.NewLine;
str.Flush();
str.Close();
fs.Close();
// Close the Stream then Individually you can access the file.
}
File.AppendAllText(path, addtext); // File Operation 2
string readtext = File.ReadAllText(path); // File Operation 3
Console.WriteLine(readtext);
In every File Operation, The File will be Opened and must be Closed prior Opened. Like wise in the Operation 1 you must Close the File Stream for the Further Operations.
You are writing to the file prior to closing your filestream:
using(FileStream fs=new FileStream(path,FileMode.OpenOrCreate))
using (StreamWriter str=new StreamWriter(fs))
{
str.BaseStream.Seek(0,SeekOrigin.End);
str.Write("mytext.txt.........................");
str.WriteLine(DateTime.Now.ToLongTimeString()+" "+DateTime.Now.ToLongDateString());
string addtext="this line is added"+Environment.NewLine;
str.Flush();
}
File.AppendAllText(path,addtext); //Exception occurrs ??????????
string readtext=File.ReadAllText(path);
Console.WriteLine(readtext);
The above code should work, using the methods you are currently using. You should also look into the using statement and wrap your streams in a using block.
File.AppendAllText does not know about the stream you have opened, so will internally try to open the file again. Because your stream is blocking access to the file, File.AppendAllText will fail, throwing the exception you see.
I suggest you used str.Write or str.WriteLine instead, as you already do elsewhere in your code.
Your file is created but contains nothing because the exception is thrown before str.Flush() and str.Close() are called.
using (var fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
using (var sw = new StreamWriter(fs))
{
sw.WriteLine(message);
}

Streamwriter not throwing exception

In the following, streamwriter is not throwing an exception if the file does not exist.
I expected it to raise an exception, why doesn't it and how can I get it to do so?
var fileName = HttpContext.ApplicationInstance.Server.MapPath("~/App_Data/emails.txt");
FileStream fs = new FileStream(fileName, FileMode.Append);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(String.Format("{0}\t{1}", email, name));
sw.Flush();
sw.Close();
fs.Close();
Why?
FileStream fs = new FileStream(fileName, FileMode.Append);
This will create the file if it doesn't exist (and append to it if it does).
Assuming from your post (there is no question in it!) you don't want it to create a file first call File.Exists to ensure the file exists.
If you want to make sure you're appending to an existing file, use FileMode.Open and then Seek to the end before writing.
With File.Exists there is a (very slim) chance of an other process deleting the file after checking but before the construction of the FileStream.
Try this:
try
{
var fileName = HttpContext.ApplicationInstance.Server.MapPath("~/App_Data/emails.txt");
if (System.IO.File.Exists(fileName ))
{
FileStream fs = new FileStream(fileName, FileMode.Append);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(String.Format("{0}\t{1}", email, name));
sw.Flush();
sw.Close();
fs.Close();
}
else
{
//Throw error here
}
}
catch()
{
}

c# Replace openfileDialog to a none gui stream

I am trying to separate the MIME gui from the code i need. I am almost there just one more gui element i dont know how to replace. This element is the openfiledialog. Here a code snippet.
Program.cs
var sfd = new OpenFileDialog();
sfd.FileName = "C:\\eml\\" + validOutputFilename;
try
{
var writer = new MimeMessageWriter();
using (var fs = sfd.OpenFile()) writer.Write(message, fs);
}
catch (Exception ex)
{
//ignore
// need to log
}
message is an IMessage. A class created to store the information about an eml file. The open file dialog is allowing you to put in the file name with an eml extension and that is all. write.Write expects an IMessage and a stream. Inside writer.Write the file is being written The only part of the file that uses this code is when the file itself is writen at the end and write out any attachments. Here are those code snippets.
*MimeMessageWriter
-the attachment uses it here
var embeddedMessage = attachment.OpenAsMessage();
var messageWriter = new MimeMessageWriter();
var msgStream = new MemoryStream();
messageWriter.Write(embeddedMessage, msgStream);
var messageAttachment = ew DotNetOpenMail.FileAttachment(msgStream.ToArray());
messageAttachment.ContentType = "message/rfc822";
messageAttachment.FileName = filename + ".eml";
outMessage.AddMixedAttachment(messageAttachment);
-write out the file part of the file
using (var sw = new StreamWriter(stream))
sw.Write(outMessage.ToDataString());
I want to replace openFileDialog with something that will allow me to pass the filename to write out file in the MimeMessageWriter
Replace
using (var fs = sfd.OpenFile()) writer.Write(message, fs);
with
string fileName = #"c:\eml\myAttachment.eml";
using ( FileStream fs = new FileStream( fileName, FileMode.CreateNew ) )
{
writer.Write( message, fs )
}
See also: http://msdn.microsoft.com/de-de/library/47ek66wy.aspx

streamWriter rewrite the file or append to the file

I am using this
for($number=0; $number < 5; $number++){
StreamWriter x = new StreamWriter("C:\\test.txt");
x.WriteLine(number);
x.Close();
}
if something is in test.text, this code will not overwrite it. I have 2 questions
1: how can I make it overwrite the file
2: how can I append to the same file
using C#
Try the FileMode enumerator:
FileStream fappend = File.Open("C:\\test.txt", FileMode.Append); // will append to end of file
FileStream fcreate = File.Open("C:\\test.txt", FileMode.Create); // will create the file or overwrite it if it already exists
StreamWriters default behavior is to create a new file, or overwrite it if it exists. To append to the file you'll need to use the overload that accepts a boolean and set that to true. In your example code, you will rewrite test.txt 5 times.
using(var sw = new StreamWriter(#"c:\test.txt", true))
{
for(int x = 0; x < 5; x++)
{
sw.WriteLine(x);
}
}
You can pass a second parameter to StreamWriter to enable or disable appending to file:
in C#.Net:
using System.IO;
// This will enable appending to file.
StreamWriter stream = new StreamWriter("YourFilePath", true);
// This is default mode, not append to file and create a new file.
StreamWriter stream = new StreamWriter("YourFilePath", false);
// or
StreamWriter stream = new StreamWriter("YourFilePath");
in C++.Net(C++/CLI):
using namespace System::IO;
// This will enable appending to file.
StreamWriter^ stream = gcnew StreamWriter("YourFilePath", true);
// This is default mode, not append to file and create a new file.
StreamWriter^ stream = gcnew StreamWriter("YourFilePath", false);
// or
StreamWriter^ stream = gcnew StreamWriter("YourFilePath");
You can start by using the FileStream and then passing that to your StreamWriter.
FileStream fsOverwrite = new FileStream("C:\\test.txt", FileMode.Create);
StreamWriter swOverwrite = new StreamWriter(fsOverwrite);
or
FileStream fsAppend = new FileStream("C:\\test.txt", FileMode.Append);
StreamWriter swAppend = new StreamWriter(fsAppend);
So what is the result of your code?
I would expect the file to contain nothing but the number 4, since the default behavior is to create/overwrite, but you are saying that it is not overwriting?
You should be able to make it overwrite the file by doing what you are doing, and you can append by making a FileStream with FileMode.Append.

Categories

Resources