Parsing data from a text file into an array - c#

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]);
}

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;

Creating specific list of Items for each file in a Directory using C#

I am trying to create a List for every file available in a directory. Each file must have a separate list of items. I have created a list, but it shows all items available in all files. How to do it? Need help in this regard.
I am doing it like this, but it shows all Items "Product" in all files:
a piece of code is here:
List products = new List();
foreach (string file in fileList)
{
using (StreamReader sr = new StreamReader(file))
{
string line;
while ((line = sr.ReadLine()) != null)
{
rows++;
if (line.StartsWith("Product"))
{
var val = line.Split(',');
upc = val[1];
pName = val[3];
products.Add(upc);
products.Add(pName);
productList = string.Join(",", products.ToArray());
Add these clases
public class ProductFile
{
public string Name;
public List<Product> Products = new List<Product>();
}
public class Product
{
public string Upc;
public string PName;
}
And then, in your code:
var productFiles = new List<ProductFile>();
foreach (string file in fileList)
{
var productFile = new ProductFile(){ Name = Path.GetFileName(file) };
using (StreamReader sr = new StreamReader(file))
{
string line;
while ((line = sr.ReadLine()) != null)
{
rows++;
if (line.StartsWith("Product"))
{
var val = line.Split(',');
var product = new Product()
{
Upc = val[1],
PName = val[3]
};
productFile.Products.Add(product); //Adds a product
}
}
};
productFiles.Add(productFile); //Adds a file
}

Console App...Objects of a Class

I have created 2 classes. One class has instance variables, default constructor, constructor with parameters, properties and one function/method. the second class, contains my main method and is required to read data from a txt. file and then save the data to the 3 different objects.
I created 3 objects that look like this
NewEmployee employee1 = new NewEmployee();
this is what my code looks like to read the text file
using (StreamReader stream = new StreamReader(#"C:\Users/path))
{
while((line = stream.ReadLine()) != null)
{
Console.WriteLine(line);
}
How do I save the data from the text file to each object?
This is what the text file looks like:
First Name
Last Name
IdNUm
Start Year
Initial Salary
repeats 2x
I think this is what the OP wants:
List<Employee> employees = new List<Employee>();
using (StreamReader sr = new StreamReader("filepath"))
{
string line;
while ((line = sr.ReadLine()) != null)
{
string[] split = line.Split(" ".ToCharArray());
employees.Add(new Employee
{
FirstName = split[0],
LastName = split[1],
EmployeedID = Int32.Parse(split[2]),
StartYear = Int32.Parse(split[3]),
InitialSalary = Decimal.Parse(split[4])
});
}
}
This assumes the lines are delimited by space and that the values will cast into the proper types. You can add the error handling but this will get you started.

Pull separate columns from .csv into separate arrays in c#

Background on this project. It started as a simple homework assignment that required me to store 5 zip codes and their corresponding cities. When a user puts a Zip code in a textbox, a corresponding city is returned, and likewise the opposite can be done. I wrote the code to return these values, but then I decided I wanted to store ALL zip codes and their corresponding Cities in an external .csv, and store those values in arrays and run the code off that because if its worth doing, its worth overdoing! To clarify, this is no longer for homework, just to learn more about using external files in C#.
In the following code, I have called to open the file successfully, now I just need help in figuring out how to pull the data that is stored in two separate columns (one for city, one for zip code) and store them in two arrays to be acted upon by the for loop. Here is the code I have now. You can see how I have previously stored the other values in arrays and pulled them out:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnConvert2City_Click(object sender, EventArgs e)
{
try
{
string dir = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().Location);
string path = dir + #"\zip_code_database_edited.csv";
var open = new StreamReader(File.OpenRead(path));
int EnteredZipcode = Convert.ToInt32(txtZipcode.Text.Trim());
string result = "No Cities Found";
string[] Cities = new String[5] { "FLINTSTONE", "JAMAICA", "SCHENECTADY", "COTTONDALE", "CINCINNATI" };
int[] Zipcode = new int[5] { 30725, 11432, 12345, 35453, 45263 };
for (int i = 0; i <= Zipcode.Length - 1; i++)
{
if (Zipcode[i] == EnteredZipcode)
{
result = Cities[i];
break;
}
}
string DisplayState = result;
txtCity.Text = DisplayState;
}
catch (FormatException)
{
MessageBox.Show("Input must be numeric value.");
}
catch (OverflowException)
{
MessageBox.Show("Zipcode to long. Please Re-enter");
}
}
private void btnConvert2Zipcode_Click(object sender, EventArgs e)
{
string dir = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().Location);
string path = dir + #"\zip_code_database_edited.csv";
var open = new StreamReader(File.OpenRead(path));
String EnteredCity = txtCity.Text.ToUpper();
string result = "No Zipcode Found";
string[] Cities = new String[5] { "FLINTSTONE", "JAMAICA", "SCHENECTADY", "COTTONDALE", "CINCINNATI" };
int[] Zipcode = new int[5] { 30725, 11432, 12345, 35453, 45263 };
for (int i = 0; i <= Cities.Length - 1; i++)
{
if (Cities[i] == EnteredCity)
{
result = Convert.ToString(Zipcode[i]);
break;
}
}
string DisplayZip = result;
txtZipcode.Text = DisplayZip;
}
}
The following data is a snippet of what the data in my excel .csv looks like:
zip,primary_city
44273,Seville
44274,Sharon Center
44275,Spencer
44276,Sterling
44278,Tallmadge
44280,Valley City
44281,Wadsworth
44282,Wadsworth
44285,Wayland
And so on for about 46,000 rows.
How can I pull the zip and the primary_city into two separate arrays (I'm guessing with some ".Split "," "line) that my for-loop can operate on?
Also, if there are better ways to go about this, please let me know (but be sure to leave an explanation as I want to understand where you are coming from).
Don't create two separate array.Create a separate class for city
class City
{
public string Name{get;set;}
public int ZipCode{get;set;}
}
Now to read the data from that csv file
List<City> cities=File.ReadAllLines(path)
.Select(x=>new City
{
ZipCode=int.Parse(x.Split(',')[0]),
Name=x.Split(',')[1]
}).ToList<City>();
Or you can do this
List<City> cities=new List<City>();
foreach(String s in File.ReadAllLines(path))
{
City temp=new City();
temp.ZipCode=int.Parse(s.Split(',')[0]);
temp.Name=s.Split(',')[1];
cities.Add(temp);
}
You can try this:
string dir = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().Location);
string path = dir + #"\zip_code_database_edited.csv";
var open = new StreamReader(File.OpenRead(path));
var cities = new HashList<string>();
var zipCodes = new HashList<int>();
var zipAndCity = new string[2];
string line = string.Empty;
using (open)
{
while ((line = reader.ReadLine()) != null)
{
zipAndCity = line.Split(",");
zipCodes.Add(int.Parse(zipAndCity[0]));
cities.Add(zipAndCity[1]);
}
}
I am posting this answer having learned much more about C# since I posted this question. When reading a CSV, there are better options than String.Split().
The .NET Framework already has a built-in dedicated CSV parser called TextFieldParser.
It's located in the Microsoft.VisualBasic.FileIO namespace.
Not only are there many edge cases that String.Split() is not properly equipped to handle, but it's also much slower to use StreamReader.

Categories