Reading, splitting and displaying a multi-line CSV file in C #

Everything,

I am trying to write a test program that will eventually allow me to take the CSV.txt file and put its contents into the SQLite database file. There are hundreds of lines in TXT files that I work with.

Here's what I still have: a WPF form with three buttons -

Output: self-evident

Download CSV file: The "Open Win32 file" dialog box opens.

Current directory information: finds the current directory from which the program runs and displays it.

and a text block that displays various information from the program output - basically, regardless of what I want, things like exceptions, etc.

To read a text file, I implement the following code:

using System; using System.Data; using System.Data.SQLite; using System.IO; using System.Windows; using System.Windows.Controls; namespace C_Sharp_SQLite_Testbed { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private static string fileName; public MainWindow() { InitializeComponent(); } private void btnLoad_Click(object sender, RoutedEventArgs e) { Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); dlg.FileName = "Document"; dlg.DefaultExt = ".txt"; dlg.Filter = "Text Documents (.txt)|*.txt"; Nullable<bool> result = dlg.ShowDialog(); if (result == true) { fileName = dlg.FileName; OutputConsole.Text = " "; OutputConsole.Text = fileName; try { using (StreamReader sr = new StreamReader(fileName)) { while (!sr.EndOfStream) { var line = sr.ReadLine(); var lineWords = line.Split(','); OutputConsole.Text = Convert.ToString(lineWords.Length); } } } catch (Exception ex) { OutputConsole.Text = " "; OutputConsole.Text = ex.Message; } } } private void btnExit_Click(object sender, RoutedEventArgs e) { Environment.Exit(0); } private void btnInfo_Click(object sender, RoutedEventArgs e) { Environment.CurrentDirectory = Environment.GetEnvironmentVariable("windir"); DirectoryInfo info = new DirectoryInfo("."); lock (info) { OutputConsole.Text = String.Format("Directory info: " + info.FullName); } } } } 

This is a fairly simple setup, and the only method I'm having problems with is btnLoad_Click . The StreamReader method receives the StreamReader variable from the dialog box as an argument. It successfully opens the file. Until at the end of the file stream, the line is read using var line = sr.ReadLine(); . Then we split the string into an array with var lineWords = line.Split(','); . After that, the length of the linesWords array is printed in the text block using OutputConsole.Text = Convert.ToString(lienWords.Length); . The problem is this: it would seem that only one value is read from the file, the reader stops at the first comma, and then stops reading. The printable value of the array is 1, and when you change OutputConsole.Text = Convert.ToString(lineWords.Length) to OutputConsole.Text = Convert.ToString(lineWords[1]); only one value is printed. Also, this is not the correct value. So basically, I only have one place in the array, and it is not filled with the correct value.

What do you propose to change? Reading files in C # has never been my strongest.

EDIT: here are the first two lines as a sampler of what is in the file. This is the output of Kinect.

Time,HLState,HLX,HLY,HLZ,KLState,KLX,KLY,KLZ,ALState,ALX,ALY,ALZ,FLState,FLX,FLY,FLZ,HRState,HRX,HRY,HRZ,KRState,KRX,KRY,KRZ,ARState,ARX,ARY,ARZ,FRState,FRX,FRY,FRZ,lknfx,lknvg,rknfx,rknvg

These are just the headlines.

Second line: 700449555,2,-0.2912986,-0.1036692,1.472573,2,-0.2512482,-0.472762,1.416523,1,-0.2034467,-0.9132867,1.340637,1,-0.1271965,-0.9447169,1.280763,2,-0.197726,-0.09682589,1.596856,2,-0.1457276,-0.5412285,1.782268,2,-0.184881,-0.5280698,1.408923,2,-0.1630141,-0.537811,1.523656,178.867138094441,12.3859203137083,64.9231529324685,142.847159325228

I believe the encoding is ANSI.


EDIT:

Here is the "new" block for reading lines. It still works well, now you need to split things into a 2D array.

 try { using (StreamReader sr = new StreamReader(fileName)) { lines = File.ReadAllLines(fileName); } int numberLines = lines.Length; OutputConsole.Text = " "; OutputConsole.Text += numberLines + " "; for (int i = 0; i < numberLines; i++) { OutputConsole.Text += lines[i] + "\n"; } } 
+4
source share
2 answers

Here's how I do it:

First, define a class to hold the output of your file:

 public class MyData { public MyData() { } public MyData(string[] values) { Time = new DateTime(long.Parse(values[0])); HlState = int.Parse(values[1]); HLX = double.Parse(values[2]); HLY = double.Parse(values[3]); HLZ = double.Parse(values[4]); } public DateTime Time { get; set; } public int HLState { get; set; } public double HLX { get; set; } public double HLY { get; set; } public double HLZ { get; set; } } 

Then change the button event to populate the list of these objects.

  private void btnLoad_Click(object sender, RoutedEventArgs e) { Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); dlg.FileName = "Document"; dlg.DefaultExt = ".txt"; dlg.Filter = "Text Documents (.txt)|*.txt"; if (dlg.ShowDialog() == true) { fileName = dlg.FileName; OutputConsole.Text = " "; OutputConsole.Text = fileName; var output = new List<MyData>(); try { // First line skipped as we do not need headers. foreach (var line in File.ReadAllLines(filename).Skip(1)) { output.Add(new MyData(line.Split(","))); } OutputConsole.Text = string.Format("{0} lines read.", output.Lenght); } catch (System.IO.IOException ex) { //let user know there was an error reading file } // Do something with output } } 

Now you have a collection of output objects, each of which has strongly typed access to your values, which should be easily populated in DB

+2
source

The code for reading your file is a bit odd (it has a slight minor change), but I don't think this is a problem. Usually (following the example of msdn) the while loop is written as such;

  string line; while ((line = sr.ReadLine()) != null) { ... } 

Also, as suggested in the comments, you can simply use string[] lines = File.ReadAllLines(fileName); and then iterate over the lines with your separate logic in the middle. I suggest removing EndOfStream from your code and using one of the other two approaches. I do not know that this will fix your problem, but it stands out as something that is not entirely normal.

In addition, your result is bad, because you do not add it to the text field, you set its value. This means that you will only see the length of the last line in the file. If you want to see the length of each line, it should be OutputConsole.Text += lineWords.Length + " "; . If you did not know that there was an implicit execution done there, so there is no need for your explicit cast, which simply makes the code less readable.

+2
source

Source: https://habr.com/ru/post/1483621/


All Articles