Saving listbox items into a csv file - c#

I have a list box which contains student information, it has a studentID and a student mark, when I write to the file I want the studentID and studentMark to be in separate columns (for example the first students ID will be in A1 and their mark will be in B1. and so on until all the students have been written into the file)
I have this code, but this code only adds the studentinformation into the one column, how would I go about making it split the data and putting them in 2 columns
if(lstMarks.Items.Count > 0)
{
using(TextWriter outputfile = new StreamWriter("StudentRecords.csv"))
{
foreach(string data in lstMarks.Items)
{
outputfile.WriteLine(data);
}
MessageBox.Show("Student Information inserted successfully");
}
}

This will do what you need...
outputfile.WriteLine(string.Join(",", data.Split(':')));
What this does it firstly split the string data where it finds the colon, and this returns an array. The string.Join() then joins that array back together as a string, using a comma as a separator.
You could alternatively use data.Replace(":", ",").

You can create a string and WriteLine inside your foreach loop
You will have to split your string so you have studentId and studentMark in an array. Then you can build a string with comma separated.
Finally use flush to clear all buffers
using(TextWriter outputfile = new StreamWriter("StudentRecords.csv"))
{
foreach(string data in lstMarks.Items)
{
var dataArray = data.split(':');
var line = string.Format("{0},{1}", data[0] , data[1]);
outputfile.WriteLine(line);
outputfile.Flush();
}
MessageBox.Show("Student Information inserted successfully");
}

Related

How to get all rows for specific column from .csv file

In my project, I have a .csv file with many columns.
I need to extract all rows for only first column. I've managed to read all lines, but got stuck on how to extract rows from first column to another .csv file.
string filePath = #"C:\Users\BP185150\Desktop\OTC.csv";
string[] OTC_Output = File.ReadAllLines(#"C:\Users\BP185150\Desktop\OTC.csv");
foreach (string line in OTC_Output)
{
Console.WriteLine(line);
Console.Read();
}
Console.ReadLine();
Depending on what seperator your csv is using you can use the string.split() function.
e.g.
string firstItem = line.Split(',')[0];
Console.WriteLine(firstItem);
Adding them to a collection:
ICollection<string> firstItems = new List<string>();
string[] OTC_Output = File.ReadAllLines(#"C:\Users\BP185150\Desktop\OTC.csv");
foreach (string line in OTC_Output)
{
firstItems.Add(line.Split(',')[0]);
}
Well if you want to use File.ReadAllLines, the best way to get the first column is to split the line with a delimiter that your csv is using. Then just add the first item of every line to a collection.
var column = OTC_Output.Select(line => line.Split(';').First()).ToList();
In lineItems, you'll have all the columns splitted:
var lineItems = line.Split(";").ToArray();
Then, parse the value only for the first of them:
lineItems.GetValue(0).ToString();

Is it possible to get specific column data from a large pipe delimited file without creating a class for every column?

I am writing a C# program that will grab some data from a pipe delimited file with 400 columns in it. I'm only required to work with 6 of the columns in each row. The file does not have headers, and the first line is a 5 column row with general description of file (file name, batch date, number of records, total, report id). Before I create a class with 400 fields in it, I was curious if anyone here had a better idea of how to approach this. Thanks for your time.
Well, you don't mention much as to how you're loading the file, but I imagine it is using System.IO and then doing a string split on each line. If so, you need not extract every field in the resulting splitted array.
Imagine you only needed two columns, the second and fourth, and had a class to accept each row as follows:
public class row {
public string field2;
public string field4;
}
Then you would extract your data like this:
IEnumerable<row> parsed =
File.ReadLines(#"path to file")
.Skip(1)
.Select(line => {
var splitted = line.Split('|');
return new row {
field2 = splitted[1],
field4 = splitted[3]
};
});
You could use the Microsoft.VisualBasic.FileIO reference and then do something like this:
using(var parser = new TextFieldParsser(file))
{
Int32 skipHeader = 0;
parser.SetDelimiters("|");
while (!parser.EndOfData)
{
//Processing row
string[] fields = parser.ReadFields();
Int32 x = 0;
if (skipHeader > 0)
{
foreach (var field in fields)
{
if (x == 0)
{
//SAVE STUFF TO VARIABLE
}
else if (x==4)
{
//SAVE MORE STUFF
}
else if (x == 20)
{
//SAVE LAST STUFF
break;//THIS IS THE LAST COLUMN OF DATA NEEDED SO YOU BREAK
}
x++;
}
//DO SOMETHING WITH ALL THE SAVED STUFF AND CLEAR IT OUT
}
else
{
skipHeader++;
}
}}

Proof Reading .CSV per line

CSVHelper and FileHelper is not an option
I have a .csv export that I need to check for consistency structured like the below
Reference,Date,EntryID
ABC123,08/09/2015,123
ABD234,08/09/2015,124
XYZ987,07/09/2015,125
QWE456,08/09/2016,126
I can use ReadLine or RealAllLines and .Split which give me entire rows/columns BUT I have need to select each row and then go through each attribute (separated by ',') for format checking
I am running into problems here. I can not single out each value in a row for this check.
It is probably either something simple onto
class Program
{
static void Main(string[] args)
{
string csvFile = #"proof.csv";
string[] lines = File.ReadAllLines(csvFile);
var values = lines.Skip(1).Select(l => new { FirstRow = l.Split('\n').First(), Values = l.Split('\n').Select(v => int.Parse(v)) });
foreach (var value in values)
{
Console.WriteLine(string.Format("{0}", value.FirstRow));
}
}
}
Or I am going down the wrong path, my searches relate to pulling specific rows or columns (as opposed to checking the individual values associated)
The sample of the data above has a highlighted example: The date is next year and I would like to be able to proof that value (just an example as it could be in either column where errors appear)
I can not single out each value in a row
That's because you split on \n twice. The values within a row are separated by comma (,).
I'm not sure what all that LINQ is supposed to do, but it's as simple as this:
string[] lines = File.ReadAllLines(csvFile);
foreach (var line in lines.Skip(1))
{
var values = line.Split(',');
// access values[0], values[1] ...
}
Instead of reading it as text read it by OLEDB object, so data of CSV file will come in datatable and you do not need to spit it.
To Read the csv file you can use these objects of OLEDB
System.Data.OleDb.OleDbCommand
System.Data.OleDb.OleDbDataAdapter
System.Data.OleDb.OleDbConnection
and
System.Data.DataTable

Splitting a string by a string and inserting into a list C#

So I'm using C# and Visual Studio. I am reading a file of students and their information. The number of students is variable, but I want to grab their information. At the moment I just want to segment the student's information based off of the string "Student ID" because each student's section starts with Student ID. I'm using ReadAllText and setting it equal to a string and then feeding that string to my function splittingStrings. The file will look like this:
student ID 1
//bunch of info
student ID 2
//bunch of info
student ID 3
//bunch of info
.
.
.
I'm wanting to split each segment into a list since the number of students will be unknown, and the information for each student will vary. So I looked into both Regular string split and Regex string splitting. For regular strings I tried this.
public static List<string> StartParse = new List<string>();
public static void splittingStrings(string v)
{
string[] DiagDelimiters = new string[] {"Student ID "};
StartParse.Add(v.Split(DiagDelimiters, StringSplitOptions.None);
}
And this is what I tried with Regex:
StartParse.Add(Regex.Split("Student ID ");
I haven't used Lists before, but from what I've read they are dynamic and easy to use. My only trouble I'm getting is that all examples I see with split are in combination with an array so syntactically I'm not sure how to do a split on a string and insert it into a list. For output my goal is to have the student segments divided so that if I need to I can call a particular segment later.
Let me verify that I'm after that batch of information not the ID's alone. A lot of the questions seem to be focused on that so I felt I needed to verify that.
To those suggesting other storage bodies:
example of what list will hold:
position 0 will hold [<id> //bunch of info]
position 1 will hold [<anotherID> //bunch of info]
.
.
.
So I'm just using the List to do multiple operations on for information that I need. The information will be FAR more manageable if I can segment them into the list as shown above. I'm aware of dictionaries, but I have to store this information either in sql tables or inside text files depending on the contents of the segments. An example would be if one segment was really funky then I would send an error report that one student's information is bad. Otherwise insert neccessary information into sql table. But I'm having to work with multiple things from the segments so I felt the List was the best way to go since I'll have to also go back and forth in the segment to cross check bits of information with earlier things in that segment I found.
There is no need to use RegEx here and I would recommend against it. Simply splitting on white space will do the trick. Lets pretend you have a list which contains each of those lines (student ID 1, student ID 2, ect) you can get a list of the id's very simply like so;
List<string> ids = students.Select(x => x.Split(' ')[2]).ToList();
The statement above essentially says, for each string in students split the string and return the third token (index 2 because it's 0 indexed). I then call ToList because Select by default returns an IEnumerable<T> but I wouldn't worry about those details just yet. If you don't have a list with each of the lines you showed the idea stays much the same, only you would add the items to you ids list one by one as you split the string. For an given string in the form of student id x I would get x on it's own with myString.Split(' ')[2] that is the basis of the expression I pass into Select.
Based on the OP's comment here is a way to get all of the data without the Student Id part of each batch.
string[] batches = input.Split(new string[] { "student id " } StringSplitOptions.RemoveEmptyEntries);
If you really need a list then you can just call ToList() and change type of batches to List<string> but that would probably just be a waste of CPU cycles.
Here's some pseudo-code, and what i'd do:
List<Integer> ids;
void ParseStudentId(string str) {
var spl = str.split(" ");
ids.add(Integer.parseInt(spl[spl.length-1])); // this will fetch "1" from "Student Id 1"
}
void main() {
ParseStudentId("Student Id 1");
ParseStudentId("Student Id 2");
ParseStudentId("Student Id 3");
foreach ( int id in ids )
Console.WriteLin(id); // will result in:
// 1
// 2
// 3
}
forgive me. i'm a java programmer, so i'm mixing Pascal with camel casing :)
Try this one:
StartParse = new List<string>(Regex.Split(v, #"(?<!^)(?=student ID \d+)"));
(?<!^)(?=student ID \d+) which means Splitting the string at the point student ID but its not at the beginning of the string.
Check this code
public List<string> GetStudents(string filename)
{
List<string> students = new List<string>();
StringBuilder builder = new StringBuilder();
using (StreamReader reader = new StreamReader(filename)){
string line = "";
while (!reader.EndOfStream)
{
line = reader.ReadLine();
if (line.StartsWith("student ID") && builder.Length > 0)
{
students.Add(builder.ToString());
builder.Clear();
builder.Append(line);
continue;
}
builder.Append(line);
}
if (builder.Length > 0)
students.Add(builder.ToString());
}
return students;
}

Comparing string to text file

I am currently working on a code where I add a student to a text file of students and make other calculations. The problem I'm having is I have to sort the new student into the text file so he is in the correct place.
StreamWriter changeFile = new StreamWriter("Students.txt", true);
if (pos > 0)
{
changeFile.Close();
}
else
{
changeFile.WriteLine(newStudent);
changeFile.Close();
}
using (StreamReader streamReader = new StreamReader("Students.txt"))
{
string text = streamReader.ReadToEnd();
}
So far I have managed to change the text file into a string to compare the 2, but it is in the wrong place. What code would I use to make the StreamWriter compare the newStudent string to the text file so it can put it in the correct order?
P.S. The text file has over 10,000 students in it.
These are the first 5 lines of the text file:
students (LIST
(LIST (LIST 'Abbott 'A_____ 'J ) 'NONE 'xxxxx#mail.usi.edu 2.3073320999676614 )
(LIST (LIST 'Abbott 'B_____ 'Y ) 'NONE 'xxxxx#mail.usi.edu 3.1915725161177115 )
(LIST (LIST 'Abbott 'R_____ 'Y ) 'NONE 'xxxxx#mail.usi.edu 3.448215586562192 )
(LIST (LIST 'Abel 'H_____ 'Y ) 'NONE 'xxxxx#mail.usi.edu 3.2517764202656974 )
) ) <- this is at the end
Simple method is:
Split the string at the line breaks
Create a List containing the source lines
Add the new student to the list
Sort the list
Write the list to the file
Alternately:
Split the string at the line breaks
Create a List containing the source lines
Write lines back to the file util you find the position for the new record
Write the new record
Write the rest of the records.
Or, even better for large files:
Read the source file line-by-line
Write lines to a temporary destination file
When you find the correct place to insert the new record, write it to the dest file.
Continue copying lines from source to destination
Delete the source file and rename the destination file to take its place.
something like
var Students = File.ReadAllText("Students.txt").Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList().Union(new string[] { newStudent }).ToList().Sort();
File.WriteAllLines("Students.txt", Students);
might work for you
Assuming the text file contains one student per line, you could read the text file into a list of strings, then add the new student then sort it and write it back to the file.
var allStudents = new List<string>(File.ReadAllLines("Students.txt"));
allStudents.Add(newStudent);
allStudents.Sort(allStudents);
File.WriteLines("Students.txt", allStudents);
This is inefficient because every time it reads and writes the whole file. If you have a choice, consider using a database like others have suggested.
EDIT:
Since the first line of your file is not a student, you should remove it before sorting and re-add it later.
You can remove that line like this:
var line = allStudents[0];
allStudents.RemoveAt(0);
And re-add it like this:
allStudents.Insert(0, line);

Categories

Resources