How to read a .CSV file into an array of a class (C#) - c#

I am trying to pull 3 values from a .csv file into an array of class called PizzaOrder. The .csv file was created using the same program. I am having problems figuring out how to insert the values from the .csv into the array of PizzaOrder.
Here is the code of the form so far:
public partial class Form1 : Form
{
PizzaOrder[] pizzaArray = new PizzaOrder[4];
PizzaOrder[] ReadPizzaArray = new PizzaOrder[4];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//this is just creating the values and inserting into the array
PizzaOrder p1 = new PizzaOrder(12, "Pepperoni", 14.88m);
PizzaOrder p2 = new PizzaOrder(15, "Mushrooms", 15.69m);
PizzaOrder p3 = new PizzaOrder(13, "Bacon", 15.33m);
PizzaOrder p4 = new PizzaOrder(16, "Olives", 17.47m);
pizzaArray[0] = p1;
pizzaArray[1] = p2;
pizzaArray[2] = p3;
pizzaArray[3] = p4;
}
private void btnDisplay_Click(object sender, EventArgs e)
{
//this is just displaying the contents of the array in a listbox
lstOrders.Items.Clear();
for(int loop = 0; loop < pizzaArray.Length; loop++)
{
lstOrders.Items.Add(pizzaArray[loop].ShowOrder());
}
}
private void btnSave_Click(object sender, EventArgs e)
{
//this is where the .csv file is being created and saved to
StreamWriter SavePizza = new StreamWriter("PizzaFile.csv", true);
try
{
for (int loop = 0; loop < pizzaArray.Length; loop++)
{
SavePizza.Write(pizzaArray[loop].ShowOrder()+ Environment.NewLine);
}
}
catch(System.Exception)
{
MessageBox.Show("A file write error has occured...", "File Error");
}
finally
{
SavePizza.Close();
}
}
private void button1_Click(object sender, EventArgs e)
{
//this is where I am attempting to read from the .csv
StreamReader ReadPizza = new StreamReader(File.OpenRead("PizzaFile.csv"));
try
{
string input = ReadPizza.ReadToEnd();
string[] PizzaRead = input.Split(',');
for (int loop2 = 0; loop2 < ReadPizzaArray.Length; loop2++)
{
//this is where I'm trying to insert from the .csv into the array again, where the problem is
ReadPizzaArray[loop2] = (PizzaRead[0], PizzaRead[1], PizzaRead[2]);
}
}
catch(System.Exception)
{
MessageBox.Show("An error occured during the file read...","File Read Error");
}
finally
{
ReadPizza.Close();
}
}
}
The PizzaOrder class accepts an int, sting, and decimal in that order.
The information from the .csv needs to be added as such.
Any information and/guidance would be most appreciated! Thanks!

You will want to create a new PizzaOrder object to do this. Along with that, you will need to convert to the proper data types. Here is example code:
for (int loop2 = 0; loop2 < ReadPizzaArray.Length; loop2++)
{
ReadPizzaArray[loop2] = new PizzaOrder(Convert.ToInt32(PizzaRead[0]), PizzaRead[1].ToString(), Convert.ToDecimal(PizzaRead[3]));
}
Along with this, you should take a look at some coding standards. local variables are usually not capitalized. A List would likely work better than an array, as you don't know how many entries there will be for different CSV files.

In addition to oppassum's answer, it seems like you didn't split your csv by lines before splitting each line by commas.
string input = ReadPizza.ReadToEnd();
string[] lines = input.Split(new[] { Environment.NewLine}, StringSplitOptions.RemoveEmptryEntries);
foreach (string line in lines)
{
string[] PizzaRead = line.Split(',');
//Insert oppassum's answer here...
}

Read the file with File.ReadAllLines(), and use String.Split() and String.Trim():
var lines = File.ReadAllLines("PizzaFile.csv")
List<PizzaOrder> orders = new List<PizzaOrder>();
foreach (var line in lines)
{
var fields = line.Split(',');
PizzaOrder order = new PizzaOrder()
{
Id = Convert.ToInt32(fields[0].Trim());
Type = fields[1].Trim();
// etc.
}
}
var result = orders.ToArray();

Related

Windows Form c# Reading and Writing to the same File on the same form Error?

I am currently trying to complete this c# windows form application. I am running into trouble.
Here is an image of my form...
The point of this form is too allow a user to input the data above. On the back end it should find the lowest test score, remove it from an array, and then when the user clicks "save student", the 3 lines of data ( The "Student Name", avg of 5 Test, and Letter grade based on the average ), should be saved to the students.txt file.
HOWEVER, my issue is can be seen in the list box below. My issue is that I am loading the data from the "students.txt" file ( using pre filled dummy data ), and I am getting an error each time I try to save the student ( because I cant read and write to the same file ) and the program will stop running.
Clicking on any of the pre filled data brings up another form with the data loaded into labels and that works just fine...
How can I stop this error so I can proceed with my work? I also am having trouble understanding the instructions where the data should be in a 2d array.
Here is an image of the instructions before I move on with my code. I am sure I can diverge from the instructions a bit.
Here is the code for my main Form...
namespace Tes3Part2
{
public partial class Form1 : Form
{
private List<PersonEntry> contactList = new List<PersonEntry>();
private List<string> contactListNames = new List<string>();
private InfromationForm personInfo = new InfromationForm();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
StreamReader inputFile = File.OpenText("students.txt");
while (!inputFile.EndOfStream)
{
PersonEntry person = new PersonEntry();
person.Name = inputFile.ReadLine();
person.AverageScore = inputFile.ReadLine();
person.LetterGrade = inputFile.ReadLine();
contactList.Add(person);
contactListNames.Add(person.Name);
}
contactListNames.Sort();
int x = 0;
while (x < contactListNames.Count)
{
contactList.Insert(x, contactList[SequentialSearch(contactList, contactListNames[x])]);
studentsListBox.Items.Add(contactList[x].Name);
x++;
}
}
catch
{
MessageBox.Show("Welcome.");
}
}
private int SequentialSearch(List<PersonEntry> inputList, string value)
{
bool found = false;
int index = 0;
int position = -1;
while (!found && index < inputList.Count)
{
if (inputList[index].Name == value)
{
found = true;
position = index;
}
index++;
}
return position;
}
private void StudentsListBox_SelectedIndexChanged(object sender, EventArgs e)
{
personInfo.nameLabel.Text = contactList[studentsListBox.SelectedIndex].Name;
personInfo.scoreLabel.Text = contactList[studentsListBox.SelectedIndex].AverageScore;
personInfo.letterLabel.Text = contactList[studentsListBox.SelectedIndex].LetterGrade;
personInfo.ShowDialog();
}
private void Button1_Click(object sender, EventArgs e)
{
double test1 = (double.Parse(t1TestBox.Text));
double test2 = (double.Parse(t1TestBox.Text));
double test3 = (double.Parse(t1TestBox.Text));
double test4 = (double.Parse(t1TestBox.Text));
double test5 = (double.Parse(t1TestBox.Text));
double average = (test1 * test2 * test3 * test4 * test5) / 5;
// Declare a StreamWriter variable.
StreamWriter outputFile;
// Create a file and get a StreamWriter object.
outputFile = File.CreateText("students.txt");
// Write the info to the file.
outputFile.WriteLine(nameTextBox.Text);
outputFile.WriteLine(average);
outputFile.WriteLine("F");
outputFile.Close();
// Let the user know the name was written.
MessageBox.Show("The employee's name was added to the file EmployeePayroll.txt, located" +
"in the Debug File");
}
private void ExitButton_Click(object sender, EventArgs e)
{
this.Close();
}
}
Here is the code for my Person Class
class PersonEntry
{
private string _name;
private string _average;
private string _letterGrade;
public PersonEntry()
{
_name = "";
_average = "";
_letterGrade = "";
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public string AverageScore
{
get { return _average; }
set { _average = value; }
}
public string LetterGrade
{
get { return _letterGrade; }
set { _letterGrade = value; }
}
}
Thank you in advance for all of your help!
As Steve mentioned you make use of the using statement while reading and writing to the file.
using (StreamReader inputFile = File.OpenText("students.txt"))
{
while (!inputFile.EndOfStream)
{
PersonEntry person = new PersonEntry();
person.Name = inputFile.ReadLine();
person.AverageScore = inputFile.ReadLine();
person.LetterGrade = inputFile.ReadLine();
}
}
using (StreamWriter outputFile = File.CreateText("students.txt"))
{
// Write the info to the file.
outputFile.WriteLine(nameTextBox.Text);
outputFile.WriteLine(average);
outputFile.WriteLine("F");
outputFile.Close();
}

how to capture real time stream data in csv or .data file in a windows form Application

I implemented a function in a windows form application to capture and read needed tabular data from a file (sourcedata.data) and save it in another file (result.data ).
How i and by using the application can capture a real time stream data like such available here :https://data.sparkfun.com/streams in csv or .data file to use it.
Or are there any direct waya to read the stream data directly from the website source periodically ?
private void button5_Click(object sender, EventArgs e)
{
List<string[]> rows = new List<string[]>();
int[] indexes = { 0, 1, 3, 5, 6, 7, 8, 9 };
using (var reader = new StreamReader(#"sourcedata.data"))
{
using (StreamWriter writetext = new StreamWriter("result.data"))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (line.IndexOf(',') == -1)
continue;
string[] values = line.Split(',');
string[] row = new string[indexes.Length];
int insertIndex = 0;
for (int i = 0; i < values.Length; i++)
{
string val = values[i];
if (val.Trim() == "?")
goto BREAK;
if (indexes.Contains(i))
row[insertIndex++] = val;
}
rows.Add(row);
writetext.WriteLine(String.Join(",", row));
BREAK:;
}
}
}
}
You have two split your problem into two separated sub problems:
Write a method public static string DownloadData(...) which will download the data from the source. This can be done by any HTTP client or library you can find like System.Net.Http.HttpClient or System.Net.WebClient.
See How to download a file from a URL in C#?
Add/start a timer which calls this method periodically. You can use classes like System.Windows.Forms.Timer or System.Timers.Timer.
See What is the best way to implement a "timer"?
#Progman
It is the code
public partial class Download : Form
{
public Download()
{
InitializeComponent();
}
WebClient client;
private void btnDownload_Click(object sender, EventArgs e)
{
string url = txtUrl.Text;
if (!string.IsNullOrEmpty(url))
{
Thread thread = new Thread(() =>
{
Uri uri = new Uri(url);
string filename = System.IO.Path.GetFileName(uri.AbsolutePath);
client.DownloadFileAsync(uri, Application.StartupPath + "/" + filename);
});
thread.Start();
}
}
private void Download_Load(object sender, EventArgs e)
{
client = new WebClient();
client.DownloadProgressChanged += Client_DownloadProgressChanged;
client.DownloadFileCompleted += Client_DownloadFileCompleted;
}
private void Client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("Download Completed.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void Client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
Invoke(new MethodInvoker(delegate ()
{
progressBar.Minimum = 0;
double recieve = double.Parse(e.BytesReceived.ToString());
double total = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = recieve / total * 100;
lblStatus.Text = $"Download {string.Format("{0:0.##}", percentage)}%";
progressBar.Value = int.Parse(Math.Truncate(percentage).ToString());
}));
}
}

Why won't my AT Command read SMS messages?

I'm attempting to write a program which would enable texts to be sent out to customers, I'm using AT Commands with a GSM modem to accomplish this, I have looked at various bits of Documentation but have been unable to find a solution for the following problem.
I am attempting to make the GSM modem return all of the text messages contained within its memory, I have tried many combinations of AT Commands and Parsing techniques to throw this into a text box, but to no avail.
Any help on this would be most appreciated, my code is below
private SerialPort _serialPort2 = new SerialPort("COM3", 115200);
private void MailBox_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
_serialPort2.Open();
//_serialPort2.Write("AT+CMGF=1 \r");
_serialPort2.Write("AT+CMGL=\"ALL\"");
string SerialData = _serialPort2.ReadExisting();
var getnumbers = new string((from s in SerialData where char.IsDigit(s) select s).ToArray());
var getText = SerialData;
SendTxt.Text = getnumbers;
SendMsgBox.Text = getText;
//for (int i = 0; i < SerialData.Length; i++ )
//{
// if (char.IsDigit(SerialData))
//}
//.Text = _serialPort2.ReadExisting();
//string[] text = { textBox1.Text };
//IEnumerable<string> formattext = from words in text where words.("+447") select words;
// foreach (var word in formattext)
//{
//SenderBox.Items.Add(word.ToString());
// }
_serialPort2.Close();
//_serialPort2.DataReceived += new SerialDataReceivedEventHandler(_serialPort2_DataReceived);
}

C#. Using all files in a folder, and writing a different string in a specific line

I need your help.
The thing is that my code works, it reads all the files in a folder which are 96 text files and saves the path of each file.
I then take each file and change the line number 32 in the text file which is
"Treatment";"1"; nr = 1,2,3,4,5,...,96.
My program will takes this string and replaces it with a different one, I change the first file for example to "Treatment";"100"; then the last file should be "Treatment";"196";
So to solve this i change the whole line with a new one. But when i write the number to the string first file is right when i start from 1, but files 2-10 are. 12,23,34,45,56,67,78,89, then it starts 2,3,4,5,6,7 from the 11-th file.
Why is this? My code is below.
I tried saving the integer as a string because I though i was somehow accesing a ASCII table. But that works the same, so my code is below any ideas?
private void button1_Click(object sender, EventArgs e)
{
DialogResult result = folderBrowserDialog1.ShowDialog();
if (result == DialogResult.OK)
{
int start = 1;
string strengur = "\";";
string myString = start.ToString();
string[] filePaths = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
//foreach (var file in Directory.EnumerateFiles(folderBrowserDialog1.SelectedPath))
for(int i = 0; i < 96 ; i++){
var lines = File.ReadAllLines(filePaths[i]);
lines[31] = "\"Treatment!!\";\"" +myString +strengur;
File.WriteAllLines(filePaths[i], lines);
start += 1;
myString = start.ToString();
}
}
}
Best Regards
Sæþór Ólafur Pétursson
Display all these files in windows explorer, sort by name, and then you will see why.
To solve it, you can set your start based on each file's line31's current number, and add by 100. E.g.:
private void button1_Click(object sender, EventArgs e)
{
DialogResult result = folderBrowserDialog1.ShowDialog();
if (result == DialogResult.OK)
{
string strengur = "\";";
string[] filePaths = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
foreach(var file in filePaths)
{
var lines = File.ReadAllLines(file);
int currentstart = int.Parse(lines[31].Split(';')[1].Trim('\"'));
lines[31] = "\"Treatment!!\";\"" + (currentstart+100).ToString() + strengur;
File.WriteAllLines(file, lines);
}
}
}
Edit based on your comment:
private void button1_Click(object sender, EventArgs e)
{
DialogResult result = folderBrowserDialog1.ShowDialog();
if (result == DialogResult.OK)
{
int start = 100; //set this to your user's input
string strengur = "\";";
string[] filePaths = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
foreach(var file in filePaths)
{
var lines = File.ReadAllLines(file);
int currentstart = int.Parse(lines[31].Split(';')[1].Trim('\"'));
lines[31] = "\"Treatment!!\";\"" + (currentstart+start-1).ToString() + strengur;
File.WriteAllLines(file, lines);
}
}
}

Validation Check for repeated data in database

I encountered a problem that whenever the user create a new record, the program must check whether the data were already created a not. My codes currently have some errors that I couldn't find what does the error lies. Can anyone give me some opinion?? Thanks!
Below were to codes to let you guys have more understanding about my problem.
private void btnCreate_Click(object sender, EventArgs e)
{
using (satsEntities Setupctx = new satsEntities())
{
//int[] stations = StationNameList();
//int[] locations = LocationNameList();
locationstation ls = new locationstation();
ls.stationID = Convert.ToInt32(cbStation.SelectedValue);
ls.locationID = Convert.ToInt32(cbLocation.SelectedValue);
var checkLS = from CLS in Setupctx.locationstations
where CLS.stationID == Convert.ToInt32(cbStation.SelectedValue)
where CLS.locationID == Convert.ToInt32(cbLocation.SelectedValue)
select CLS;
if (checkLS = checked)
{
MessageBox.Show("This Location Station Has Been Created. Please enter a new Location Station.");
}
else
{
{
Setupctx.locationstations.AddObject(ls);
Setupctx.SaveChanges();
cbStation.SelectedIndex = -1;
cbLocation.SelectedIndex = -1;
MessageBox.Show("New Location Station Is Created");
}
}
}
}
The columns that needs to be compared were saved in an array
private int[] LocationNameList()
{
using (satsEntities Setupctx = new satsEntities())
{
return Setupctx.locationstations.Select(x => x.locationID).OrderBy(x => x).ToArray();
}
}
private int[] StationNameList()
{
using (satsEntities Setupctx = new satsEntities())
{
return Setupctx.locationstations.Select(y => y.stationID).OrderBy(y => y).ToArray();
}
}
Any help will be greatly appreciated.
A crude way would be to create a unique index on those two columns, and attempt save in a try/catch block.
This answer is working for me as I figured it out myself.
private void btnCreate_Click(object sender, EventArgs e)
{
using (satsEntities Setupctx = new satsEntities())
{
locationstation ls = new locationstation();
int Stations = Convert.ToInt32(cbLocation.SelectedValue);
int Locations = Convert.ToInt32(cbStation.SelectedValue);
ls.stationID = Convert.ToInt32(cbStation.SelectedValue);
ls.locationID = Convert.ToInt32(cbLocation.SelectedValue);
var AuthCheck = from Ls in Setupctx.locationstations
where (Ls.locationID == Stations && Ls.stationID == Locations)
select Ls;
if (AuthCheck.Count() != 0)
{
MessageBox.Show("This Location Station Has Been Created. Please enter a new Location Station.");
}
else
{
Setupctx.locationstations.AddObject(ls);
Setupctx.SaveChanges();
cbStation.SelectedIndex = -1;
cbLocation.SelectedIndex = -1;
MessageBox.Show("New Location Station Is Created");
}
}
}

Categories

Resources