StringReader not "exiting"/breaking - c#

I am experiencing a problem with the below code… When I run it the code never exits. I have tried to debug this for about an hour and I am at a complete loss as to what the problem is. OutputDebug(); is essentially like Console.WriteLine();
//Iterate through all lines to find sections
using (StringReader lineReader = new StringReader(Program))
{
int i = 0;
string line = string.Empty;
while (line != null)
{
line = lineReader.ReadLine();
if (line != string.Empty)
{
//If the program is exiting (doExit == true), then break the lööp bröther
if (doExit)
break;
//Iterate through all characters in the line
foreach (char Character in line)
{
i++;
OutputDebug(i.ToString());
if (isOnSameLineAsSectionStart)
{
sectionName += Character;
}
else if (Character == ':' && sectionName == string.Empty)
{
isOnSameLineAsSectionStart = true;
}
else if (Character == ':' && !isOnSameLineAsSectionStart && sectionName != string.Empty)
{
OutputDebug("End of section \"" + sectionName + "\" found");
OutputDebug(linesInSection.Count() + " lines found total in " + sectionName + "\" during section search");
try
{
sections.Add(sectionName, linesInSection);
}
catch (Exception)
{
OutputError("Two/Multiple sections with the same names exist. Ignoring the latest section with the same name");
}
linesInSection = new List<string>();
sectionName = string.Empty;
isOnSameLineAsSectionStart = true;
}
}
if (!isOnSameLineAsSectionStart && sectionName != string.Empty)
{
linesInSection.Add(line);
}
if (isOnSameLineAsSectionStart && sectionName != string.Empty)
{
OutputDebug("Start of section \"" + sectionName + "\" found");
}
if (isOnSameLineAsSectionStart == true)
{
isOnSameLineAsSectionStart = false;
}
}
lineReader.Close();
OutputDebug("In StringReader!" + i);
}
Thanks in advance!

you can use while approach below:
while ((line = reader.ReadLine()) != null)
{
foreach (char Character in line)
{
i++;
OutputDebug(i.ToString());
}
}

Well, if you want to output all the characters line by line. You could split them into an array of strings:
var lines = Regex.Split(input, "\r\n|\r|\n") extracted from here.
Later, using a foreach instead of a while statment you should solve the problem:
foreach(string line in lines)
Also comparing a string to a null value... Doesn't look so fine. Why don't use (in-built) string.IsNullOrEmpty(line) method to check if the current line is null?
If you want to use your approach you should do something like this:
while (!string.IsNullOrEmpty(line = reader.ReadLine()))
{
// Your code...
}
Hope this helps!

Since we're limited to this snippet we can only make assumptions.
lineReader.ReadLine();
if this is a blocking call than the code may never exit as long as no input is given.
if this is a unblocking call, it means that it returns something even though no input is provided. If returned value is empty string in this case then you're in infinite loop.
I believe the key function is ReadLine here.

Related

C# if else conditional inside of foreach loop possibly using count

I have working example without the conditional here.
public string RenderPostTags(DMCResultSet resultSet)
{
string output = "";
string filterForm = RenderFilterForm(resultSet);
string pagination = RenderPagination(resultSet);
List<XElement> items = resultSet.items;
foreach(XElement i in items)
{
string tags = "";
if (i.Element("tags") != null)
{
foreach(string tag in i.Element("tags").Elements("tag"))
{
tags += "" + tag + "";
}
}
output += tags;
}
return output;
}
I know just putting a count on it wont work but I've tried several different methods and they haven't worked for me. Could be a syntactical error I'm a total C# noob.
But I need to output adjusted html using a if else conditional similar to this
public string RenderPostTags(DMCResultSet resultSet){
string output = "";
string filterForm = RenderFilterForm(resultSet);
string pagination = RenderPagination(resultSet);
List<XElement> items = resultSet.items;
foreach(XElement i in items){
string tags = "";
if (i.Element("tags") != null) {
int count = 1;
int total = i.Element("tags").Elements("tag").Count;
foreach(string tag in i.Element("tags").Elements("tag")) {
if(count == total){
tags += "" + tag + "";
count++;
}else{
tags += "" + tag +","+ " " + "";
count++;
}
}
}
output += tags;
}
return output;
}
Methods I have tried can be found on this thread.
Foreach loop, determine which is the last iteration of the loop
Thank you for any assitance.
As #Sach said, use the for loop instead of foreach.
string output = "";
List<XElement> items = new List<XElement>();
foreach (XElement i in items)
{
string tags = "";
if (i.Element("tags") != null && i.Element("tags")?.Elements("tag") != null)
{
List<XElement> tagItems = i.Element("tags").Elements("tag").ToList();
if (tagItems == null) continue;
for (int j = 0; j < tagItems.Count(); j++)
{
XElement tag = tagItems[j];
if (j == i.Element("tags")?.Elements("tag").Count() - 1)
{
tags += "" + tag + "";
}
else
{
tags += "" + tag + "," + " " + "";
}
}
}
output += tags;
}
You can write your foreach loop like this to capture both conditions. You can use condition ? true : false to write either/or based on the last item in the collection.
int counter = 1; // Start with 1 since we are using != later on.
int totalRecords = i.Element("tags").Elements("tag").Count();
foreach (string tag in i.Element("tags").Elements("tag"))
tags += "" + tag + counter++ != totalRecords ? ", " : string.Empty + "";
Above is equivalent to
if (i.Element("tags") != null)
{
int counter = 1;
int totalRecords = i.Element("tags").Elements("tag").Count();
foreach (string tag in i.Element("tags").Elements("tag"))
{
if (counter++ == totalRecords)
{
tags += "" + tag + "";
}
else
{
tags += "" + tag + ", " + "";
}
}
}
Make a note that IEnumerable does not have a Count property but have a method Count().
So maybe for namespace reasons the count method would not solve my issue.
However after some toil this solution worked perfectly. Thankyou for those to helped me get to this solution.
public string RenderPostTags(DMCResultSet resultSet){
string output = "";
string filterForm = RenderFilterForm(resultSet);
string pagination = RenderPagination(resultSet);
List<XElement> items = resultSet.items;
foreach(XElement i in items){
string tags = "";
if (i.Element("tags") != null) {
foreach(string tag in i.Element("tags").Elements("tag")){
if(tags != "") tags += ", ";
tags += "" + tag +"";
}
}
output += tags;
}
return output;
}

If a specific string is not in the file, I'm trying to report a message. I keep getting the same message

I'm reading a text file. If a specific string is not in the file, I'm trying to report a message. I keep getting the same message over again, or, not at all depending on where I put it.
I have moved this (code just above counter++; near the bottom)
"else lbOne.Items.Add(txtID.Text + " does not exist.");" around to every conceivable line with no luck. I know just enough to be dangerous, so could use some help with this.
if (rButtonFind.Checked)
{
int counter = 0;
string line;
System.IO.StreamReader file = new System.IO.StreamReader(#"F:\Quality\CMM Fixtures\fixtures.txt");
if (new FileInfo(#"F:\09 Quality\CMM Fixtures\fixtures.txt").Length == 0)
{
MessageBox.Show("There is no data in the file to search." + "\n" + "There must be at least one fixture" + "\n" + " to not see this message.");
}
while ((line = file.ReadLine()) != null)
{
if (line.Contains(txtID.Text))
{
lbOne.Items.Add(line);
}
else
lbOne.Items.Add(txtID.Text + " does not exist.");
counter++;
}
file.Close();
}
}
As I said, it either lists the "does not exist" message many times, or not at all.
Since you need to know only if the file contains at least one occurrence of the string, then this is the code you need. But you also need to better defend against the file not existing.
I don't know if counter is supposed to be a count of lines read or if it's supposed to indicate a count of times the string is not found. I just assumed it's a count of times the string is not found. But regardless, the scope of counter is within the if block and so there's no use for it unless you intend to do something with it later, in which case you'll have to change its scope.
if (rButtonFind.Checked) {
int counter = 0;
string line;
string filename = #"F:\Quality\CMM Fixtures\fixtures.txt";
System.IO.StreamReader file = new System.IO.StreamReader(filename);
if (new FileInfo(filename).Length == 0) {
MessageBox.Show("There is no data in the file to search." + "\n" + "There must be at least one fixture" + "\n" + " to not see this message.");
} else {
bool found = false;
while ((line = file.ReadLine()) != null) {
if (line.Contains(txtID.Text)) {
lbOne.Items.Add(line);
found = true;
break;
}
}
if (!found) {
lbOne.Items.Add(txtID.Text + " does not exist.");
counter++;
}
}
file.Close();
}
I found the answer by playing with Jeff's code. By simply switching the bool declaration to true, and then the if found to "!true", and removing the break, it works as it should. I would not have gotten this without Jeffs help. I double asterisked the changes I made to Jeffs code that made it work.
bool found = **true**;
while ((line = file.ReadLine()) != null)
{
if (line.Contains(txtID.Text))
{
lbOne.Items.Add(line);
found = **!true**;
}
counter++;
}
if (**found**)
{
lbOne.Items.Add(txtID.Text + " does not exist.");
}
file.Close();

Read file, check correctness of column, write file C#

I need to check certain columns of data to make sure there are no trailing blank spaces. At first thought I thought it would be very easy, but after attempting to achieve the goal I have got stuck.
I know that there should be 6-digits in the column I need to check. If there is less I will reject, if there are more I will trim the blank spaces. After doing that for the entire file, I want to write it back to the file with the same delimiters.
This is my attempt:
Everything seems to be working correctly except for writing the file.
if (File.Exists(filename))
{
using (StreamReader sr = new StreamReader(filename))
{
string lines = sr.ReadLine();
string[] delimit = lines.Split('|');
while (delimit[count] != "COLUMN_DATA_TO_CHANGE")
{
count++;
}
string[] allLines = File.ReadAllLines(#filename);
foreach(string nextLine in allLines.Skip(1)){
string[] tempLine = nextLine.Split('|');
if (tempLine[count].Length == 6)
{
checkColumn(tempLine);
writeFile(tempLine);
}
else if (tempLine[count].Length > 6)
{
tempLine[count] = tempLine[count].Trim();
checkColumn(tempLine);
}
else
{
throw new Exception("Not enough numbers");
}
}
}
}
}
public static void checkColumn(string[] str)
{
for (int i = 0; i < str[count].Length; i++)
{
char[] c = str[count].ToCharArray();
if (!Char.IsDigit(c[i]))
{
throw new Exception("A non-digit is contained in data");
}
}
}
public static void writeFile(string[] str)
{
string temp;
using (StreamWriter sw = new StreamWriter(filename+ "_tmp", false))
{
StringBuilder builder = new StringBuilder();
bool firstColumn = true;
foreach (string value in str)
{
if (!firstColumn)
{
builder.Append('|');
}
if (value.IndexOfAny(new char[] { '"', ',' }) != -1)
{
builder.AppendFormat("\"{0}\"", value.Replace("\"", "\"\""));
}
else
{
builder.Append(value);
}
firstColumn = false;
}
temp = builder.ToString();
sw.WriteLine(temp);
}
}
If there is a better way to go about this, I would love to hear it. Thank you for looking at the question.
edit:
file structure-
country| firstname| lastname| uniqueID (column I am checking)| address| etc
USA|John|Doe|123456 |5 main street|
notice the blank space after the 6
var oldLines = File.ReadAllLines(filePath):
var newLines = oldLines.Select(FixLine).ToArray();
File.WriteAllLines(filePath, newLines);
string FixLine(string oldLine)
{
string fixedLine = ....
return fixedLine;
}
The main problem with writing the file is that you're opening the output file for each output line, and you're opening it with append=false, which causes the file to be overwritten every time. A better approach would be to open the output file one time (probably right after validating the input file header).
Another problem is that you're opening the input file a second time with .ReadAllLines(). It would be better to read the existing file one line at a time in a loop.
Consider this modification:
using (StreamWriter sw = new StreamWriter(filename+ "_tmp", false))
{
string nextLine;
while ((nextLine = sr.ReadLine()) != null)
{
string[] tempLine = nextLine.Split('|');
...
writeFile(sw, tempLine);

If not called. c# [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
incorrectly checks the response c#
I have a code:
Match match = regex.Match(responseFromServer);
if (match.Success)
{
var input = responseFromServer;
var split = input.Split(':');
var final = split[3];
ProcessStartInfo mcStartInfo = new Shitocode;
Process.Start(mcStartInfo);
this.Close();
}
else if (responseFromServer == " Bad Login")
{
MessageBox.Show("Uncorrect login/password!");
}
else if (responseFromServer == " Old version")
{
MessageBox.Show("Launcher is old!");
}
Why there is no message box showing in the last two inspections?
I have tried to do things differently:
if (match.Success)
{
var input = responseFromServer;
var split = input.Split(':');
var final = split[3];
ProcessStartInfo mcStartInfo = new Shitocode;
Process.Start(mcStartInfo);
this.Close();
}
else if (responseFromServer.Equals("Bad Login"))
{
MessageBox.Show("Uncorrect login/password!");
}
else if (responseFromServer.Equals("Old Version"))
{
MessageBox.Show("Launcher is old!");
}
I enter the wrong password, but does not open the messagebox
string s = instxtbox.Text;
string[] s1 = new string[3];
s1[0] = " ";
s1[1] = " ";
s1[2] = " ";
string[] portion = s.Split(s1, StringSplitOptions.RemoveEmptyEntries);
int val = Convert.ToInt32(portion[2]);
string reg = portion[1];
if (reg == "ax")
axtxtbox.Text = portion[2];
else if (reg == "bx")
bxtxtbox.Text = portion[2];
else if (reg == "cx")
cxtxtbox.Text = portion[2];
else if (reg == "dx")
dxtxtbox.Text = portion[2];
Probably your responseFromServer does not match the values you are checking (Bad Login, and Old Version).
Try to add another else at the end of the if sequence and look what you've got.
if (match.Success)
{
//your code
}
else if (responseFromServer.Equals("Bad Login"))
{
MessageBox.Show("Uncorrect login/password!");
}
else if (responseFromServer.Equals("Old Version"))
{
MessageBox.Show("Launcher is old!");
}
else
{
MessageBox.Show("Cannot login, unknown response: " + responseFromServer)
}
EDIT after comment
If you do not the exact message, but you know that it has to contain some exact string, you could change the two responseFromServer.Equals() to responseFromServer.Contains()
Just set a breakingpoint, go through the code and check the Value of responseFromServer Copy this in the two cases and compare it in your code, i noticed you have whitespaces in the 1st code part before " Bad Login", but im not sure its the reason anyway.

C# text creation issue

This is whats going on. I have a huge text file that is suppose to be 1 line per entry. The issue is sometimes the line is broken with a new line.
I edit this entire file and wherever the file doesn't begin with ("\"A) i need to append the current line to the previous line ( replacing \n with " "). Everything I come up with keeps appending the line to a new line. Any help is appricated...
CODE:
public void step1a()
{
string begins = ("\"A");
string betaFilePath = #"C:\ext.txt";
string[] lines = File.ReadAllLines(betaFilePath);
foreach (string line in lines)
{
if (line.StartsWith(begins))
{
File.AppendAllText(#"C:\xt2.txt",line);
File.AppendAllText(#"C:\xt2.txt", "\n");
}
else
{
string line2 = line.Replace(Environment.NewLine, " ");
File.AppendAllText(#"C:\xt2.txt",line2);
}
}
}
Example:
Orig:
"\"A"Hero|apple|orange|for the fun of this
"\"A"Hero|apple|mango|lots of fun always
"\"A"Her|apple|fruit|no
pain is the way
"\"A"Hero|love|stackoverflowpeople|more fun
Resulting:
"\"A"Hero|apple|orange|for the fun of this
"\"A"Hero|apple|mango|lots of fun always
"\"A"Her|apple|fruit|no pain is the way
"\"A"Hero|love|stackoverflowpeople|more fun
my problem isnt the finding the if (line.StartsWith(begins)) its the else statement, it appends line2 to a new line
it seems like your string is not well formated...
try this "\"\\\"A\"" instead
public void step1a()
{
string begins = ("\"\\\"A\"");
string betaFilePath = #"C:\ext.txt";
string[] lines = File.ReadAllLines(betaFilePath);
foreach (string line in lines)
{
if (line.StartsWith(begins))
{
File.AppendAllText(#"C:\xt2.txt",line);
File.AppendAllText(#"C:\xt2.txt", "\n");
}
else
{
string line2 = line.Replace(Environment.NewLine, " ");
File.AppendAllText(#"C:\xt2.txt",line2);
}
}
}
This does what you want:
CopyFileRemovingStrayNewlines(#"C:\ext.txt", #"C:\xt2.txt", #"""\""A");
With this method:
public static void CopyFileRemovingStrayNewlines(string sourcePath, string destinationPath, string linePrefix)
{
string[] lines = File.ReadAllLines(sourcePath);
bool firstLine = true;
foreach (string line in lines)
{
if (line.StartsWith(linePrefix))
{
if (!firstLine)
File.AppendAllText(destinationPath, Environment.NewLine);
else
firstLine = false;
File.AppendAllText(destinationPath, line);
}
else
{
File.AppendAllText(destinationPath, " ");
File.AppendAllText(destinationPath, line);
}
}
}
It does have the problem of appending to an existing file, though. I suggest using a StreamWriter rather than AppendAllText. Like this:
public static void CopyFileRemovingStrayNewlines(string sourcePath, string destinationPath, string linePrefix)
{
string[] lines = File.ReadAllLines(sourcePath);
bool firstLine = true;
using (StreamWriter writer = new StreamWriter(destinationPath, false))
{
foreach (string line in lines)
{
if (line.StartsWith(linePrefix))
{
if (!firstLine)
writer.WriteLine();
else
firstLine = false;
writer.Write(line);
}
else
{
writer.Write(" ");
writer.Write(line);
}
}
}
}
Your problem is that the \ is a C# escape code.
Your string is parsed as "A, because \" is the escape code for a single ".
You should make the begins string an #-string, which does not use escape codes.
You will then need to escape the " by doubling it up.
For example:
const string begins = #"\""A";
Note that the best way to do this is to use a StreamWriter, like this:
using(StreamWriter writer = File.Create(#"C:\xt2.txt"))
{
foreach (string line in lines)
{
if (line.StartsWith(begins))
writer.WriteLine(); //Close the previous line
writer.Write(line);
}
}
Based on #SLaks's example here is some code that should do the trick:
public static void step1a()
{
string betaFilePath = #"C:\ext.txt";
string[] lines = File.ReadAllLines(betaFilePath);
using (StreamWriter writer = new StreamWriter(File.Create(#"C:\xt2.txt")))
{
string buffer = null;
foreach (string line in lines)
{
if (!line.StartsWith(begins))
{
writer.WriteLine(buffer + line);
buffer = null;
}
else
{
if (buffer != null)
writer.WriteLine(buffer);
buffer = line;
}
}
if(buffer != null)
Console.Out.WriteLine(buffer);
}
}

Categories

Resources