c# File.ReadAllLines doesn't read blank lines - c#

I am using c# for reading some txt documents and writing/deleting some lines in them
I have to read a text document, delete some of it's lines and then save it again in the same path.
It worked all good until I realized that it doesn't read empty lines or when there is just a space in a new line :(.
Here's my text file structure:
-Name
-LastName
-Age
-Phone
-Address
-Address2(optional) -// this line will be deleted
-Address3(optional) -// this line will be deleted
****here comes the empty line****
Here's my code:
List<string> myLines = File.ReadAllLines(path).ToList();
if (myLines.Count > 5)
{
for(int i = 7; i >= 5; i--)
{
myLines.RemoveAt(i);
}
File.WriteAllLines(path, myLines.ToArray());
}
So I don't know why when I run File.ReadAllLines will give me 7 lines (ignoring the blank one) and of course after I delete something in the file, the blank line is still there.
Note: I am working with more than 100k files, either way I would just delete that specific line by hand.
Can you help me sort this out and delete that blank line? Thank you.

Here's some code:
var f = #"-Name
-LastName
-Age
-Phone
-Address
-Address2(optional) -// this line will be deleted
-Address3(optional) -// this line will be deleted
-Name2";
File.WriteAllText(#"C:\temp\a.txt", f);
var f2 = File.ReadAllLines(#"C:\temp\a.txt").ToList();
f2.RemoveAt(7);
f2.RemoveAt(6);
f2.RemoveAt(5);
File.WriteAllLines(#"C:\temp\b.txt", f2);
Open the two resulting files a.txt and b.txt in c:\temp (make sure you have a c:\temp) - the a has blank lines, the b has no interim blank lines or address2/3
..but do note that b has a blank line at the end, because File.WriteAllLines will end the final line (Name2 in my example) with a CRLF.
If this is what you're talking about/you don't want, consider something else instead, perhaps:
File.WriteAllText(#"C:\temp\b.txt", string.Join(Environment.NewLine, f2));

Related

C# How to duplicate line in text file (.txt) when button is clicked?

I've a winform application and I want to ducplicate a line in a text file (.txt) when I click a button.
eg :
Hello world
and I want to have something like:
Hello world
Hello world
when I click a button.
void duplicateLine(string text, int line){
//Read text file
//duplicate the line
//insert (Write) the duplicate line in text file(.txt)
}
One way to duplicate a line in a text file in C# is to use the File.ReadAllLines method to read the file into a string array, then use a loop to insert the duplicate line at the desired index, and then use the File.WriteAllLines method to write the modified array back to the file. For example, the following code snippet duplicates the first line of a text file:
void duplicateLine(string text, int line)
{
//Read the file into a string array
string[] lines = File.ReadAllLines("textfile.txt");
//Create a list to store the modified lines
List<string> newLines = new List<string>();
//Loop through the array and insert the duplicate line
for (int i = 0; i < lines.Length; i++)
{
//Add the original line to the list
newLines.Add(lines[i]);
//If the line is the one to be duplicated, add it again
if (i == line)
{
newLines.Add(lines[i]);
}
}
//Write the modified list back to the file
File.WriteAllLines("textfile.txt", newLines);
}
This code will result in a text file like this:
Hello world
Hello world
Some other line
Another line
It is better to write the code yourself and ask questions about the code problems. Try the following method:
1-Read all line of file to list using File.ReadAllLines
2- check line if not exist in the file
3-Add a new line at a specific position of list( duplicate one line)
4-Write list to file
void duplicateLine(string text, int line){
string _path = "data.txt"; //path of your file
var txtLines = File.ReadAllLines(_path).ToList(); //1
if(line>=txtLines.Count) //2
{
MessageBox.Show("this line not exist in file..");
return;
}
txtLines.Insert(line, Text); //3
File.WriteAllLines(_path, txtLines); //4
}

How to add text to the line that starts with "hello" in a file

I have a file that contains many lines. There is a line here looking like below:
hello jim jack nina richi sam
I need to add a specific text salmon in this line and change it to below (it could be added anywhere in this line -end -begining - in the middle -doesnt matter ):
hello jim jack nina richi sam salmon
I tried:
string path = #"C:\testFolder\newTestLog.txt";
StreamReader myReader = new StreamReader(path);
string[] allLines = File.ReadAllLines(path);
foreach (string element in allLines) {
if (element.StartsWith("hello"))
{
Console.WriteLine(element);
}
}
myReader.Close();
}
Using this I'm able to read the file line by line and add each line to an array and print that line if that starts with "hello", but I'm not sure how to add text to this line
You should use what Joel answered it's nicer but if you're having trouble implementing it try this. After adding the salmon to the lines that start with hello you can overwrite the txt file by using File.WriteAllLines
string filePath = #"C:\testFolder\newTestLog.txt";
string[] allLines = File.ReadAllLines(filePath);
for(int i = 0; i < allLines.Length; i++)
{
if (allLines[i].StartsWith("hello"))
{
allLines[i] += " salmon";
}
}
File.WriteAllLines(filePath, allLines);
Try this:
string path = #"C:\testFolder\newTestLog.txt";
var lines = File.ReadLines(path).Select(l => l + l.StartsWith("hello")?" salmon":"");
foreach (string line in lines)
Console.WriteLine(line);
Note that this still only writes the results to the Console, as your sample does. It's not clear what you really want to happen with the output.
If you want this saved to the original file, you've opened up a small can of worms. Think of all of the data in your file as if it's stored in one contiguous block1. If you append text to any line in the file, that text has nowhere to go but to overwrite the beginning of the next. As a practical matter, if you need to modify file, this often means either writing out a whole new file, and then deleting/renaming when done, or alternatively keeping the whole file in memory and writing it all from start to finish.
Using the 2nd approach, where we keep everything in memory, you can do this:
string path = #"C:\testFolder\newTestLog.txt";
var lines = File.ReadAllLines(path).Select(l => l + l.StartsWith("hello")?" salmon":"");
File.WriteAllLines(path, lines);
1 In fact, a file may be split into several fragments on the disk, but even so, each fragment is presented to your program as part of a single whole.

C# how to append text in end of row text file?

i have text file like this
IPen ID,Datetime,Status,Data Received
is it possible to add some word in end of row. I want append some word so the final result is :
IPen ID,Datetime,Status,Data Received,Data Reply
i already browsing and searching, the result only show append text in new line, but thats not what i want, i want append text in end of row. any suggestion for me?
It's not overly clear what you're asking, but it sounds like you're saying that any line in a file that has the text "IPen ID,Datetime,Status,Data Received" should be replaced with the text "IPen ID,Datetime,Status,Data Received,Data Reply".
If that's the case then this code works:
File
.WriteAllLines(#"path",
File
.ReadAllLines(#"path")
.Select(x =>
x + (x == "IPen ID,Datetime,Status,Data Received" ? ",Data Reply" : "")));
You can add text at the end of an existing file like this:
using (var stream = new StreamWriter("Your file path here"))
{
stream.Write("Your text here");
}
This method will add the text in a new line only if there is already a end of line character on the end of file. Otherwise, it will add on the same line.
This also adds the text only on the end of the file, if you need to select the line or insert into all lines that match a specific condition it will be a little more complicated, but I can show you if you tell me exactly what you need.
EDIT: Since you need to add the text in the middle of a line, we should read all the lines, change then and save them back on the file:
// Define your file path.
var filePath = "Your file path here";
// Fill an array with the lines from the txt file.
var txtLines = File.ReadAllLines(filePath);
// Change all lines into what you want.
var changedLines = ChangeLines(txtLines);
// Write the file with all the changed lines.
File.WriteAllLines(filePath, changedLines);
And this is how to change the lines:
public static IEnumerable<string> ChangeLines(IEnumerable<string> lines)
{
foreach (var line in lines)
{
yield return line.Replace("A C", "A B C");
}
}
This will replace all the occurrences of "A C" with "A B C". If you want to add something after some text, before, split a line in two or whatever you want, you can change this method to do what you want and all the changes will be saved back into the file. I hope that helps.

Alternative to File.AppendAllText for newline

I am trying to read characters from a file and then append them in another file after removing the comments (which are followed by semicolon).
sample data from parent file:
Name- Harly Brown ;Name is Harley Brown
Age- 20 ;Age is 20 years
Desired result:
Name- Harley Brown
Age- 20
I am trying the following code-
StreamReader infile = new StreamReader(floc + "G" + line + ".NC0");
while (infile.Peek() != -1)
{
letter = Convert.ToChar(infile.Read());
if (letter == ';')
{
infile.ReadLine();
}
else
{
System.IO.File.AppendAllText(path, Convert.ToString(letter));
}
}
But the output i am getting is-
Name- Harley Brown Age-20
Its because AppendAllText is not working for the newline. Is there any alternative?
Sure, why not use File.AppendAllLines. See documentation here.
Appends lines to a file, and then closes the file. If the specified file does not exist, this method creates a file, writes the specified lines to the file, and then closes the file.
It takes in any IEnumerable<string> and adds every line to the specified file. So it always adds the line on a new line.
Small example:
const string originalFile = #"D:\Temp\file.txt";
const string newFile = #"D:\Temp\newFile.txt";
// Retrieve all lines from the file.
string[] linesFromFile = File.ReadAllLines(originalFile);
List<string> linesToAppend = new List<string>();
foreach (string line in linesFromFile)
{
// 1. Split the line at the semicolon.
// 2. Take the first index, because the first part is your required result.
// 3. Trim the trailing and leading spaces.
string appendAbleLine = line.Split(';').FirstOrDefault().Trim();
// Add the line to the list of lines to append.
linesToAppend.Add(appendAbleLine);
}
// Append all lines to the file.
File.AppendAllLines(newFile, linesToAppend);
Output:
Name- Harley Brown
Age- 20
You could even change the foreach-loop into a LINQ-expression, if you prefer LINQ:
List<string> linesToAppend = linesFromFile.Select(line => line.Split(';').FirstOrDefault().Trim()).ToList();
Why use char by char comparison when .NET Framework is full of useful string manipulation functions?
Also, don't use a file write function multiple times when you can use it only one time, it's time and resources consuming!
StreamReader stream = new StreamReader("file1.txt");
string str = "";
while ((string line = infile.ReadLine()) != null) { // Get every line of the file.
line = line.Split(';')[0].Trim(); // Remove comment (right part of ;) and useless white characters.
str += line + "\n"; // Add it to our final file contents.
}
File.WriteAllText("file2.txt", str); // Write it to the new file.
You could do this with LINQ, System.File.ReadLines(string), and System.File.WriteAllLines(string, IEnumerable<string>). You could also use System.File.AppendAllLines(string, IEnumerable<string>) in a find-and-replace fashion if that was, in fact, the functionality you were going for. The difference, as the names suggest, is whether it writes everything out as a new file or if it just appends to an existing one.
System.IO.File.WriteAllLines(newPath, System.IO.File.ReadLines(oldPath).Select(c =>
{
int semicolon = c.IndexOf(';');
if (semicolon > -1)
return c.Remove(semicolon);
else
return c;
}));
In case you aren't super familiar with LINQ syntax, the idea here is to loop through each line in the file, and if it contains a semicolon (that is, IndexOf returns something that is over -1) we cut that off, and otherwise, we just return the string. Then we write all of those to the file. The StreamReader equivalent to this would be:
using (StreamReader reader = new StreamReader(oldPath))
using (StreamWriter writer = new StreamWriter(newPath))
{
string line;
while ((line = reader.ReadLine()) != null)
{
int semicolon = line.IndexOf(';');
if (semicolon > -1)
line = c.Remove(semicolon);
writer.WriteLine(line);
}
}
Although, of course, this would feed an extra empty line at the end and the LINQ version wouldn't (as far as I know, it occurs to me that I'm not one hundred percent sure on that, but if someone reading this does know I would appreciate a comment).
Another important thing to note, just looking at your original file, you might want to add in some Trim calls, since it looks like you can have spaces before your semicolons, and I don't imagine you want those copied through.

How to traverse back and forth of text file line

I have a text file which contains lines that i need to process.Here is the format of the lines present into my text file..
07 IVIN 15:37 06/03 022 00:00:14 600 2265507967 0:03
08 ITRS 15:37 06/03 022 00:00:09 603 7878787887 0:03
08 ITRS 15:37 06/03 022 00:00:09 603 2265507967 0:03
Now as per my requirement i have to read this text file line by line.Now as soon as i get ITRS into any line i have to search for the number 2265507967 into the immediate upside of the text file lines.As soon as it gets 2265507967 in the upside lines ,it should read that line.
Now i am reading the lines into strings and breaking into characters based on spaces.Here is my code..
var strings = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
My problem is that i am not getting way to traverse upside of the text file and search for the substring .i.e. 2265507967.Please help .
I am not aware of being able to go backwards when reading a file (other than using the seek() method) but I might be wrong...
A simpler approach would be to:
Create a dictionary, key value being the long numeric values while the value being the line to which it belongs: <2265507967,07 IVIN 15:37 06/03 022 00:00:14 600 2265507967 0:03>
Go through the file one line at a time and:
a. If the line contains ITRS, get the value from the line and check your dictionary. Once you will have found it, clear the dictionary and go back to step 1.
b. If it does not contain ITRS, simply add the number and the line as key-value pairs.
This should be quicker than going through one line at a time and also simpler. The drawback would be that it could be quite memory intensive.
EDIT: I do not have a .NET compiler handy, so I will provide some pseudo code to better explain my answer:
//Initialization
Dictionary<string, string> previousLines = new Dictionary<string, string>();
TextReader tw = new TextReader(filePath);
string line = String.Empty;
//Read the file one line at a time
while((line = tw.ReadLine()) != null)
{
if(line.contains("ITRS")
{
//Get the number you will use for searching
string number = line.split(new char[]{' '})[4];
//Use the dictionary to read a line you have previously read.
string line = previousLines[number];
previousLines.Clear(); //Remove the elements so that they do not interrupt the next searches. I am assuming that you want to search between lines which are found between ITRS tags. If you do not want this, simply omit this line.
... //Do your logic here.
}
else
{
string number = line.split(new char[]{' '})[4];
previousLines.Add(number, line);
}
}

Categories

Resources