I'd appreciate if someone could advise on the following.
I read the file containing the below text and writing each line into the List<string>:
CODE/1
NAME/some_name1
SHORT_NAME/short_name1
CODE/2
NAME/document is a piece of paper
containing information often
used as proof of something
SHORT_NAME/document is a piece
Now I'm parsing the list to get CODE, NAME and SHORT_NAME separately.
The problem is that some lines containing NAME have one sencence which is broken into several lines due to its long length. I want to append these lines into one sentence, the output should be:
...
NAME/document is a piece of paper containing information often used as proof of something
...
My code appends only one next line:
List<string> lines = File.ReadLines(path).ToList();
List<string> full_lines = new List<string>();
foreach (string line in lines)
{
if (line.StartsWith("NAME"))
{
name_index = lines.IndexOf(line);
string new_line = "";
if (!lines.ElementAt(name_index + 1).StartsWith("SHORT_NAME")) //checking if
//the next line does not start with SHORT_NAME (then it is continuation of NAME)
{
new_line = line + " " + lines.ElementAt(name_index + 1);//appending the next
//line
full_lines.Add(new_line); //adding into new list
}
else
{
full_lines.Add(line);
}
}
}
So the output is:
...
NAME/document is a piece of paper
...
So, how can I append all lines?
Thank you
When you're reading the file, read each line separately, instead of all them together. Then don't create a new line unless it starts with a key word or if the '/' is unique unless the line contains a '/'. Something like this might help:
List<string> full_lines = new List<string>();
System.IO.StreamReader sr = new System.IO.StreamReader(path);
string line = "";
while(!sr.EndOfStream)
{
line = sr.ReadLine();
if(!line.Contains("/"))
{
full_lines[full_lines.Count - 1] += line;
}
else
full_lines.Add(line);
}
change
if (!lines.ElementAt(name_index + 1).StartsWith("SHORT_NAME")) //checking if
//the next line does not start with SHORT_NAME (then it is continuation of NAME)
{
new_line = line + " " + lines.ElementAt(name_index + 1);//appending the next
//line
full_lines.Add(new_line); //adding into new list
}
else
{
full_lines.Add(line);
}
to
new_line = line;
name_index++;
while (!lines.ElementAt(name_index).StartsWith("SHORT_NAME"))
{
new_line = new_line + " " + lines.ElementAt(name_index);//appending the next line
name_index++;
}
full_lines.Add(new_line);
Related
So I have a text file copied into memory that is delimited as follows:
"425,9856\n852,9658\n"
This is a long string with some 30,000 entries in total. What I want to do is create two arrays, one for the value to the left of the comma, one for the value to the right of the comma, and then to each array respectively i want to append the next two comma delimited strings that come after the "\n".
I have tried splitting using .Split and passing two delimiting values, but it obviously just creates one array with all values sequentially. Such as:
425
9856
852
9658
When what I want is:
array1:
452
852
array2:
9856
9658
Does that make sense?
many thanks
Since you're reading from a file, why not stream the input line-by-line, rather than reading the whole lot into memory in one go?
using var reader = new StreamReader(filePath);
while (reader.ReadLine() is not null line)
{
// Each line is of the form '425,9856', so just split on the comma
var parts = line.Split(',');
firstList.Add(parts[0]);
secondList.Add(parts[1]);
}
You can just split it twice to get what you want
public static void Main()
{
var foo = "425,9856" + Environment.NewLine + "852,9658" + Environment.NewLine;
var array1 = new List<string>();
var array2 = new List<string>();
string[] lines = foo.Split(
new string[] { Environment.NewLine },
StringSplitOptions.None);
foreach(var line in lines)
{
//Console.WriteLine("line: " + line);
var lineSplit = line.Split(',');
//Console.WriteLine("lineSplit: " + lineSplit.Length);
//lineSplit.Dump();
if(lineSplit.Length > 1)
{
array1.Add(lineSplit[0]);
array2.Add(lineSplit[1]);
}
}
Console.WriteLine("Array1: ");
array1.Dump();
Console.WriteLine("Array2: ");
array2.Dump();
}
And here's a working fiddle of it.
You can use RegEx
string row = #"425,9856\n852,9658\n";
string left = #"[^|(?<=n)]\d*(?=,)";
string right = #"(?<=,)\d*(?=\\)";
Regex rgLeft = new Regex(left);
var l = rgLeft.Matches(row).Select(p=> p.Value);
Regex rgRight = new Regex(right);
var r = rgRight.Matches(row).Select(p=> p.Value);
I have to read a text file and if line contains ".engineering $name" then look for line which contains ".default" and do some operation with this line. I need to keep reading lines until I find ".default" in a set of lines. (This set is like, until I hit next ".engineering"). Loop continue like this again for next ".engineering $name"
Note:
".engineering" keyword is fixed string, $name reading dynamically,
".default" is fixed string,
I am able to do the first part that is reading line which contains ".engineering $name"
I am unable to get logic for next part, finding ".default" until it hits next ".engineering"
Looking for logic or code for this logic in C#. Thank you
Code:
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
using (var reader = new StreamReader(stream))
{
while (!reader.EndOfStream)
{
string[] def_arr = null;
var line1 = reader.ReadLine();
if (line1.Contains(".engineering " + name + " ") && !reader.EndOfStream)
{
var nextLine = reader.ReadLine(); // nextLine contains ".default"
def_arr = nextLine.Split(' ');
def_val = def_arr[1].Replace("\"", "");
port_DefaultValues.Add(name + ", " + def_val);
}
}
}
var nextLine is the line containing ".default". I have coded like immidiate next line of finding ".engineering" is having ".default".But it is not always the case. ".default" can be in any line before it hits next ."engineering".
I hope the problem statement is clear.
Try this code -
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
using (var reader = new StreamReader(stream))
{
while (!reader.EndOfStream)
{
string[] def_arr = null;
var line1 = reader.ReadLine();
if (line1.Contains(".engineering " + name + " ") && !reader.EndOfStream)
{
var nextLine = reader.ReadLine(); // nextLine contains ".default"
while (!nextLine.Contains(".default") && !reader.EndOfStream)
{
nextLine = reader.ReadLine();
}
def_arr = nextLine.Split(' ');
def_val = def_arr[1].Replace("\"", "");
port_DefaultValues.Add(name + ", " + def_val);
}
}
}
I have just added a loop that will keep reading the next line until it encounters .default. Keep in mind it will throw exception if that is not found in rest of the file.
I'm relatively new to programming and I've set up a "fairly" simple task for me to work on. What I am trying to accomplish is clicking on a "Settings" button on Form1 that will open and post the results of "config.txt" to labels on Form2.
Config.txt looks like this:
[VERSION] 7544
[WIDTH] 480
[HEIGHT] 768
[SCALE] 1
[UI] 8
[SERVER] 2
[DEMO] 1
[BRIGHT] 50
[CURSOR] 1
I have been able to create the .txt file if it does not exist with default values using
using (StreamWriter sw = new StreamWriter("config.txt"))
{
sw.Write("[DATA1] 7544");
sw.Write("[DATA2] 8");
sw.Write("[DATA3] 2");
}
I'm having issues reading the lines of code separately and displaying them to separate labels.
int counter = 0;
string line;
System.IO.StreamReader file = new System.IO.StreamReader(#"config.txt");
while ((line = file.ReadLine()) != null)
{
//System.Console.WriteLine(line);
string labelTest = string.Format(line);
labelVersRead.Text = "Version: " + line;
counter++;
}
file.Close();
I believe the issue I'm having is saying var line3 = line[3]. I can only get it to output the complete .txt into a single string.
In that case you could have a list.
var list = new List<Config>();
public class Config{
string LabelText
string LabelValue
}
while ((line = file.ReadLine()) != null)
{
//Split the line based on the pattern and build the list object for Labeltext and LabelValue.
//You will have to come up with the logic to split the line into string based on the pattern. Where text in the [] is LabelTesxt and anything followed after ] is LabelValue
list.Add(new Config{LavelText = "VERSION" ,LabelValue="7544"});
counter++;
}
//Once done, you could bind the data to the label
var item = list.Find(item => item.LabelText == "VERSION");
lblVersionLabel.Text = item.LabelValue
It looks like you always overriding the Text for the label.
Use + to append the text.
labelVersRead.Text += "Version: " + line;
Or with new line at the end
labelVersRead.Text += "Version: " + line + "\r\n";
Is it this solve the issue you encounter ?
I am working on a method that reads txt file with multiple lines and then turns it into a txt file with only single line.
Like this:
first line,
second line,
third line.
Into this:
first line, second line, third line.
I have this code but it only shows "third line." in file:
MAIN:
static void Main(string[] args)
{
string fLine= "first line,\n second line,\n third line.";
string sLine= "";
Console.Write(fLine);
Console.WriteLine();
Console.Write(sLine);
string filDat1 = "D:\\Dat1.txt";
string filDat2 = "D:\\Dat2.txt";
if (File.Exists(filDat1))
Console.WriteLine("File already exist!");
else
{
File.WriteAllText(filDat1, fLine);
}
File.WriteAllText(filDat2, sLine);
changeFile(filDat1);
Console.ReadKey();
}
METHOD:
public static void changeFile(string name)
{
StringBuilder dato;
string filDat2 = "D:\\Dat2.txt";
try
{
string[] lines = File.ReadAllLines(name);
foreach (string line in lines)
{
Console.WriteLine("Words in file: " + line);
}
Console.WriteLine();
Console.Write("New words in new file: ");
foreach (string line in lines)
{
string line1 = line;
dato = new StringBuilder();
line1 = line1.Replace("\n", " ");
for (int i = 0; i < line1.Count(); i++)
{
if (!line1[i].Equals(""))
{
dato.Append(line1[i] + "");
}
}
Console.WriteLine(dato);
File.WriteAllText(filDat2, dato.ToString());
}
}
I don't know what I'm doing wrong. I only get the last word in my case "third word." in new file Dat2.txt.
Also, is there any way to create a method that can take two files. One file to read and one file to write that changed text to it?
Here is a method to make anew file for given file with only 1 line:
public static void changeFile(string InputPath,string OutputPath)
{
List<string> OUTPUT = new List<string>();
StreamReader sr = new StreamReader(InputPath);
while (!sr.EndOfStream)
{
OUTPUT.Add(sr.ReadLine());
}
sr.Close();
StreamWriter fs = new StreamWriter(OutputPath);
string output = "";
foreach (string line in OUTPUT)
{
output += line + " ";
}
fs.WriteLine(output);
fs.Close();
}
In case you were curious as to why your approach didn't work, it was because you reset dato every iteration, just move that outside and away you go, I've also moved the write outside too since you only need to do that once.
dato = new StringBuilder();
foreach (string line in lines)
{
string line1 = line;
line1 = line1.Replace("\n", " ");
for (int i = 0; i < line1.Count(); i++)
{
if (!line1[i].Equals(""))
{
dato.Append(line1[i] + "");
}
}
Console.WriteLine(dato);
}
File.WriteAllText(filDat2, dato.ToString());
I want to write a string next to a line, randomly could be any line, also I want to know how to delete a line from it, here is how my StreamReader works:
using (StreamReader sb = new StreamReader("admin.txt"))
{
string[] ffoo = File.ReadAllLines("admin.txt");
string[] ppoof = ffoo[0].Split(';');
string line;
while ((line = sb.ReadLine()) != null)
{
if (line.StartsWith("#" + Server.Name.ToLower() + ": "))
{
string[] punch = line.Split(';');
if (!punch.Contains(Channel.Name.ToLower()))
{
StringBuilder str = new StringBuilder("admin.txt");
str.Append(Channel.Name.ToLower() + ";");
return;
}
}
}
Here is how the list is made:
#main: alien;nobody;somebody;
#devs: headdev;wae;
It reads it fine just it can't write something next to main channel, I mean I can only write a line or a string next to end of it which is on dev, and I want to write something on main, also I have some problems on how to delete an admin from main or dev. also this file would be oversize, maybe includes 500 lines at all after we use it, so please if you can give a solution for big files, thanks!
When calling StringBuilder.Append it appends to the end of the string.
When calling the StringBuilder(string) constructor it will append to the string passed as parameter for the constructor.
In this case you are passing "Admin.txt" as a string, but you really want to pass the content of Admin.txt, so you need to read the content of it.
This should do the trick:
string[] lines = File.ReadAllLines("admin.txt");
for (int i = 0; i < lines.Length; i++)
{
if (lines[i].StartsWith(string.Format("#{0}: ", Server.Name.ToLower()))
{
if (!lines[i].Split(';').Contains(Channel.Name.ToLower()))
lines[i] += ";" + Channel.Name.ToLower();
}
}
File.WriteAllLines("admin.txt", lines);
I'm sorry if I misunderstood what you wanted to do though.