Reputation:
I am trying to append the text from a text box to a new line in a text file and have run into an issue. Lets say that there are already contents in the text file and looks something like this
something
Something
Something<---- Cursor ends here
And the cursor ends where the arrow is pointing (After the g on the last 'something'. If I try to use
File.AppendAllLines(@"Location", new[]{tb.Text});
Or
File.AppendAllText(@"Location", tb.Text + Environment.NewLine);
They will put the text where the cursor is at, not on a new line under the last item in the text file. It works if the cursor is on a new line to begin with but as soon as it ends at the end of the word everything goes on the same line.
Is there something I'm missing? Would using a streamwriter or some other method fix this issue?
Upvotes: 5
Views: 5246
Reputation: 4405
Actually, as pointed out in other answers. This is by design. File.AppendAllLines appends text at the end of the file. It does not add a line break before appending text. For this, you will have to read the file somehow and determine if the last character is a line break. There are multiple ways to do this.
The simplest way is to just read all lines and check if the last line is empty. If not, just prepend a line break to your string before passing it to File.AppendAllLines.
However, if dealing with large files, or if you do not want to open the file multiple times - something like the following method will do this whilst still only opening the file once.
public void AppendAllLinesAtNewLine(string path, IEnumerable<string> content)
{
// No file, just append as usual.
if (!File.Exists(path))
{
File.AppendAllLines(path, content);
return;
}
using (var stream = File.Open(path, FileMode.Open, FileAccess.ReadWrite))
using (var reader = new StreamReader(stream))
using (var writer = new StreamWriter(stream))
{
// Determines if there is a new line at the end of the file. If not, one is appended.
long readPosition = stream.Length == 0 ? 0 : -1;
stream.Seek(readPosition, SeekOrigin.End);
string end = reader.ReadToEnd();
if (end.Length != 0 && !end.Equals("\n", StringComparison.Ordinal))
{
writer.Write(Environment.NewLine);
}
// Simple write all lines.
foreach (var line in content)
{
writer.WriteLine(line);
}
}
}
Note: the long readPosition = s.Length == 0 ? 0 : -1; is for handling empty files.
Upvotes: 0
Reputation:
Thank you all for your suggestions, here is what I decided to do
FileStream stream = new FileStream("location", FileMode.Open, FileAccess.Read);
char actual = '\0';
if(stream.Length != 0)
{
stream.Seek(-1, SeekOrigin.End);
var lastChar = (byte)stream.ReadByte();
actual = (char)lastChar;
}
stream.Close();
try {
if(addCompT.Text != "")
{
if (actual == '\n' || actual == '\0')
File.AppendAllText("location", addCompT.Text + Environment.NewLine);
else
File.AppendAllText("location", Environment.NewLine + addCompT.Text + Environment.NewLine);
addCompT.Text = "";
}
}
catch(System.UnauthorizedAccessException)
{
MessageBox.Show("Please Run Program As Administrator!");
}
I appreciate everyone's help!
Upvotes: 0
Reputation: 216293
It does what you should expect. Your text doesn't init with a newline so it is appended just after the point where the previous text ends, To solve your problem you could open the file before writing in it and try to read the last byte.
bool addNewLine = true;
using (FileStream fs = new FileStream(@"location", FileMode.Open))
using (BinaryReader rd = new BinaryReader(fs))
{
fs.Position = fs.Length - 1;
int last = rd.Read();
// The last byte is 10 if there is a LineFeed
if (last == 10)
addNewLine = false;
}
string allLines = (addNewLine ? Environment.NewLine + tb.Text : tb.Text);
File.AppendAllLines(@"Location", new[]{allLines});
As you can see this a bit more complex but this avoid to read all the file in memory.
Upvotes: 2
Reputation: 45
If you put the Environment.NewLine
in front of the text, it should give you the results you're looking for:
File.AppendAllText(@"Location", Environment.NewLine + tb.Text);
Upvotes: 0
Reputation: 156948
This is exactly what you are asking to do. It appends the text you have to the existing file. If that file is 'wrong', the writer can't help it.
You could make sure the line end is always written to the file, if the file is entirely under your control. Else, you could read every line, append yours to it, and write the entire file back. This is bad for large files obviously:
File.WriteAllLines( @"Location"
, File.ReadAllLines(@"Location")
.Concat(new string[] { text })
);
Upvotes: 0