Greets.
I'm calling a Window with .ShowDialog() and returning some lines form a textbox.
The lines return back to a List<>, but each character in the textbox getting returned is getting assigned to it's own index value within the List<>.
I essentially want to add an entire line from the textbox to it's own index value in the List<>
EXAMPLE:
I enter the below in the textbox that was called from the ShowDialog();
123456
87564
125
How do I add each line from the textbox to it's own index on the list?
This is what I have now. (No code on the textbox window that I enter these values into) (I realize I spelled it as imput...) When I debug and review the pos List<>, each character has it's own index ID..
private void GetPOs()
{
MultiLineImput getPOList = new MultiLineImput();
getPOList.ShowDialog();
foreach (char po in getPOList.listOfPOs.Text)
{
pos.Add(po.ToString());
}
if (pos.Count > 0)
{
string a = String.Join("", pos);
MessageBox.Show(a, "POs to Process");
}
else
{
if (!getPOList.wasCanceled.Equals(1))
{
MessageBox.Show("No values were passed", "Warning");
}
}
}
You're iterating over the characters of Text property, so each character is converted to string and added to list separately.
I'm not sure what you mean by adding the entire "line". In your example there's only one line, so you can rewrite this loop
foreach (char po in getPOList.listOfPOs.Text)
{
pos.Add(po.ToString());
}
to simply
pos.Add(getPOList.listOfPOs.Text);
if you meant to split this line in entries "123456", "87564", "125", you can do the following way:
foreach (string po in getPOList.listOfPOs.Text.Split(' '))
{
pos.Add(po);
}
if your textbox indeed support multiline input, you can split by Environment.NewLine, like this:
foreach (string po in getPOList.listOfPOs.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None))
{
pos.Add(po);
}
If you iterate over a string, the iterator will pull one character at a time. It has no idea what a line break is.
I suggest you break the string up by line breaks, then iterate over the result, like so:
MultiLineInput getPOList = new MultiLineInput();
getPOList.ShowDialog();
var wholeText = getPOList.listOfPOs.Text;
var lines = wholeText.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
foreach (string po in getPOList.listOfPOs.Text)
{
pos.Add(po);
}
//Etc.....
Related
I`m new in c#, I'm still learning that language. Now I try to make app which read text and to my data i need only specific lines. Text look like:
[HAEDING]
Some value
[HEADING]
Some other value
[HEADING]
Some other text
and continuation of this text in new line
[HEADING]
Last text
I try to write method which read text and put it into string[] by split it like this:
string[0] = Some value
string[1] = Some other value
string[2] = Some other text and continuation of this text in new line
string[3] = Last text
So I want to read line from value [HEADING] to value new line which is empty. I thought that is should write by ReadAllLines and line by line check start position on value [HEADING] and end position on empty value in new line. I try this code:
string s = "mystring";
int start = s.IndexOf("[HEADING]");
int end = s.IndexOf("\n", start);
string result = s.Substring(start, end - start);
but it's substring to all lines in my text not like loop between first [HEADING] and empty new line, second etc.
Maybe someone can help me with this?
You could try to split the string by "[HEADING]" to get the strings between these lines. Then you could join each string into a single line and trim the whitespace around the strings:
string content = #"[HEADING]
Some value
[HEADING]
Some other value
[HEADING]
Some other text
and continuation of this text in new line
[HEADING]
Last text";
var segments = content.Split(new[] { "[HEADING]"}, StringSplitOptions.RemoveEmptyEntries) // Split into multiple strings
.Select(p=>p.Replace("\r\n"," ").Replace("\r"," ").Replace("\n"," ").Trim()) // Join each single string into single line
.ToArray();
Result:
segments[0] = "Some value"
segments[1] = "Some other value"
segments[2] = "Some other text and continuation of this text in new line"
segments[3] = "Last text"
Here's a solution which avoids the substring/index checking, which could potentially be fraught with errors.
There are answers such as this one that use LINQ, but for a newcomer to the language, basic looping is an OK place to start. Also, this is not necessarily the best solution for efficiency or whatever.
This foreach loop will handle your case, and some of the "dirty" cases.
var segments = new List<string>();
bool headingChanged = false;
foreach (var line in File.ReadAllLines("somefilename.txt"))
{
// skip blank lines
if (string.IsNullOrWhitespace(line)) continue;
// detect a heading
if (line.Contains("[HEADING]")
{
headingChanged = true;
continue;
}
if (headingChanged)
{
segments.Add(line);
// this keeps us working on the same segment if there
// are more lines to be added to the segment
headingChanged = false;
}
else
{
segments[segments.Length - 1] += " ";
segments[segments.Length - 1] += line;
// you could replace the above two lines with string interpolation...
// segments[segments.Length - 1] = $"{segments[segments.Length - 1]} {line}";
}
}
In the above loop, the ReadAllLines obviates the need to check for \r and \n. Contains will handle [HEADING] no matter where it changes.
You don't need substring, you can just compare the value s == "[HEADING]".
Here's an easy to understand example:
var lines = System.IO.File.ReadAllLines(myFilePath);
var resultLines = new List<String>();
var collectedText = new List<String>();
foreach (var line in lines)
{
if (line == "[HEADING]")
{
collectedText = new List<String>();
}
else if (line != "")
{
collectedText.Add(line);
}
else //if (line == "")
{
var joinedText = String.Join(" ", collectedText);
resultLines.Add(joinedText);
}
}
return resultLines.ToArray();
the loop does this:
we go line by line
"start collecting" (create list) when we encounter with "[HEADING]" line
"collect" (add to list) line if not empty
"finish collecting" (concat and add to results list) when line is empty
I opened a text file and showed it in a listbox (lstArchivo) every string is divided by a semi colon (;) i'm trying to split every string in that listbox (lstArchivo) that has the semicolon. The problem i'm having is that when i display the new splitted list in listbox1 the output i get is String[] Array in every item. Is it better to split every string reading from textfile directly or reading from listbox?
string[] strFields;
string strLine;
char[] charDelimiter = { ';' };
foreach(string item in lstArchivo.Items)
{
strLine = lstArchivo.Items.ToString();
strFields = strLine.Split(charDelimiter);
listBox1.Items.Add(strFields);
}
this is the code i have
You could use code like this:
char[] charDelimiter = { ';' };
foreach(string item in lstArchivo.Items)
{
strFields = item.Split(charDelimiter);
listBox1.Items.Add(strFields[0]);
}
Note that we are splitting on "item" from your foreach loop.
I'm trying to grab a text from html page using HtmlAgilityPack. here is my code
var headers = doc.DocumentNode.SelectNodes("//h2");
if (headers != null)
{
foreach (HtmlNode item in headers)
{
textBox1.AppendText(item.InnerText);
Console.WriteLine(item.InnerText);
}
}
It show different results on the console and the textbox.
result on console:
Avril
Lavigne
result on textBox:
AvrilLavigne
I want it like:
Avril Lavigne
I can't figure out what the character between two words.
The original text on the html is : Avril Lavigne there is already space between Avril and Lavigne. but it does not on textbox.
Console.WriteLine write your input and then add Environement.NewLine after it.
You can use
var headers = doc.DocumentNode.SelectNodes("//h2");
if (headers != null)
{
textBox1.AppendText(string.Join(' ', headers.Select(item => item.innerHTML)));
}
Which will join each of you item.innerHTML and adding a space in between.
Try adding all of the text elements to an array and then pass that array to
var arr = new List<string>();
foreach(var item in items){
arr.Add(item.InnerText);
}
textBox1.AppendText(string.Join(" ", arr));
The TextBox control's AppendText method just appends whatever string you pass to it to the end of the control's Text property. The Console class's WriteLine method appends the string you pass to it to the console, and then it appends the end of line characters, that is, a carriage return & line feed.
If you want your text in the TextBox and in the console to be separated with spaces, you'll have to construct it yourself:
bool isFirst = true;
foreach (HtmlNode item in headers)
{
string textToAppend = (isFirst ? string.Empty : " " ) + item.InnerText;
isFirst = false;
textBox1.AppendText(textToAppend);
Console.Write(textToAppend);
}
In this case, Console.Write just outputs the string you pass to it without adding any end of line characters.
:58A:/C/81000098099CL
CBNINGLA
:72:/CODTYPTR/012
/CLEARING/0003
/SGI/DBLNNGLA
am trying to read the swift message above, line :58A: and line :72:, am having a little issue. My code only reads line :58A: like this C/81000098099CL, but I want it to read down the line before getting to line :72:, in short, the output should be like this for line :58A: C/81000098099CL CBNINGLA.
Same also for line :72:, this is because the messages come formatted in this form. This is my code below
if (line.StartsWith(":58A:"))
{
string[] narr = line.Split('/');
inflow202.BENEFICIARY_INSTITUTION = narr[2];
}
if (line.StartsWith(":72:"))
{
inflow202.RECEIVER_INFORMATION = line.Substring(5);
}
You can replace all new lines not followed by : with spaces (or empty string).
string output = Regex.Replace(text, #"\r?\n(?!:)", " ");
string[] lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
if (line.StartsWith(":58A:"))
{
}
else if (line.StartsWith(":72:"))
{
}
}
If the message always comes formatted in this form and : never occurs in the text except for these line starters, consider splitting the whole text into an array by : first. On 0th position there will be nothing, on all odd positions will be the number, on all even positions will be the content until next :. This solution will work providing that you are able to read the whole input into a single string first. I.e. having string message, you can do something like:
var splitted = message.Split(':');
for (i=1;i<= splitted.Length -1; i+=2){
if (splitted[i] == "58A") {
//do what you need to do, the text you need is stored in splitted[i+1]
}
...
}
I'm trying to get the contents of a Text File, delete a line of string, and re-write back to the Text File, deleting the line of string. I'm using StreamReader to get the text, importing into a List, removing the string, then rewriting using StreamWriter. My problems arises somewhere around the removing or writing of the string. Instead of writing back the existing, non deleted contents to the text file, all the text is replaced with :
System.Collections.Generic.List`1[System.String]
My code for this function is as follows:
{
for (int i = deleteDevice.Count - 1; i >= 0; i--)
{
string split = "";
//deleteDevice[i].Split(',').ToString();
List<string> parts = split.Split(',').ToList();
if (parts.Contains(deviceList.SelectedItem.ToString()))
{
deleteDevice.Remove(i.ToString());
}
}
if (deleteDevice.Count != 0) //Error Handling
{
writer.WriteLine(deleteDevice);
}
}
deviceList.Items.Remove(deviceList.SelectedItem);
}
I would just like the script to write back any string that isn't deleted (If there is any), without replacing it. Any help is appreciated, Cheers
You can read all the info from the text file into a list and then remove from the list and rewrite that to the text file.
I would change the list 'deleteDevice' to store a string array instead and use the code below to determine which item to remove.
List<int> toRemove = new List<int>();
int i = 0;
/*build a list of indexes to remove*/
foreach (string[] x in deleteDevice)
{
if (x[0].Contains(deviceList.SelectedItem.ToString()))
{
toRemove.Add(i);
}
i++;
}
/*Remove items from list*/
foreach (int fd in toRemove)
deleteDevice.RemoveAt(fd);
/*write to text file*/
using (StreamWriter writer = new StreamWriter("Devices.txt"))
{
if (deleteDevice.Count != 0) //Error Handling
{
foreach (string[] s in deleteDevice)
{
StringBuilder sb = new StringBuilder();
for (int fds = 0; fds < s.Length; fds++ )
{
sb.Append(s[fds] + ",");
}
string line = sb.ToString();
writer.WriteLine(line.Substring(0, line.Length - 1));
}
}
}
This isn't the best solution but should work for your needs. There's probably a much easier way of doing this.
The problem is in the following line:
writer.WriteLine(deleteDevice);
You're writing deleteDevice (I assume this is of type List). List.ToString() returns the type name of the list, because this has no specific implementation. What you want is
foreach(String s in deleteDevice)
{
writer.WriteLine(s);
}
Problems
deleteDevice is of type List<string>, and because it also doesn't overload ToString(), the default behaviour of List<string>.ToString() is to return the name of the type.
Hence your line writer.WriteLine(deleteDevice); writes the string System.Collections.Generic.List1[System.String]`.
Other than that, there are many things wrong with your code...
For example, you do this:
string split = "";
and then on the line afterwards you do this:
List<string> parts = split.Split(',').ToList();
But because split is "", this will always return an empty list.
Solution
To simplify the code, you could first write a helper method that will remove from a file all the lines that match a specified predicate:
public void RemoveUnwantedLines(string filename, Predicate<string> unwanted)
{
var lines = File.ReadAllLines(filename);
File.WriteAllLines(filename, lines.Where(line => !unwanted(line)));
}
Then you can write the predicate something like this (this might not be quite right; I don't really know exactly what your code is doing because it's not compilable and omits some of the types):
string filename = "My Filename";
string deviceToRemove= deviceList.SelectedItem.ToString();
Predicate<string> unwanted = line =>
line.Split(new [] {','})
.Contains(deviceToRemove);
RemoveUnwantedLines(filename, unwanted);