So let me give you an example of how my file could look:
Hello
my
name
is
Now, for example, I want to go through the different lines of this file with System.IO.File.ReadAllLines(); and then check with a loop whether the current line has the word "my" in it (so the second line in this case).
As my next step, I want to add a new line right after "my", so it looks like this:
Hello
my
name
is
I approached this with 2 methods now. I was hoping File.Append(); would offer a method where I could append anything after it has found the string I am looking for, but obviously it only offers methods to append strings to the end of files.
My second approach was to read in all the lines with string[] test=System.IO.File.ReadAllLines();
and then iterate through all the lines, checking each line with
for (int i = 0; i < (test.Length - 1); i++)
{
if(test[i].Contains("my"))
{
test[i] = test[i] + Environment.NewLine;
}
}
and then write all this back in the file with System.IO.File.WriteAllLines();
The problem I am facing here is the fact that this command does not really add a real new line to the file, as I've checked test.Length before and after, and both time I got 4 as a result.
Another option is to add the lines to a List which would give you the Insert() method:
*Only use this for relatively small files.
Something like:
string path = #"c:\some\path\file.txt";
List<String> lines = new List<string>(System.IO.File.ReadAllLines(path));
for (int i = 0; i < lines.Count; i++)
{
if (lines[i].Contains("my"))
{
if (i < lines.Count -1)
{
lines.Insert(i + 1, "");
}
else
{
lines.Add("");
}
}
}
System.IO.File.WriteAllLines(path, lines.ToArray());
First, I suggest you use StringBuilder. It's best to use it when you're adding many strings, since strings are immutable and thus each string is created again when you do +=, or simply assigning a new one to an array slot.
This code will do what you're looking for, and it treats the no new line edge case:
var filePath = //your file path
var test = File.ReadAllLines(filePath);
var sb = new StringBuilder();
for (int i = 0; i < (test.Length - 1); i++)
{
sb.Append(test[i]);
sb.Append(Environment.NewLine);
if (test[i].Contains("my"))
{
// This adds that extra new line
sb.Append(Environment.NewLine);
}
}
sb.Append(test[test.Length-1]);
File.WriteAllText(filePath, sb.ToString());
[TestMethod]
public void InsertLines()
{
var test = File.ReadAllLines(#"c:\SUService.log");
var list = new List<string>();
for (int i = 0; i < (test.Length - 1); i++)
{
list.Add(test[i]);
if (test[i].Contains("my"))
{
list.Add(Environment.NewLine);
}
}
File.WriteAllLines(#"c:\SUService.log", list);
}
Not for the above question: But in general if you want to add a new line after a line you just have to add a new line character -> so if you want to add an empty line after a line Just add 2 newline characters
File.WriteAllText(filePath,"\n\n");
Here the the writer will jump 2 times and add the upcoming contents in the send line
Related
I know how to read through all lines of a file and replace a selected line when a certain sequence of characters is found. The issue that I'm having at the moment is that I'm stuck with a structure that has no unique string to search for except for the main class name. So for example I'd know that the name of the class is "List_of_boats" and the structure tells me that 11 lines underneath that line is the value "items=2;" which I need to change to a certain value, depending on the amount of items I want to insert there.
Is there a way to use the foreach function or something to do this? I have provided some code that I've already got so far but I'm kind of stuck now.
var lines = File.ReadAllLines(fileToMerge);
var linID = 0;
foreach (var line in lines) {
if (line.Contains("ace_arsenal_saved_loadouts")) {
var newlinID = linID + 11; //go from ace_arsenal_saved_loadouts to "items=x;" to change number of items.
}
linID = linID + 1;
}
Convert the enumerable to an array, and loop through it by index:
var lines = File.ReadAllLines(fileToMerge).ToArray();
for (var linID = 0; linID < lines.Length; linID++) {
var line = lines[linID];
if (line.Contains("ace_arsenal_saved_loadouts")) {
var newlinID = linID + 11; //go from ace_arsenal_saved_loadouts to "items=x;" to change number of items.
}
}
my error is on the very last line, saying my index is out of range. Not sure what the problem is. I would like to continue using a list of lists or lists. I am trying to read a line of a csv file and separate that line into groups if one of the words in that line repeats; for example:
"hey how are you hey whats up"
hey how are you would be in one group and then hey whats up would be in the other group.
string[] ReadDirectory = Directory.GetFiles("C:\\Users\\-------", "*.csv");
List<List<List<string>>> myList = new List<List<List<string>>>();
List<string> CSVlist = new List<string>();
foreach (string file in ReadDirectory)
{
using (StreamReader readFile = new StreamReader(file))
{
int groupIndex = 0;
string line = readFile.ReadLine();
string[] headers = line.Split(',');
Array.Reverse(headers);
CSVlist.Add(headers[headers.Length - 1]);
myList.Add(new List<List<string>>());
for (int i = 0; i < headers.Length; i++)
{
if (headers[i].Contains("repeats") && headers[i + 1].Contains("repeats"))
{
myList.Add(new List<List<string>>());
groupIndex++;
}
myList[0][groupIndex].Add(headers[i]);
}
}
}
the problem resides when i =headers.Length-1, then headers[i + 1] is out of bounds. try:
for (int i = 0; i < headers.Length; i++)
{
if (i<headers.Length-1)
{
if (headers[i].Contains("repeats") && headers[i + 1].Contains("repeats"))
{
myList.Add(new List<List<string>>());
groupIndex++;
}
myList[0][groupIndex].Add(headers[i]);
}
}
Looking at the code, I'm not sure it'll do what you want it too (eg. if headers contains the exact word 'repeats', but this may just be example code so I'll ignore that) - but I'll focus on the error reported.
The exact error you reported is caused by this line:
myList[0][groupIndex].Add(headers[i]);
When you first add a nested list to myList, you don't add a nested list to that first nested list - so when the if statement is false, it tries to add the header into myList[0][0] where the second index is out of range because there is no inner list at myList[0].
Changing
myList.Add(new List<List<string>>());
to something like
var innerGroupList = new List<string>();
var groupList = new List<List<string>>();
groupList.Add(innerGroupList);
myList.Add(groupList);
will resolve the issue, but you won't get your expected outcome from the example data as the word 'repeats' is not there, you would need to do something like save each word in a Hashset, and check each word against that. If it already exists in the dictionary, split it into another group.
My testerfile contains:
processes
deleting
agreed
And this the code in C#
PorterStemmer testing = new PorterStemmer();
string temp,stemmed;
string[] lines = System.IO.File.ReadAllLines(#"C:\\Users\\PJM\\Documents\\project\\testerfile.txt");
System.Console.WriteLine("Contents of testerfile.txt = ");
for (int i = 0; i <2; i++)
{
temp = lines[i];
stemmed = testing.StemWord(temp);
System.IO.File.WriteAllText(#"C:\\Users\\PJM\\Documents\\project\\testerfile3.txt", stemmed);
Console.WriteLine("\t" + stemmed);
}
After running the code, the testerfile3 contains only "agre" .
So my problem here is that I want each word in the string array to be processed seperately i.e. I am having problem accessing string array. Is there any way to access every index in the string array?
From the documentation of WriteAllText:
If the target file already exists, it is overwritten.
so each iteration in your for loop overwrites the file, and you're only left with the text from the last iteration.
you can use System.IO.File.AppendAllText instead
also, you can use the array's Length property to loop through all words for (int i = 0; i < lines.Length; i++)
Alternatively, instead of the for-loop you can use LINQ's Select to project the non-stemmed line to the stemmed one and use AppendAllLines to write the results:
System.IO.File.AppendAllLines(#"C:\\Users\\PJM\\Documents\\project\\testerfile3.txt", lines.Select(l => testing.StemWord(l)));
I would like to consecutively read from a text file that is generated by my program. The problem is that after parsing the file for the first time, my program reads the last line of the file before it can begin re-parsing, which causes it to accumulates unwanted data.
3 photos: first is creating tournament and showing points, second is showing text file and the third is showing that TeamA got more 3 points
StreamReader = new StreamReader("Torneios.txt");
torneios = 0;
while (!rd.EndOfStream)
{
string line = rd.ReadLine();
if (line == "Tournament")
{
torneios++;
}
else
{
string[] arr = line.Split('-');
equipaAA = arr[0];
equipaBB = arr[1];
res = Convert.ToChar(arr[2]);
}
}
rd.Close();
That is what I'm using at the moment.
To avoid mistakes like these, I highly recommend using File.ReadAllText or File.ReadAllLines unless you are using large files (in which case they are not good choices), here is an example of an implementation of such:
string result = File.ReadAllText("textfilename.txt");
Regarding your particular code, an example using File.ReadAllLines which achieves this is:
string[] lines = File.ReadAllLines("textfilename.txt");
for(int i = 0; i < lines.Length; i++)
{
string line = lines[i];
//Do whatever you want here
}
Just to make it clear, this is not a good idea if the files you intend to read from are large (such as binary files).
I am trying to read a text file in C# and add line numbers to the lines.
This my input file:
This is line one
this is line two
this is line three
And this should be the output:
1 This is line one
2 this is line two
3 this is line three
This is my code so far:
class Program
{
public static void Main()
{
string path = Directory.GetCurrentDirectory() + #"\MyText.txt";
StreamReader sr1 = File.OpenText(path);
string s = "";
while ((s = sr1.ReadLine()) != null)
{
for (int i = 1; i < 4; i++)
Console.WriteLine(i + " " + s);
}
sr1.Close();
Console.WriteLine();
StreamWriter sw1 = File.AppendText(path);
for (int i = 1; i < 4; i++)
{
sw1.WriteLine(s);
}
sw1.Close();
}
}
I am 90% sure I need to use for cycle to get the line numbers there but so far with this code I get this output in the console:
1 This is line one
2 This is line one
3 This is line one
1 this is line two
2 this is line two
3 this is line two
1 this is line three
2 this is line three
3 this is line three
And this is in the output file:
This is line number one.
This is line number two.
This is line number three.1
2
3
I am not sure why the string variable s is not used when writing in the file even though it is defined earlier (another block, another rules maybe?).
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace AppendText
{
class Program
{
public static void Main()
{
string path = Directory.GetCurrentDirectory() + #"\MyText.txt";
StreamReader sr1 = File.OpenText(path);
string s = "";
int counter = 1;
StringBuilder sb = new StringBuilder();
while ((s = sr1.ReadLine()) != null)
{
var lineOutput = counter++ + " " + s;
Console.WriteLine(lineOutput);
sb.Append(lineOutput);
}
sr1.Close();
Console.WriteLine();
StreamWriter sw1 = File.AppendText(path);
sw1.Write(sb);
sw1.Close();
}
}
}
IEnumerable<string> lines = File.ReadLines(file)
.Select((line,i)=>i + " " + line)
.ToList();
File.WriteAllLines(file, lines);
OPEN STREAM
read the whole line and store it in a temp variable.
Use a counter to keep track which line you have read.
concatenate the counter with the temp variable.
save it to the file.
move your line pointer to next line and
repeat.
THEN CLOSE YOUR STREAM
I could provide you the right code, but because it is home work I will just ask you question that should lead you to the right answer:
why do you close the StreamReader the while inside your loop ? You will still access it after, that can cause an error.
why do you write in your StreamWriter without the prepended index ?
Why do you open the StreamWriter inside the loop ? Wouldn't it be better to open the StreamWriter and StreamReader outside the loop. Do you job in the loop and then close the Streams ?
You need to prepend the line number to each line string. Check out String.Format. Also, try a counter variable that sits outside the while loop to keep the line number count.
Hopefully that's enough to get you on the right path without handing you the exact answer.
Are you sure you want to close stream inside the loop while?
Watch out the FOR loops, you put them inside the While, so basically you are saying:
while ((s = sr1.ReadLine()) != null)
Every row read
for (int i = 1; i < 4; i++)
Repeat 3 times a write.
Also, you are closing the stream inside the while, so after the first row read.
Here is one major issue for you:
for (int i = 1; i < 4; i++)
Console.WriteLine(i + " " + s);
}
You are closing the for loop with a curly brace but not using a curly brace to open it. This means that the curly brace quoted above is actually closing the while loop so you loop through doing all the console.writeline and then when you come to writing to the file you are actually not reading from the file at all - s is "" due to scoping.
An alternative to #Hasan's answer for in-memory strings as a one-liner:
function AddLineNumbers(string input) =>
String.Join('\n', input.Split('\n').Select((text, i) => $"{i+1}: {text}"));