searching for strings in a text file using foreach loops - c#

so I am trying to search a file for some specific strings these strings are stroed in a list and are called universities, Courses and UGPG I am using a Streamreader to load the file in.
the issue I am having is that after the first foreach loop has executed the remaining searches I want to complete return N/a as if the strings are not present in the text file. however I know they are in the text file.
Is there a reason for this or a better way to code this?
my code is below.
any help would be greatly appreciated.
validdirectory = new DirectoryInfo(path);
Vfiles = validdirectory.GetFiles("*.txt");
foreach (FileInfo file in Vfiles)
{
//reads the file contents
bool Stepout = false;
bool nextouterloop = false;
using (StreamReader ReadMessage = new StreamReader(file.FullName))
{
String MessageContents = ReadMessage.ReadToEnd();
Message_Viewer.Text = MessageContents;
foreach (string Uni_Name in Universities)
{
if (MessageContents.Contains(Uni_Name))
{
Display_Uni.Text = Uni_Name;
}
}
foreach (string course in Courses)
{
if (MessageContents.Contains(course))
{
Display_Course.Text = course;
}
Display_Course.Text = "N/A";
}
if (MessageContents.Contains("Postgraduate"))
{
Display_UGPG.Text = "Postgraduate";
}
else if (MessageContents.Contains("Undergraduate"))
{
Display_UGPG.Text = "Undergraduate";
}
Display_UGPG.Text = "N/A";
}
}

Remove the assignement of N/A inside the loop and let it run until completition.
At the end you could just test the content of the textboxes to see if your loops have found something and, if not, set the N/A text
foreach (string course in Courses)
{
if (MessageContents.Contains(course))
Display_Course.Text = course;
}
if (MessageContents.Contains("Postgraduate"))
Display_UGPG.Text = "Postgraduate";
else if (MessageContents.Contains("Undergraduate"))
Display_UGPG.Text = "Undergraduate";
if(string.IsNullOrWhitespace(Display_Course.Text))
Display_Course.Text = "N/A";
if(string.IsNullOrWhitespace(Display_UGPG.Text ))
Display_UGPG.Text = "N/A";
By the way, having you used arrays or lists for the universities and courses I suppose that you want to see all the matching names. Actually, your code writes always the last course and university found in the textboxes overwriting the previous name found.
You should change the line that set the Text property with a call to AppendText (perhaps adding also a newline if the textboxes are multiline = true)
....
Display_Uni.AppendText(Uni_Name + Environment.NewLine);
...
Display_Course.AppendText(course + Environment.NewLine);

Here is a possible solution without the complicated foreach loops:
if (Universities.Select(p => MessageContents.Contains(p)).Any())
{
Display_Uni.Text = Uni_Name;
}
else if (Courses.Select(p => MessageContents.Contains(p)).Any())
{
Display_Course.Text = course;
}
else if (MessageContents.Contains("Postgraduate"))
{
Display_UGPG.Text = "Postgraduate";
}
else if (MessageContents.Contains("Undergraduate"))
{
Display_UGPG.Text = "Undergraduate";
}
else
{
Display_UGPG.Text = "N/A";
}

Related

Is there a way to make foreach loop faster while inserting data into database inside a loop?

I'm inserting message into database for each member inside a foreach loop which makes the application slow as it is going to run 200+ times to add message for each member. I tried to make it parallel foreach loop but that would throw error of connection was open while saving data and I have multiple foreach loop.
Anybody to help out here?
foreach (var item in coachee)
{
MessageRecord MsgRecord = new MessageRecord();
MsgRecord.MessageID = msgID;
MsgRecord.CoachID = coachID;
MsgRecord.CoacheeID = item.CoacheeIdentityID;
MsgRecord.CreatedBy = Session["user"].ToString();
MsgRecord.IsActive = 1;
MsgRecord.CreatedDate = DateTime.Now;
message.DocumentPath = DocumentPath;
bool val = await _repoObjCoach.AddMessageRecordForCoacheeasync(MsgRecord);
if (val)
{
coacheeMails.Add(item.EmailID);
if (item.Parent_Email != null)
{
ParentMails.Add(item.Parent_Email);
}
if (item.PhoneMail != null)
{
PhoneMails.Add(item.PhoneMail);
}
if (Convert.ToInt32(Session["Role"]) == ConstantData.Role.Coach)
{
_repoObjCoach.MessageCreatedNotification(MessageCreatedByCoach.Coachee + Session["user"].ToString(), string.Concat(LinkPageMessageCreated.coachee, item.UserID.ToString()), "", item.CoacheeIdentityID);
}
else
{
_repoObjCoach.MessageCreatedNotification(MessageCreatedByCoach.alternateCoachee + Session["user"].ToString(), string.Concat(LinkPageMessageCreated.coachee, item.UserID.ToString()), "", item.CoacheeIdentityID);
}
}
}

How to filter values read from a text file

I want to get a couple of values from a textfile in C#. Example:
1.sex=male
1.name=barack
1.lastname=obama
1.age = 55
2.sex=female
2.name= kelly
2.lastname=clinton
2.age = 24
3.sex = male
3.firstname= mike
3.lastname= james
3.age= 19
I only want to get all the "name", "lastname" and ages from the textFile, not the "sex". How can I filter this? I have tried something like this, but it only shows 1 value.
var list = new List<string>();
var text = File.ReadAllLines(#"C:\Users\Jal\Desktop\Test.text");
foreach (var s in text)
{
if (s.Contains("Name"))
{
if (s.Contains("Name"))
{
var desc = s.Substring(s.IndexOf("=") + 1);
list.Add(desc);
ListView.Items.Add(desc);
}
}
}
I found this code on Stack Overflow, but it doesn't get all of the values I want.
var names = new List<string>();
var lastnames = new List<string>();
var text = File.ReadAllLines(#"C:\Users\Jal\Desktop\Test.text");
foreach (var s in text)
{
if (s.Contains("lastname"))
{
var lastname = s.Substring(s.IndexOf("=") + 1);
lastnames.Add(lastname);
continue;
}
if (s.Contains("name"))
{
var name = s.Substring(s.IndexOf("=") + 1);
names.Add(name);
continue;
}
}
And in same way you can add another properties.
s.Contains("Name") won't ever be true on this case because it's case-sensitive, and your string in the file is "name".
Try using s.Contains("name")
But you would be better off using a Regex for this kind of thing.

Reading specific lines in a .Log file

I have a log file that I am reading into different objects. One object starts at a Line that contains the words "Announce message" and the following lines contain the data that belongs to that message. This entry stops at a line that contains the word "Disposed".
I want to read all the data from between these 2 lines that, contains certain words.
Im currently using a Dictionary because the line with "Announce message" also contains a UID but the following lines contain the data for that UID.
How would you do that?
This is what i have come up with so far.
public static void P2PLogParser(List<FileInfo> fileList)
{
foreach (FileInfo fi in fileList)
{
//Læser alle linier i csv fil
foreach (var line in File.ReadAllLines(fi.FullName))
{
string MeterUID = GetMeterUID(line);
string MimHashcode = GetMimHashcode(line);
string FirmwareUploadStatus = GetFirmwareUploadStatus(line);
string IsKnown = GetIsKnown(line);
DateTime P2PTimeStamp = GetTimestamp(line);
if (IsMeterEntry(line) && !meters.ContainsKey(MeterUID))
{
string MeterNr = GetMeterUID(line).Replace("4B414D", "");
int meternr = int.Parse(MeterNr, System.Globalization.NumberStyles.HexNumber);
meters.Add(MeterUID, new Meter()
{
MeterUID = MeterUID,
MeterNR = meternr,
P2Pmeterentry = new List<P2PMeterEntry>()
});
}
if (IsMeterEntry(line))
{
P2PMeterEntry p2pmeter = new P2PMeterEntry
{
P2PTimeStamp = P2PTimeStamp,
MimHashcode = MimHashcode,
FirmwareUploadStatus = FirmwareUploadStatus,
IsKnown = IsKnown,
P2PMetersession = new List<P2PMeterSession>()
};
if (IsNoLongerMeterEntry(line))
{
string SessionLevel = GetLevel(line);
string SessionMessage = GetSessionMessage(line);
string Context = GetSessionContext(line);
P2PMeterSession MeterSession = new P2PMeterSession
{
SessionTimeStamp = P2PTimeStamp,
SessionLevel = SessionLevel,
SessionMessage = SessionMessage,
Context = Context
};
meterSession.Add(MeterSession);
}
meters[MeterUID].P2Pmeterentry.Add(p2pmeter);
}
}
}
}
and the IsMeterEntry and IsNoLongerMeterEntry
//IsMeterSession
public static bool IsMeterEntry(string text)
{
return text.ToLower().Contains("announce message received:");
}
public static bool IsNoLongerMeterEntry(string text)
{
return text.ToLower().Contains("context - disposed");
}
Implement a simple state machine with two states: IgnoreLine (initial state) and Announce.
for each line in log
if line contains "Announce message"
read UID
create a StringBuilder
set state=Announce
else if line contains "Disposed"
store the StringBuilder's content in the dictionary[uid]
set state=IgnoreLine
else if state==Announce and line contains "certain words"
append line to StringBuilder

Saving windows form listbox to a text file C#

I'm trying to save the contents of a listbox into a text file. and it works, but instead of the text entered into the list box, I get this:
System.Windows.Forms.ListBox+ObjectCollection
Here is the relevant code I'm using for the form itself.
listString noted = new listString();
noted.newItem = textBox2.Text;
listBox1.Items.Add(textBox2.Text);
var radioOne = radioButton1.Checked;
var radioTwo = radioButton2.Checked;
var radioThree = radioButton3.Checked;
if (radioButton1.Checked == true)
{
using (StreamWriter sw = new StreamWriter("C:\\windowsNotes.txt"))
{
sw.Write(listBox1.Items);
}
}
else if (radioButton2.Checked == true)
{
using (StreamWriter sw = new StreamWriter("C:\\Users\\windowsNotes.txt"))
{
sw.Write(listBox1.Items);
}
}
else if (radioButton3.Checked == true)
{
using (StreamWriter sw = new StreamWriter("../../../../windowsNotes.txt"))
{
sw.Write(listBox1.Items);
}
}
else
{
MessageBox.Show("Please select a file path.");
}
}
The class is just a simple one:
namespace Decisions
{
public class listString
{
public string newItem {get; set;}
public override string ToString()
{
return string.Format("{0}", this.newItem);
}
}
}
You cannot just do
sw.Write(listBox1.Items);
as it's calling .ToString() on the collection object itself.
Try something like:
sw.Write(String.Join(Environment.NewLine, listBox1.Items));
Or loop through each item and ToString the individual item.
You will have to write the items one by one:
using (StreamWriter sw = new StreamWriter("C:\\windowsNotes.txt") {
foreach (var item in listBox1.Items) {
sw.WriteLine(item.ToString());
}
}
You're writing the ToString of the collection to the output stream rather than of the elements of the collection. Iterating over the collection and outputting each one individually would work, and I'm sure there there's a succint Linq (or even more obvious) way of doing that.

C# String manipulation

I am working on an application that gets text from a text file on a page.
Example link: http://test.com/textfile.txt
This text file contains the following text:
1 Milk Stuff1.rar
2 Milk Stuff2.rar
3 Milk Stuff2-1.rar
4 Union Stuff3.rar
What I am trying to do is as follows, to remove everything from each line, except for "words" that start with 'Stuff' and ends with '.rar'.
The problem is, most of the simple solutions like using .Remove, .Split or .Replace end up failing. This is because, for example, formatting the string using spaces ends up returning this:
1
Milk
Stuff1.rar\n2
Milk
Stuff2.rar\n3
Milk
Stuff2-1.rar\n4
Union
Stuff3.rar\n
I bet it's not as hard as it looks, but I'd apreciate any help you can give me.
Ps: Just to be clear, this is what I want it to return:
Stuff1.rar
Stuff2.rar
Stuff2-1.rar
Stuff3.rar
I am currently working with this code:
client.HeadOnly = true;
string uri = "http://test.com/textfile.txt";
byte[] body = client.DownloadData(uri);
string type = client.ResponseHeaders["content-type"];
client.HeadOnly = false;
if (type.StartsWith(#"text/"))
{
string[] text = client.DownloadString(uri);
foreach (string word in text)
{
if (word.StartsWith("Patch") && word.EndsWith(".rar"))
{
listBox1.Items.Add(word.ToString());
}
}
}
This is obviously not working, but you get the idea.
Thank you in advance!
This should work:
using (var writer = File.CreateText("output.txt"))
{
foreach (string line in File.ReadAllLines("input.txt"))
{
var match = Regex.Match(line, "Stuff.*?\\.rar");
if (match.Success)
writer.WriteLine(match.Value);
}
}
I would be tempted to use a regular expression for this sort of thing.
Something like
Stuff[^\s]*.rar
will pull out just the text you require.
How about a function like:
public static IEnumerable<string> GetStuff(string fileName)
{
var regex = new Regex(#"Stuff[^\s]*.rar");
using (var reader = new StreamReader(fileName))
{
string line;
while ((line = reader.ReadLine()) != null)
{
var match = regex.Match(line);
if (match.Success)
{
yield return match.Value;
}
}
}
}
for(string line in text)
{
if(line.EndsWith(".rar"))
{
int index = line.LastIndexOf("Stuff");
if(index != -1)
{
listBox1.Items.Add(line.Substring(index));
}
}
}

Categories