Hi I am trying to make a program which ; takes an input txt file then shows its lines in reverse order
I was using File.ReadAllLines so I get a array of strings then I used indexes of the strings and used for loop to reverse the order.
But I did some research and found the File.ReadAllLines is not good for very long txt files so they say I should use File.ReadLines.
But I couldn't understand how to access the lines indexes as I did in string array
My working code is below ( which is written by using File.ReadAllLines) I want to do this with File.ReadLines How can I do this how can I access indexes if I use ReadlLines
private void button1_Click(object sender, EventArgs e)
{
openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "Txt Files Only |*.txt";
openFileDialog1.InitialDirectory = @"C:\";
openFileDialog1.Title = "Load Log File";
openFileDialog1.ShowDialog();
textBox1.Text = openFileDialog1.FileName;
checkBox1.Checked = true;
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
textBox1.Clear();
checkBox1.Visible = false;
button1.Visible = false;
textBox1.Multiline = true;
textBox1.Height = 200;
textBox1.Width = 600;
button2.Visible = false;
textBox1.ScrollBars = ScrollBars.Vertical;
string[] lines = File.ReadAllLines(openFileDialog1.FileName);
int n = lines.Length;
for (int i = 0; n > i; n--)
{
textBox1.Text = lines[n - 1] Environment.NewLine;
}
}
CodePudding user response:
To reverse the lines, you need to load all of them into memory anyway (unless you read from the bottom), so File.ReadAllLines
is the correct choice.
But I couldn't understand how to access the lines indexes as I did in string array
You can't. File.ReadLines
returns an IEnumerable<String>
. IEnumerables can't be indexed. You could call ToArray
or ToList
to transform it to an array or list. In alternative, you can use ElementAt
on the IEnumberable to get the value at the specified index. This is very inefficient, tho.
Summary: Stick to File.ReadAllLines
CodePudding user response:
You could use
IEnumerable<string> lines = File.ReadLines(openFileDialog1.FileName);
foreach (string line in lines.Reverse()) {
...
}
However, you won't get any performance benefit in this case, as the Reverse()
operation will have to buffer all the lines. And this is precisely what ReadLines
avoids doing by reading the lines lazily as you are looping through them.
Using ReadAllLines
and a reverse for-loop is better in this case. But you can get a performance benefit by using a StringBuilder:
var sb = new StringBuilder();
string[] lines = File.ReadAllLines(openFileDialog1.FileName);
for (int i = lines.Length - 1; i >= 0; i--)
{
sb.AppendLine(lines[i]);
}
textBox1.Text = sb.ToString();
The reason for this is that creating a string with repeated =
operations will create a new, lager string each time and copy the old value into the new one.
See also: Use Visual C# to improve string concatenation performance.
To increase the speed further, you could calculate the size of the resulting text in advance and use it to initialize the StringBuilder
with an optimal buffer size.
string[] lines = File.ReadAllLines(openFileDialog1.FileName);
var sb = new StringBuilder(lines.Sum(s => s.Length 2));
Note: You can expand the forr
code snippet in Visual Studio to get a reverse for loop.
CodePudding user response:
I don't think what you are trying to do is possible with File.ReadLines, since it returns an IEnumerable which is in this case implemented as a ReadLinesIterator. The iterator is only able to read one line at a time going forward. Anything that requires knowledge about all the lines (reversing them, counting them...) cannot be done without iterating through all lines first.
You could find lower-level approaches to do that, but it might be tricky. Anyway, since you are displaying all the lines inside a textbox, you are keeping all the file's content in memory anyway. Looking for a more efficient way to read the file doesn't seem really useful in this case.