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

时间:2013-05-30 16:00:06

标签: c# csv

全部,

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

这是我到目前为止所拥有的:带有三个按钮的WPF表单 -

退出:不言自明

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

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

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

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

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

这是一个相当简单的设置,我唯一遇到问题的方法是btnLoad_ClickStreamReader方法从对话框中接收fileName变量作为参数。它成功打开了该文件。虽然不在文件流的末尾,但使用var line = sr.ReadLine();读取一行。然后,我们使用var lineWords = line.Split(',');将该行拆分为一个数组。然后,使用OutputConsole.Text = Convert.ToString(lienWords.Length);将lineWords数组的长度打印到文本块。问题是这样:好像只从文件中读取一个值,读取器停在第一个逗号,然后停止读取。打印的数组值为1,当我将OutputConsole.Text = Convert.ToString(lineWords.Length)更改为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";
    }

}

2 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分:2)

我就是这样做的:

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

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

        }
    }

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