首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从没有包含数据的文本文件中读取?

如何从没有包含数据的文本文件中读取?
EN

Stack Overflow用户
提问于 2020-12-10 11:01:56
回答 2查看 88关注 0票数 2

我有一个文本文件,它存储有关生产信息和过程的信息。该过程由StrippingCleaningPaint等几个阶段组成,这些阶段存储的日期可以是expected datestart datefinished datedelay date

一个示例.txt文件:

567,Eindhoven,21岁,汽提_e=20/05/2020,汽提_s=21/05/2020,剥落_f=22/05/2020,清洁_e=23/05/2020,清洁_s=27/05/2020,清洁_f=28/05/2020,油漆_e=28/05/2020,Panint_s=28/05/2020,油漆_f=29/05/2020,内阁_e=29/05/2020,内阁_s=31/05/2020,Cabinet_f=,Table_e=,Table_s=,Table_f=,Stand_e=,Stand_s=,Stand_f=,Display_e=,Display_s=,Display_f=,UControls_e=,UControls_s=,UControls_f=,Test_e=,Test_s=,Test_f=,Prepack_e=,Prepack_s=,Prepack_f=,Endpack_e=,Endpack_s=,Endpack_f=,Release_e=,Release_s=,Release_f=,

在读取此.txt文件后,我将其存储在dataGridView中,如下所示:

但是,我不知道如何将最新的日期添加到相应的列中。如果在文本文件中看到Stripping_e,则希望重写Stripping列中的Stripping_f值。其余的列也是一样。这也是我不一定有一个日期(预期,开始,完成或推迟)的专栏。

下面是我目前使用的代码:

代码语言:javascript
复制
private void IGT_Load(object sender, EventArgs e)
        {
            table.Columns.Add("SalesNr", typeof(int));
            table.Columns.Add("PName", typeof(string));
            table.Columns.Add("Type", typeof(int));
            table.Columns.Add("Stripping", typeof(string));
            table.Columns.Add("Cleaning", typeof(string));
            table.Columns.Add("Paint", typeof(string));
            table.Columns.Add("Cabinet", typeof(string));
            table.Columns.Add("Table", typeof(string));
            table.Columns.Add("Stand", typeof(string));
            table.Columns.Add("Display", typeof(string));
            table.Columns.Add("User Controls", typeof(string));
            table.Columns.Add("Test", typeof(string));
            table.Columns.Add("Pre-pack", typeof(string));
            table.Columns.Add("End-pack", typeof(string));
            table.Columns.Add("Release for Delivery", typeof(string));
            dataGridView1.DataSource = table;
            Import();
        }

        private void Import()
        {
            // get lines from the text file
            string[] lines = File.ReadAllLines(@"..\..\567.txt");
            string[] values;


            for (int i = 0; i < lines.Length; i++)
            {
                values = lines[i].ToString().Split(',', '=');
                string[] row = new string[values.Length];

                for (int j = 0; j < values.Length; j++)
                {
                    
                    if(values[j] == "Stripping_e")
                    {
                        row[j] = values[j + 1].Trim();
                        j++;
                    }
                    else if (values[j] == "Stripping_s")
                    {
                        row[j-2] = values[j+1].Trim();
                        j++;
                    }
                    else if(values[j] == "Cleaning_s" || values[j] == "Cleaning_e" || values[j] == "Cleaning_f" || values[j] == "Cleaning_d")
                    {
                        row[j] = values[j + 1].Trim();
                    }
                    else
                    {
                        row[j] = values[j].Trim();
                    }
                }
                table.Rows.Add(row);
            }
        }

table是以DataSource的形式连接到dataGridView1DataTable

我以前从未处理过文本文件,所以我非常感谢您的帮助!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-12-10 14:23:45

读一个半非结构化的CSV可能是很棘手的,你必须对CSV文件有很大的信心总是正确的。示例,如果类别的日期之一拼写错误,如…“Panint_s=28/05/2020”…在发布的数据…中然后,在下面的代码中,这种拼写错误不会抛出任何类型的错误或消息,它将永远不会被使用。所以编码器要小心。下面是这样一种“讨厌”的方法。

您可能遇到的一个复杂问题是当前代码是如何使用字符串数组(string[])的。这会使事情变得更复杂。当代码到达SomeCategory=SomeDate点时,它很有用。下面是一个字符串数组,用于这些拆分来获取类别的日期。在代码的其他部分,它使用一个List<string>来分隔数据中的行。当我们想要获得“特定”类别的日期时,这将有所帮助。下面会有更多。

因此,给出一个数据的string,例如string是网格中的“单一”行,那么我将在逗号上“拆分”这个字符串。然后将字符串数组转换为List<string>。它可能看起来像…

代码语言:javascript
复制
List<string> SplitRow = curRow.Split(',').ToList();

考虑到发布的单行数据,这个List<string> allData看起来可能类似于…。

可以看到,我们将使用这个List<string>来获取网格中前三个单元格的数据,当我们到达代码中我们想要获得特定类别的“最新”日期的部分时,我们可以“过滤”这个List<string>,使其只包含我们想要的类别。如果allData是上面的List<string>,那么要筛选列表仅包含我们想要的类别,代码可能看起来类似于…。

代码语言:javascript
复制
String targetCategory = “Stripping”;
List<string> categoryData = allData.Where(x => x.Contains(targetCategory)).ToList();

这将产生一个只有“剥离”类别的List<string> categoryData。就像下面的…

使用此列表,我们可以循环遍历所有字符串,解析日期,并从所有给定日期返回最新日期。如果我们创建一个返回此日期字符串的方法,那么我们可以使用它为每一行分配网格中的每个类别列。

因此,采用allData列表和string类别进行…筛选的方法。也许会派上用场。此方法可能类似于…下面的内容。

代码语言:javascript
复制
private string GetLatestDateForCategory(List<string> allData, string targetCategory) {
  List<string> categoryData = allData.Where(x => x.Contains(targetCategory)).ToList();
  DateTime latestDate = DateTime.MinValue;
  string[] splitArray;
  foreach (string catLine in categoryData) {
    splitArray = catLine.Split('=');
    if (splitArray.Length >= 2) {
      if (DateTime.TryParseExact(splitArray[1], "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date)) {
        if (date > latestDate) {
          latestDate = date;
        }
      } 
    }
  }
  if (latestDate != DateTime.MinValue) {
    return latestDate.ToShortDateString();
  }
  return "";
}

遍历此方法将从“过滤”所有数据开始,以获得targetCategory字符串值的列表。然后创建一个DateTime变量来比较日期,并将其用作最新日期。我们将把日期设置为“min”值,并使用这个“min”日期来指示类别中没有日期。接下来是字符串数组splitArray,用于拆分“=”字符上的每个字符串。

将启动一个遍历列表中所有筛选字符串的循环。在拆分“=”字符上的字符串后,将进行检查,以确保字符串中有日期。如果存在日期字符串,则将该日期解析为DateTime对象,以便进行比较。如果日期分析成功,则代码将检查已解析的日期到最新日期。如果分析的日期晚于当前latestDate,则更新该日期以反映此更新的最新日期。

检查完所有日期后,代码将检查latestDate。如果latestDate仍然是“Min”值,那么这意味着没有为该类别找到日期,并且返回一个空字符串,否则代码将返回最新的日期字符串。

如果代码循环遍历有许多行的数据中的每个字符串,那么当我们想从特定类别获得最新的日期时,上面的方法就会派上用场了。

因此,将这些放在一起可能类似于下面的…

代码语言:javascript
复制
private void Import() {
  List<string> allLines = File.ReadAllLines(@"D:\Test\CSV\567.txt").ToList();
  DataRow dr;
  List<string> SplitRow;
  int value;
  foreach (string curRow in allLines) {
    dr = table.NewRow();
    SplitRow = curRow.Split(',').ToList();
    if (SplitRow.Count >= 3) {
      value = 0;
      if (int.TryParse(SplitRow[0], out value)) {
        dr["SalesNr"] = value;
      }
      if (int.TryParse(SplitRow[2], out value)) {
        dr["Type"] = value;
      }
      dr["PName"] = SplitRow[1];
      dr["Stripping"] = GetLatestDateForCategory(SplitRow, "Stripping");
      dr["Cleaning"] = GetLatestDateForCategory(SplitRow, "Cleaning");
      dr["Paint"] = GetLatestDateForCategory(SplitRow, "Paint");
      dr["Cabinet"] = GetLatestDateForCategory(SplitRow, "Cabinet");
      dr["Table"] = GetLatestDateForCategory(SplitRow, "Table");
      dr["Stand"] = GetLatestDateForCategory(SplitRow, "Stand");
      dr["Display"] = GetLatestDateForCategory(SplitRow, "Display");
      dr["User Controls"] = GetLatestDateForCategory(SplitRow, "UControls");
      table.Rows.Add(dr);
    }
  }
}

从从CSV文件中获取List<string>开始,遍历此方法。在已发布的数据中,这将是列表中的单个字符串。接下来定义一个DataRow dr,我们将使用此行来添加从数据中获得的值。另一个List<string> SplitRow用于列表中的“每个”字符串。最后,一个int value,用于解析intSalesNrType

从所有数据开始遍历每个字符串的循环,从现有的DataRow中创建一个新的table,然后在逗号“;”上拆分当前字符串。检查以确保SalesNr、PName和Type至少有三个(3)值。解析SalesNrType值,然后将PName字符串值设置为新行。然后,每个“类别”将使用上面的方法来设置每个类别的日期字符串。最后,该行被添加到table中。注意:并非所有类别都填写在代码中。

我希望这是合理的。它很讨厌,但在我的测试中起了作用。祝好运。

票数 2
EN

Stack Overflow用户

发布于 2020-12-10 15:32:11

我就是这样做的。

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Globalization;

namespace WindowsFormsApplication71
{
    public partial class Form1 : Form
    {
        const string FILENAME = @"c:\temp\test.csv";
        public Form1()
        {
            InitializeComponent();

            StreamReader reader = new StreamReader(FILENAME);
            string line = "";
            int row = 0;
            DataTable dt = new DataTable();
            while ((line = reader.ReadLine()) != null)
            {
                line = line.Trim();
                if (line.Length > 0)
                {
                    string[] columns = line.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToArray();
                    List<object> newRow = new List<object>(); ;
                    if (++row == 1)
                    {
                        dt.Columns.Add("SalesNr", typeof(string));
                        dt.Columns.Add("PName", typeof(string));
                        dt.Columns.Add("Type", typeof(int));
                    }
                    for (int col = 0; col < columns.Length; col++)
                    {
                        switch (col)
                        {
                            case 0:
                                newRow.Add(columns[0]);
                                break;
                            case 1:
                                newRow.Add(columns[1]);
                                break;
                            case 2:
                                newRow.Add(columns[2]);
                                break;
                            default:
                                string[] keyValue = columns[col].Split(new char[] { '=' });
                                if (row == 1)
                                {
                                    dt.Columns.Add(keyValue[0], typeof(DateTime));
                                }
                                if (keyValue[1].Trim().Length > 0)
                                {
                                    newRow.Add(DateTime.ParseExact(keyValue[1], "dd/MM/yyyy", CultureInfo.InvariantCulture));
                                }
                                else
                                {
                                    newRow.Add(null);
                                }
                                break;
                        }
                    }
                    dt.Rows.Add(newRow.ToArray());
                }
            }
            dataGridView1.DataSource = dt;
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65233281

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档