Split array and add to new array in while loop - c#

I have a flat file that I am reading in C# and then attempting to parse. I mean to store the account number in the flat file in an array.
AccountNumber | AccountName | DateCreated
1 | Bob | 1/1/2011
2 | Donna | 3/2/2013
3 | Jake | 2/21/2010
5 | Sally | 4/2/2014
So far this is what my splitting looks like:
//List<string[]> myArrayList = new List<string[]>();
using (StreamReader read = new StreamReader(#"C:\text\Accounts.txt"))
{
string line;
while ((line = read.ReadLine()) != null)
{
string[] parts = line.Split('|');
Console.WriteLine(parts[0]);
//myArrayList.Add(parts[0]);
}
}
How do I store everything that's printed in parts[0] in it's own array outside of the while loop? I've tried doing a list add but I keep getting errors for invalid arguments. I commented out the bits that don't work.

the following code reads the contents of the file, splits the lines, stores it in a list and finally displays the first column in a RichTextBox
private void button1_Click(object sender, EventArgs e)
{
List<string[]> myArrayList = new List<string[]>();
StreamReader read = new StreamReader(#"C:\test\Accounts.txt");
string line;
while ((line = read.ReadLine()) != null)
{
string[] parts = line.Split('|');
//Console.WriteLine(parts[0]);
myArrayList.Add(parts);
}
foreach (var account in myArrayList)
{
richTextBox1.Text = richTextBox1.Text + account[0].ToString() + Environment.NewLine;
}
}

I like MethodMan's suggestion:
// Class structure
public class Account
{
public int AccountNumber;
public string AccountName;
public DateTime DateCreated;
public Account(string[] info)
{
// This is all dependent that info passed in, is already valid data.
// Otherwise you need to validate it before assigning it
AccountNumber = Convert.ToInt32(info[0]);
AccountName = info[1];
DateCrated = DateTime.Parse(info[2]);
}
}
Your code using the class structure:
List<Account> myAccounts = new List<Account>();
using (StreamReader read = new StreamReader(#"C:\text\Accounts.txt"))
{
string line;
while ((line = read.ReadLine()) != null)
{
string[] parts = line.Split('|');
myAccounts.Add(new Account(parts));
}
}
// Do whatever you want after you have the list filled

Related

Read file using FileDialog and save to the List<>

I am trying to read text file and store the information into the List<>.
So far, I managed to read strings off the file and split it, but having trouble storing the information onto the List<>. Perhaps I am trying to do too many things under one function.
using System.IO;
private void openFileDialog_Click(object sender, EventArgs e)
{
if (myOpenFileDialog.ShowDialog() == DialogResult.OK) ;
using (FileStream fStream = File.OpenRead(myOpenFileDialog.FileName))
{
StreamReader reader;
reader = new StreamReader(fStream);
string line;
while ((line = reader.ReadLine()) != null)
{
string[] playerInfo = line.Split(';');
int ID = int.Parse(playerInfo[0]);
string firstName = playerInfo[1];
string lastName = playerInfo[2];
DateTime dob = DateTime.Parse(playerInfo[3]);
List<Player> players = new List<Player>
players.add(new Player(id, firstName, lastName, dob);
}
}
}
When I check with MessageBox.Show, it comes out with 0 for the amount of lines I have in the file...
Perhaps my list.add code is in wrong place.
Thank you for your help and your time
You're creating a new List every time you're iterating over a new line, that's probably why you're not getting the correct amount of lines.
I also saw you have a few sintax errors in your code, I'll asume that you didn't copy/paste the code directly from the source and that's the reason of those errors (The Add method is in uppercase, and you missed the parentheses when initializing the List)
The working code would be like this:
List<Player> players = new List<Player>();
while ((line = reader.ReadLine()) != null) {
string[] playerInfo = line.Split(';');
int ID = int.Parse(playerInfo[0]);
string firstName = playerInfo[1];
string lastName = playerInfo[2];
DateTime dob = DateTime.Parse(playerInfo[3]);
players.Add(new Player(id, firstName, lastName, dob);
}
If you want to have access to the list more globally you could do it this way:
Let's assume your class name is Sample:
public class Sample {
// Declare the list as a private field
private List<Player> players;
// Constructor - Creates the List instance
public Sample() {
players = new List<Player>();
}
private void openFileDialog_Click(object sender, EventArgs e) {
players.Clear(); //Clears the list
if (myOpenFileDialog.ShowDialog() == DialogResult.OK) ;
using (FileStream fStream = File.OpenRead(myOpenFileDialog.FileName)) {
StreamReader reader;
reader = new StreamReader(fStream);
string line;
while ((line = reader.ReadLine()) != null) {
string[] playerInfo = line.Split(';');
int ID = int.Parse(playerInfo[0]);
string firstName = playerInfo[1];
string lastName = playerInfo[2];
DateTime dob = DateTime.Parse(playerInfo[3]);
players.Add(new Player(id, firstName, lastName, dob);
}
}
}
}
Declaring the list this way you'll be able to get the values of the list from other methods inside the same class.

How to read the null string with Streamreader c#

I am reading the file which has data as below
123456788|TUUKKA|RASK|01/01/85|HOCKEY|123
123456786|TOM|BRADY|01/01/75|FOOTBALL|123
123456787|RAJON|RONDO|01/01/80|BASKETBALL|ABC
123456785|DUSTIN|PEDROIA|01/01/83|BASEBALL|
123456789|DAVID|ORTIZ|01/01/77|BASEBALL|123
and splitting it with the delimiter '|', but I am the stream reader is not reading the line 4 which contains a null at the end.How do I handle this?
This is my code for reading and splitting the text file line
string s = string.Empty;
using (System.IO.StreamReader File = new System.IO.StreamReader(Path))
{
File.ReadLine();//Removing the first line
while ((s = File.ReadLine()) != null)
{
string[] str = s.Split('|');
UpdateRecords.Athelete(str);
}
}
this is my UpdateRecords.Athelete(str) code:
public static void Athelete(string[] Records) {
tblAthlete athlete = new tblAthlete();
using (SportEntities sportEntities = new SportEntities()) {
var temp = Convert.ToInt32(Records[0]);
if (sportEntities.tblAthletes.FirstOrDefault(x => x.SSN == temp) == null) {
athlete.SSN = Convert.ToInt32(Records[0]);
athlete.First_Name = Records[1];
athlete.Last_Name=Records[2];
athlete.DOB = Convert.ToDateTime(Records[3]);
athlete.SportsCode = Records[4];
athlete.Agency_Code = Records[5];
sportEntities.tblAthletes.Add(athlete);
sportEntities.SaveChanges();
}
}
}
If we put:
athlete.Agency_Code = Records[5];
together with (from comments):
The column is an FK referenced to another table PK and it can accept null values.
the problem becomes clear. An empty string ("") is not a null; it is an empty string! It sounds like you simply want something like:
var agencyCode = Records[5];
athlete.Agency_Code = string.IsNullOrEmpty(agencyCode) ? null : agencyCode;

C# - Extracting satellite two line elements from a text file

I'm very new to c# and programming in general so I apologise if this doesn't make sense...
I need to be able to search a textbox or combobox to read a notepad file containing many satellite two line element codes.
The text file is set out like this:
0 VANGUARD 1
1 00005U 58002B 14242.42781498 .00000028 00000-0 24556-4 0 2568
2 00005 034.2497 271.4959 1848458 183.2227 175.4750 10.84383299975339
0 TRANSIT 2A
1 00045U 60007A 14245.43855606 .00000265 00000-0 95096-4 0 2208
2 00045 066.6958 193.0879 0251338 053.7315 060.2264 14.33038972819563
0 EXPLORER 11
1 00107U 61013A 14245.36883128 .00001088 00000-0 12832-3 0 1217
2 00107 028.7916 229.2883 0562255 219.9933 302.0575 14.05099145667434
Etc.
I need to search the box for the only satellite's name (the name after the 0 in the 'first' row) and extract that name into another textbox, and to use in my code. Additionally, I need to seperately extract the 2 lines of code directly beneath the name selected in the box (also to use in the code).
I have written code to use these two line elements, but I'm not able to automatically put them in my code.
Thank you
here is something that you can try quick and dirty that I have come up with.
1st place the file in a folder on your local hard drive.
2nd where I have filepath defined replace it with your actual file path and know how to use the # symbol and what it means in C#
3rd notice how I used the string .Replace Method.. you will have to tweak it I just gave you an Idea I am not going to write the entire code for you.. good luck.
static void Main(string[] args)
{
var fileName = string.Empty;
var filePath = #"C:\Users\myfolder\Documents\RGReports\"; //for testing purposes only
List<string> listNames = new List<string>();
string[] filePaths = Directory.GetFiles(#filePath);
foreach (string file in filePaths)
{
if (file.Contains(".txt"))
{
fileName = file;
using (StreamReader sr = File.OpenText(fileName))
{
//string s = String.Empty;
var tempFile = sr.ReadToEnd();
var splitFile = tempFile.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
foreach (string str in splitFile)
{
if (str.Length == 12)
{
listNames.Add(str.Substring(0, str.Length).Replace("0", "").Replace("1", "").Replace("2A",""));
}
Console.WriteLine(str);
}
}
}
}
}
Results will yield the following for names for example tested in a Console App
VANGUARD
TRANSIT
EXPLORER
You can use regular expressions for this task.
(I assume that the letters/numbers block after the name is also part of the name)
This code will do the following:
capture the name of the satellite and the two lines into a Satellite object
populate a ComboBox with the names of the satellite
whenever you selected a satellite you can know which one it was
a search box that searches for the first satellite beginning with the typed text
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
private readonly BindingList<Satellite> _satellites = new BindingList<Satellite>();
private string _input = #"
0 VANGUARD 1
1 00005U 58002B 14242.42781498 .00000028 00000-0 24556-4 0 2568
2 00005 034.2497 271.4959 1848458 183.2227 175.4750 10.84383299975339
0 TRANSIT 2A
1 00045U 60007A 14245.43855606 .00000265 00000-0 95096-4 0 2208
2 00045 066.6958 193.0879 0251338 053.7315 060.2264 14.33038972819563
0 EXPLORER 11
1 00107U 61013A 14245.36883128 .00001088 00000-0 12832-3 0 1217
2 00107 028.7916 229.2883 0562255 219.9933 302.0575 14.05099145667434
";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var regexObj =
new Regex(#"(?<=^\d+\s(?<name>[\w|\d|\s]+))\r\n(?<line1>(?<=^).*)\r\n(?<line2>(?<=^).*(?=\r))",
RegexOptions.Multiline);
Match matchResult = regexObj.Match(_input);
while (matchResult.Success)
{
string name = matchResult.Groups["name"].Value;
string line1 = matchResult.Groups["line1"].Value;
string line2 = matchResult.Groups["line2"].Value;
var regexObj1 = new Regex(#"(?<=^[1|2].*)([\d\w.-]+)");
Match matchResult1 = regexObj1.Match(line1);
var numbers1 = new List<string>();
while (matchResult1.Success)
{
string s = matchResult1.Value;
numbers1.Add(s);
matchResult1 = matchResult1.NextMatch();
}
var regexObj2 = new Regex(#"(?<=^[1|2].*)([\d\w.-]+)");
Match matchResult2 = regexObj2.Match(line2);
var numbers2 = new List<string>();
while (matchResult2.Success)
{
string s = matchResult2.Value;
numbers2.Add(s);
matchResult2 = matchResult2.NextMatch();
}
_satellites.Add(new Satellite
{
Name = name,
Line1 = line1,
Line2 = line2,
Numbers1 = numbers1,
Numbers2 = numbers2
});
matchResult = matchResult.NextMatch();
}
comboBox1.DataSource = _satellites;
comboBox1.DisplayMember = "Name";
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var comboBox = (ComboBox) sender;
var satellites = comboBox.DataSource as List<Satellite>;
if (satellites != null && comboBox.SelectedIndex > -1)
{
Satellite selectedSatellite = satellites[comboBox.SelectedIndex];
Console.WriteLine("Selected satellite: " + selectedSatellite.Name);
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
var textBox = (TextBox) sender;
string text = textBox.Text;
if (!string.IsNullOrWhiteSpace(text))
{
Satellite satellite =
_satellites.FirstOrDefault((s => s.Name.ToLower().StartsWith(text.ToLower())));
if (satellite != null)
{
Console.WriteLine("Found satellite: " + satellite);
}
}
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
var textBox = (TextBox) sender;
string text = textBox.Text;
if (!string.IsNullOrWhiteSpace(text))
{
Satellite satellite =
_satellites.FirstOrDefault(
s => s.Numbers1.Any(t => t.StartsWith(text)) || s.Numbers2.Any(t => t.StartsWith(text)));
if (satellite != null)
{
Console.WriteLine("Found satellite: " + satellite);
}
}
}
}
internal class Satellite
{
public string Name { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public List<string> Numbers1 { get; set; }
public List<string> Numbers2 { get; set; }
public override string ToString()
{
return string.Format("Name: {0}", Name);
}
}
}
Result:
If you don't want to use regex you could do something like this:
public List<string> GetSatelliteNames(string input)
{
string[] split = input.split(new string[2] { "\n", "\r\n" });
List<string> result = new List<string>();
foreach (var s in split)
{
string splitagain = s.split(new char[1] { ' ' });
if (s[0] == "0") result.add(s[1]);
}
return result;
}

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

Parsing data from a text file into an array

I have a flat text file that contains the following data;
Following are the names and ages in a text file.
26|Rachel
29|Chris
26|Nathan
The data is kept on a server (e.g http://domain.com/info.dat), I'd like to read this text file and insert it into an array (age and name). I'd like to ignore the first line (Following are....).
I've sorted the code to grab the data file using a webclient and the code to open the dat file using streamreader as follows;
using (StreamReader sr = new StreamReader(path))
{
while (sr.Peek() >= 0)
{
string[] channels = Text.Split('|');
foreach (string s in channels)
{
}
}
}
The problem with the above code is when it comes to inputting it into an array with the correct columns. Could anyone give me some pointers?
Many thanks
How about an answer that uses some LINQ:
var results = from str in File.ReadAllLines(path).Skip(1)
where !String.IsNullOrEmpty(str)
let data = str.Split('|')
where data.Length == 2
select new Person { Age = Int32.Parse(data[0], NumberStyles.Integer, CultureInfo.CurrentCulture), Name = data[1] };
results is now IEnumerable<Person> which you can do ToList or ToArray on to get a List<Person> or Person[], or you can simply use the results with a foreach loop.
UPDATE: here is the Person class needed to make this more functional.
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
}
You could do something like this. (There is no error checking, you might want to check for errors when parsing the age etc.
class Person
{
string Name {get;set;}
int Age {get;set;}
}
List<Person> people = new List<Person>();
string line;
using (StreamReader sr = new StreamReader(path))
{
sr.ReadLine();
while ((line == sr.ReadLine()) != null)
{
string[] channels = line.Split('|');
people.Add(new Person() {Age=int.Parse(channels[0]), Name=channels[1]});
}
}
You should use Dictionary and not Array to store the data.
Sample code:
FileStream fs = new FileStream("filename");
Dictionary<int,string> dict = new Dictionary<int,string>();
string line = "";
fs.ReadLine(); //skip the first line
while( (line = fs.ReadLine()) != null)
{
string parts = line.split("|".ToCharArray());
dict.Add(int.Parse(parts[0]), parts[1]);
}

Categories