4

全部,

我正在尝试编写一个测试平台程序,该程序最终将允许我获取一个 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_Click. 该StreamReader方法fileName从对话框接收变量作为参数。它成功打开文件。虽然不在文件流的末尾,但使用var line = sr.ReadLine();. 然后,我们使用 将行拆分为一个数组var lineWords = line.Split(',');。之后,lineWords 数组的长度使用 打印到文本块中OutputConsole.Text = Convert.ToString(lienWords.Length);。问题是这样的:似乎只从文件中读取了一个值,读取器在第一个逗号处停止,然后停止读取。正在打印的数组值为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";
    }

}
4

2 回答 2

2

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

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

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

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

于 2013-05-30T16:08:28.553 回答
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,每个对象都对你的值具有强类型访问权限,这些对象应该很容易填充到数据库中

于 2013-05-30T16:26:03.780 回答