在C#中读取,拆分和显示多行CSV文件

所有,

我正在尝试编写一个测试平台程序,最终允许我获取CSV .txt文件并将其内容放入SQLite数据库文件中。 我正在使用的.txt文件有数百行。

以下是我到目前为止:带有三个按钮的WPF表格 –

退出:不言自明

加载CSV文件:弹出Win32打开文件对话框。

当前目录信息:查找程序正在运行的当前目录,并显示它。

和一个文本块,它显示程序输出中的各种信息 – 基本上,无论我想要什么,例如exception等。

为了读取文本文件,我实现了以下代码:

using System; using System.Data; using System.Data.SQLite; using System.IO; using System.Windows; using System.Windows.Controls; namespace C_Sharp_SQLite_Testbed { ///  /// Interaction logic for MainWindow.xaml ///  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 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); } } } } 

这是一个相当简单的设置,我遇到问题的唯一方法是btnLoad_ClickStreamReader方法从对话框中接收fileName变量作为参数。 它成功打开了该文件。 虽然不在文件流的末尾,但是使用var line = sr.ReadLine();读取var line = sr.ReadLine(); 。 然后我们使用var lineWords = line.Split(',');将线分割成一个数组var lineWords = line.Split(','); 。 然后,使用OutputConsole.Text = Convert.ToString(lienWords.Length);将lineWords数组的长度打印到文本块OutputConsole.Text = Convert.ToString(lienWords.Length); 。 问题是:看起来好像只从文件中读取一个值,读取器停在第一个逗号,然后停止读取。 打印的数组值为1,当我将OutputConsole.Text = Convert.ToString(lineWords.Length)更改为OutputConsole.Text = Convert.ToString(lineWords[1]);时,只打印一个值OutputConsole.Text = Convert.ToString(lineWords[1]); 。 而且,这不是正确的价值。 所以基本上,我在数组中只有一个空格,而且它没有填充正确的值。

你们有什么建议改变这个? 用C#读取文件从来都不是我的强项。

编辑:这是前两行,作为文件中的内容的采样器。 它是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

这些只是标题。

第二行: 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

我相信编码是ANSI。


编辑:

这是读取线条的“新”块。 到目前为止工作得很好,现在,需要将事物分成2D数组。

 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"; } } 

我就是这样做的:

首先,定义一个类来保存文件的输出:

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

然后修改按钮事件以填充这些对象的列表

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

现在,您有一个对象的集合output ,每个对象都具有对值的强类型访问权限,这些对象应该很容易填充到数据库中

你的文件阅读代码有点奇怪(它有一些小的减少)但我不认为这是问题。 通常(在msdn示例之后),while循环是这样写的;

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

另外,如评论中所建议的那样,你可以使用string[] lines = File.ReadAllLines(fileName); 然后在中间循环使用拆分逻辑。 我建议从代码中删除EndOfStream并使用其他两种方法之一。 我不知道它会解决你的问题,但这是一个不正常的事情。

此外,您的输出很糟糕,因为您没有附加到文本框,而是设置它的值。 这意味着您只会看到文件中最后一行的长度。 如果你想看到每一行的长度,它需要是OutputConsole.Text += lineWords.Length + " "; 如果您不知道在那里进行了隐式转换,那么就不需要进行显式转换,这会使代码的可读性降低。