Shift text file rows by one deleting the first line - c#

how to Shift text file rows by one after deleting a particular line based on condition xyz=true for that particular line. I want to use C#.
using (StreamWriter writer = new StreamWriter(file))
{
while ((line = rows[rowIndex++]) != null)
{
if( line contains xyz )// i know the logic to find this;
{
delete this line and shift all below lines one up;
}
}
}

A simple way to do this for small files (files which can be completely loaded into memory) is to use File.ReadAllLines() to get a string[] of the lines. With this, you can loop through the array of strings and test each one to determine if it should be written to the new file or not.
A similar question came up recently here C# Delete line i text file if it is different than specific term
If you're writing the output to a new file, you don't need to worry about moving all the later lines up, removing the entire line will also remove the line ending characters.
Hope this helps

Related

Delete specific row from File

I have this little project in C# where I am manipulating with files. Now my task is that I have to delete specific rows from files.
For example my file looks like this:
1-this is the first line
2-this is the second line
3-this is the third line
4-this is the fourth line
Now how can I keep only the first two rows and delete only the last two rows?
Note- this is how I read the file from my local machine:
string[] lines = File.ReadAllLines(#"C:\Users\admin\Desktop\COMMANDS.dat");
I have tried something like this but I think it's not so "efficient"
string text = File.ReadAllText(#"C:\Users\admin\Desktop\COMMANDS.dat");
text = text.Replace(lines[2], "");
text = text.Replace(lines[3], "");
File.WriteAllText(#"C:\Users\admin\Desktop\COMMANDS.dat", text);
So this actually does the job, it replaces the lines by string with an empty character but when I take a look at the file, I don't want to have 4 lines there, even though 2 of them are real strings and the other two are just empty lines... Can I manage to do this in another way?
Try replacing the newline character with an empty string:
string text = File.ReadAllText(#"C:\Users\admin\Desktop\COMMANDS.dat");
text = text.Replace(lines[2], "").Remove(Environment.NewLine, "");
text = text.Replace(lines[3], "").Remove(Environment.NewLine , "");
File.WriteAllText(#"C:\Users\admin\Desktop\COMMANDS.dat", text);
If my answer is useful, please mark it as accepted, and upvote it.
async Task Example()
{
var inputLines = await File.ReadAllLinesAsync("path/to/file.txt");
var outputLines = inputLines.Where((l, i) => i < 2);
await File.WriteAllLinesAsync("target/file.txt", outputLines);
}
What it does
Read data but not as one string but as a collection of lines
Create a new collection containing only the lines you want in your output
Write the filtered lines
Notes:
This example is not optimized for memory usage (because we read all lines and for larger files, e.g. multiple GB, this will fail). See existing answers for memory optimized version) - but: It's totally fine to do it this way if you know you have just a few k lines. (and it's faster)
Try not to "modify" strings. This will always create a copy and needs a lot of memory.
In this "Linq style" (functional) approach, we should treat data as immutable. That means: we have one variable that represents the input file and one variable that represents the result. We use declarative Linq to describe how the output should look like. "output is input where the filter index < 2 matches" instead of "if xy remove line" in an imperative style.

Removing text above real content of CSV file

I have a CSV whose author, annoyingly enough, has decided to 'introduce' the file before the contents themselves. So in all, I have a CSV that looks like:
This file was created by XXXXYY and represents the crossover between YY and QQQ.
Additional information can be found through the website GG, blah blah blah...
Jacob, Hybrid
Dan, Pure
Lianne, Hybrid
Jack, Hatchback
So the problem here is that I want to get rid of the first few lines before the 'real content' of the CSV file begins. I'm looking for robustness here, so using Streamreader and removing all content before the 4th line for example, is not ideal (plus the length of the text can vary).
Is there a way in which one can read only what matters and write a new CSV into a directory path?
Regards,
genesis
(edit - I'm looking for C sharp code)
The solution depends on the files you have to parse. You need to look for a reliable pattern that distinguishes data from comment.
In your example, there are some possibilities that might be the same in other files:
there are 4 lines of text. But you say this isn't consistent across files
The text lives may not contain the same number of commas as the data table. But that is unlikely to be reliable for all files.
there is a blank/whitespace only line between the text and the data.
the data appears to be in the form word-comma-word. If this is true it should be easy to identify non data lines (any line which doesn't contain exactly one comma, or has multiple words etc)
You may be able to use a combination of these heuristics to more reliably detect the data.
You could scan by line (looking for the \r\n) and ignore lines that don't have a comma count that matches you csv.
You should be able to read the file into a string pretty easily unless it is really massive.
e.g.
var csv = "some test\r\nsome more text\r\na,b,c\r\nd,e,f\r\n";
var lines = csv.Split('\r\n');
var csvLines = line.Where(l => l.Count(',') == 2);
// now csvLines contains only the lines you are after
List<string> info = new List<string>();
int counter = 0;
// Open the file to read from.
info = System.IO.File.ReadAllLines(path).ToList();
// Find the lines up until (& including) the empty one
foreach (string s in info)
{
counter++;
if(string.IsNullOrEmpty(s))
break; //exit from the loop
}
// Remove the lines including the blank one.
info.RemoveRange(0,counter);
Something like this should work, you should probably put some tests in to make sure counter is not > length and other tests to handle errors.
You could adapt this code so that it just finds the empty line number using linq or something, but I don't like the overhead of linq (Yeah ironic considering I'm using c#).
Regards,
Slipoch

C# overwrite first few lines of a text file with constant time [duplicate]

This question already has an answer here:
StreamWriter replace line with a new text
(1 answer)
Closed 7 years ago.
I have a text file:
FIRST LINE
SECOND LINE
THIRD LINE
...
I want to overwrite the first line of the file, eg. with "2345"
with the StreamWriter, I can only overwrite the file into:
2345
with
using (StreamWriter newWriter = new StreamWriter(playingFileDirectory, false)){
newWriter.WriteLine("2345");
}
or
FIRST LINE
SECOND LINE
THIRD LINE
...
2345
with
using (StreamWriter newWriter = new StreamWriter(playingFileDirectory, true)){
newWriter.WriteLine("2345");
}
However My desired result is:
2345
SECOND LINE
THIRD LINE
...
Is there any quick way (linear time) of doing that? I have some text that need to be updated whenever the user presses a button. The database records contains 100,000 lines. I just want to change the first line like in a text editor, but not changing 1 line and rewriting the whole file.
I don't think that is possible out-of-the-box. I would suggest to do the following:
Open the output file for writing;
Write your first few lines;
Open the input file for reading;
Read up to the line you need;
Read the line from input and write it to the output;
Close both.
If you need to, you can first move the input file and write the output file to the original location.
I would advise against the use of File.ReadAllLines if the file is large. It will have an enormous impact on your memory.
Read and write the file in terms of lines:
var allLines = File.ReadAllLines("MyFile");
allLines[0] = "2345";
File.WriteAllLines("MyFile", allLines);
I think this should do it:
var lines = System.IO.File.ReadAllLines("YOUR_PATH");
lines[0] = "2345";
System.IO.File.WriteAllLines("YOUR_PATH", lines);
Read all lines method
Write all lines method

Read specified line from external text file

I'm using C# and writing a Windows Form application for Windows 7 or Windows 8.
I need to know how to get my app to read a specific line which should be assigned to a specific text box or combo box.
This is the code I have so far.
using (StreamReader QNARead = new StreamReader(TestPath))
if (QNARead.Peek() >= 0)
{
string Line1 = QNARead.ReadLine();
QuestionText1.Text = Line1;
string Line2 = QNARead.ReadLine();
QuestionText2.Text = Line2;
string Line3 = QNARead.ReadLine();
AlternativesList1.Items.Add(Line3);
}
But with this method I'll have to read a lot of lines, because the line could be the 500th in the text file. (I do know the exact line number, eg. 54).
I used once this to read a specific line in a text file:
string filename = "test.txt";
if (File.Exists(filename))
{
string[] lines = File.ReadAllLines(filename);
Console.WriteLine(lines[5]);
}
where 5 can be replaced with any line number (zero based).
Since a file is just a list of bytes, you need to know how far into it to read, to get the line you want.
Unless the lines are fixed (or predictable) lengths, or you have some kind of separate index, you need to read every line up to the one you want. From a code point of view you can make this fairly tidy, for example in Framework 4.0:
string line54 = File.ReadLines(FileName).Skip(53).Take(1).First();
Note that at this point, you're not taking advantage of reading the earlier lines being skipped over, so a more efficient way would be to keep reading in a loop until you reach the last line needed.

.CSV file write by line, checking for errors

first question so hopefully it'll be relevant. While not terribly new to coding... I'm pretty new to 'Good' coding so apologies if I'm completely unaware of obvious best practice.
I'm currently writing to a CSV file by row (using c#).
Which was all well and good till i got told this morning, that the department i'm writing the code for actually want all the lines in one file (i was doing a file per batch, and error checking on a batch lvl, so if anything was wrong with the batch none of the batch was exported)
They still need it to be all or nothing on a batch lvl (and i'm checking the 'cell' values before trying to write them to file, so that stage should work) but I'm acutely aware that the one part of my code which i currently can't check works before beginning the file write is the line writes themselves. And I was wondering how likely it is for individual lines to fail to write?, assuming the file is created properly/ accessed properly for the first line?
and i guess secondly if this is likely to be a problem, is there any 'best practice' I should be aware of to easy(or eliminate) the problem.
code below which i call for each row in the batch that needs writing.
public void WriteRow(CsvRow row)
{
StringBuilder builder = new StringBuilder();
bool firstColumn = true;
foreach (string value in row)
{
// Add separator if this isn't the first value
if (!firstColumn)
builder.Append(',');
// Implement special handling for values that contain comma or quote
// Enclose in quotes and double up any double quotes
if (value.IndexOfAny(new char[] { '"', ',' }) != -1)
builder.AppendFormat("\"{0}\"", value.Replace("\"", "\"\""));
else
builder.Append(value);
firstColumn = false;
}
row.LineText = builder.ToString();
WriteLine(row.LineText);
}

Categories

Resources