问题 如何从文件读取一次数据,然后将其用于不同的按钮事件?

哇哇

成员
已加入
2019年11月9日
留言内容
16
编程经验
Beginner
嗨,所以我不得不做一个要从文本文件(名称,性别,bDay等)中获取数据的应用程序,并将其加载到dataGridView表中。另外要补充的是,仅需要加载3个按钮(女性,男性或比* set age *年龄大的任何人)。
我几乎做了我需要的事情,但是每个按钮每次都必须读取该文件。因此,我想知道如何才能一次读取该文件,然后将按钮保留为仅用作设置数据的过滤器?

C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        // Nuskaityti moterys
        private void button1_Click(object sender, EventArgs e)
        {
            string systemPath = System.IO.Directory.GetCurrentDirectory() + @"\txt1.txt";

            using (var streamReader = new System.IO.StreamReader(systemPath))
            {
                dataGridView1.Rows.Clear();
                while (!streamReader.EndOfStream)
                {
                    string line = streamReader.ReadLine();
                    string[] values = line.Split('\t');

                    for (int i=0; i<values.Length; i++)
                    {
                        string[] rez = values[i].Split(',');
                        rez[2] = rez[2].Trim();

                        if (rez[2].ToString() == "Moteris")
                        {
                            int rowIndex = dataGridView1.Rows.Add();
                            dataGridView1.Rows[rowIndex].Cells["Column1"].Value = rez[0];
                            dataGridView1.Rows[rowIndex].Cells["Column2"].Value = rez[1];
                            dataGridView1.Rows[rowIndex].Cells["Column3"].Value = rez[2];
                            dataGridView1.Rows[rowIndex].Cells["Column4"].Value = rez[3];
                            dataGridView1.Rows[rowIndex].Cells["Column5"].Value = rez[4];
                            dataGridView1.Rows[rowIndex].Cells["Column6"].Value = rez[5];
                        }
                    }
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            string systemPath = System.IO.Directory.GetCurrentDirectory() + @"\txt1.txt";

            using (var streamReader = new System.IO.StreamReader(systemPath))
            {
                dataGridView1.Rows.Clear();
                while (!streamReader.EndOfStream)
                {
                    string line = streamReader.ReadLine();
                    string[] values = line.Split('\t');

                    for (int i = 0; i < values.Length; i++)
                    {
                        string[] rez = values[i].Split(',');
                        rez[2] = rez[2].Trim();

                        if (rez[2].ToString() == "Vyras")
                        {
                            int rowIndex = dataGridView1.Rows.Add();
                            dataGridView1.Rows[rowIndex].Cells["Column1"].Value = rez[0];
                            dataGridView1.Rows[rowIndex].Cells["Column2"].Value = rez[1];
                            dataGridView1.Rows[rowIndex].Cells["Column3"].Value = rez[2];
                            dataGridView1.Rows[rowIndex].Cells["Column4"].Value = rez[3];
                            dataGridView1.Rows[rowIndex].Cells["Column5"].Value = rez[4];
                            dataGridView1.Rows[rowIndex].Cells["Column6"].Value = rez[5];
                        }
                    }
                }
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            string systemPath = System.IO.Directory.GetCurrentDirectory() + @"\txt1.txt";

            using (var streamReader = new System.IO.StreamReader(systemPath))
            {
                dataGridView1.Rows.Clear();
                while (!streamReader.EndOfStream)
                {
                    string line = streamReader.ReadLine();
                    string[] values = line.Split('\t');

                    for (int i = 0; i < values.Length; i++)
                    {
                        string[] rez = values[i].Split(',');
                        string date;

                        date = rez[5].Replace("-", "");
                        int today = int.Parse(DateTime.UtcNow.ToString("yyyyMMdd"));
                        int bDay = int.Parse(date);
                        int age = (today - bDay) / 10000;
                        int filterDate = Convert.ToInt32(textBox1.Text);

                        if (age >= filterDate)
                        {
                            int rowIndex = dataGridView1.Rows.Add();
                            dataGridView1.Rows[rowIndex].Cells["Column1"].Value = rez[0];
                            dataGridView1.Rows[rowIndex].Cells["Column2"].Value = rez[1];
                            dataGridView1.Rows[rowIndex].Cells["Column3"].Value = rez[2];
                            dataGridView1.Rows[rowIndex].Cells["Column4"].Value = rez[3];
                            dataGridView1.Rows[rowIndex].Cells["Column5"].Value = rez[4];
                            dataGridView1.Rows[rowIndex].Cells["Column6"].Value = rez[5];
                        }
                    }
                }
            }
        }
    }
}

提前致谢!
 

羊皮

知名会员
已加入
2018年9月5日
留言内容
1,982
编程经验
10+
您能否提供您要引用的文本文件。

我已经打算将其读入数组,但是一旦看到文本文件,我就可以肯定知道。

顺便说一句,欢迎来到论坛
 

哇哇

成员
已加入
2019年11月9日
留言内容
16
编程经验
Beginner
您能否提供您要引用的文本文件。

我已经打算将其读入数组,但是一旦看到文本文件,我就可以肯定知道。

顺便说一句,欢迎来到论坛
姓名,姓氏,性别,电子邮件,地址,出生日期
那几乎是格式,我用以下文件填充了文件:
名1,姓1,女, [email protected],Street1,2000年1月1日
姓2,姓2,男, [email protected],Street2,1988年1月6日
等等...您想要多长时间(出于测试目的,我将其简化了)。

谢谢你
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,566
地点
悉尼,澳大利亚
编程经验
10+
You should start by reading the file into a DataTable, using either an OleDbDataAdapter or a TextFieldParser. The latter is declared in the Microsoft.VisualBasic.dll assembly, so you'd need to reference that. As with any object that you need to access at arbitrary times, you should assign the DataTable to a member variable, i.e. a field. You can then bind the DataTable to a BindingSource 和 bind that to your DataGridView. You can then filter the data by setting the Filter property of BindingSource, e.g.
C#:
myBindingSource.Filter = "Gender = 'Female'";
或者:
C#:
var ageThreshold = Convert.ToInt32(ageNumericUpDown.Value);
var dateThreshold = DateTime.Today.AddYears(-ageThreshold);

myBindingSource.Filter = $"[Date of birth] <= #{dateThreshold:M/dd/yyyy}#";
 
Last edited:

羊皮

知名会员
已加入
2018年9月5日
留言内容
1,982
编程经验
10+
我只在大约3,4周前在这里回答了同样的问题 回到六月。从文本文件接收此数据的麻烦要求每次数据都具有完全相同的结构。例如,您可以保证不会再有第二条街吗?因为如果有的话,在将文本加密时,它将使您使用的任何方法都不可靠。我的问题是;是否可以使用文本以外的其他格式的数据(也许是XML)?预防总比治疗好。但是,如果您对当前如何接收此数据感到满意,那么John的答复将解决您问题的第二部分。
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,609
地点
弗吉尼亚州切萨皮克
编程经验
10+
并回想起仍然用于电子邮件地址的RFC5322仍然支持带引号的字符串,因此以下是合法的电子邮件地址:
C#:
"Last, First"@domain.com
请注意电子邮件地址中的逗号,在这种情况下,由于引号是合法的。
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,566
地点
悉尼,澳大利亚
编程经验
10+
并回想起仍然用于电子邮件地址的RFC5322仍然支持带引号的字符串,因此以下是合法的电子邮件地址:
C#:
"Last, First"@domain.com
请注意电子邮件地址中的逗号,在这种情况下,由于引号是合法的。
我没有意识到这一点。当然,使用这种电子邮件地址的任何人都不应该收到任何电子邮件,我认为许多系统可能仍然不接受它。

Of course, well-written parsing code would handle that anyway, if the file was also well-written. If you escape any double-quotes with another double-quote and wrap any values that contains delimiters in double-quotes then a TextFieldParser will handle it and I'd wager that ADO.NET would too.
 

哇哇

成员
已加入
2019年11月9日
留言内容
16
编程经验
Beginner
我只在大约3,4周前在这里回答了同样的问题 回到六月。从文本文件接收此数据的麻烦要求每次数据都具有完全相同的结构。例如,您可以保证不会再有第二条街吗?因为如果有的话,在将文本加密时,它将使您使用的任何方法都不可靠。我的问题是;是否可以使用文本以外的其他格式的数据(也许是XML)?预防总比治疗好。但是,如果您对当前如何接收此数据感到满意,那么John的答复将解决您问题的第二部分。
哦,不,我才刚开始第一年,我们只涉及C#的基础知识。这个学期我们不会处理任何非常困难的事情,因此文本文件将始终保持相同的格式。
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,609
地点
弗吉尼亚州切萨皮克
编程经验
10+
我认为很多系统可能还是不会接受它。
是的,很不幸"front-end"UI不接受它,很多用户也同样不接受'+','{'或'}'符号。我相信这是因为它们只是天真地浏览了RFC和/或只是欺骗了其他人RegEx来验证电子邮件地址。正如整个互联网上所述,不应使用正则表达式来验证电子邮件地址,但人们仍然会这样做。

不应对电子邮件地址的本地部分施加限制,但人们似乎仍然可以这样做。对我来说,这听起来像是不公平且在文化上不敏感,就像说"您只能使用一个名字,一个可选的名字,一个中间名和一个姓氏-按此顺序"。本地部分的要点是,它取决于目标域来进行任何进一步的解析。邮件传输代理唯一要做的工作就是将邮件传输到适当的域。他们不应该从本地获得信息和特殊信息。但是,这里我们和人们一起编写UI并在本地部分施加了限制。

这就像说“ +”是 不适用于电子邮件地址的本地部分.
 

羊皮

知名会员
已加入
2018年9月5日
留言内容
1,982
编程经验
10+
C#:
        public static readonly string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "mytext.txt");
        public static List<string[]> IEnum = new List<string[]>();
我将文本文件存储在桌面上,因此路径指向那里,并将路径目录与文件名结合在一起。列表<T>IEnum是每个读取行的占位符,它们由定界符从 TextFieldParser 约翰先前曾建议过。它也是IDisposible的,因此您可以将其与 使用语句。解析器实际上非常好,并且通过使用可以非常轻松地处理CSV文件甚至文本文件。 TextFieldParser.ReadFields方法(Microsoft.VisualBasic.FileIO)。它还具有一些非常不错的属性,例如: TextFieldParser.TrimWhiteSpace属性(Microsoft.VisualBasic.FileIO) 用于修剪您需要或想要的任何空白。它还允许您检查行是否包含引号中的单词: TextFieldParser.HasFieldsEnclosedInQuotes属性(Microsoft.VisualBasic.FileIO).

无论如何,我从一个按钮开始,将数据从文件中获取到IEnum(如上定义)中,IEnum存储了string []列表<string[]>-在这里,您会在列表中找到各行,各行都有各自的索引,并且每个索引都包含一个字符串数组条目,您可以在其中访问文件中存储的每行的逗号分隔的数据条目。字符串数组。见调试器:
截图_43.jpg

C#:
        private void Button1_Click(object sender, EventArgs e)
        {
            using (FileStream reader = File.OpenRead(path))
            using (TextFieldParser iParse = new TextFieldParser(reader))
            {
                iParse.Delimiters = new[] { "," }; iParse.HasFieldsEnclosedInQuotes = false;
                do
                    IEnum.Add(iParse.ReadFields());
                while (!iParse.EndOfData);
            }
        }
现在您的文件内容已在IEnum列表中正确组织,现在可以对其进行迭代以访问如下详细信息:
C#:
        private void button2_Click(object sender, EventArgs e)
        {
            foreach (var (firstName, secondName)
                in from string[] line in IEnum
                   let firstName = line[0]
                   let secondName = line[1]
                   let genderType = line[2]
                   let emailAddress = line[3]
                   let personalAddress = line[4]
                   let personalDOB = line[5]
                   select (firstName, secondName))
            /* To get more variables, you need to extend Linq to iterate over and select the additional's */
            {
                Console.WriteLine($"Persons first name is : {firstName}");
                var fullName = string.Concat(firstName, string.Empty.PadRight(1), secondName);
                Console.WriteLine($"Persons Full Name is : {string.Concat(firstName, string.Empty.PadRight(1), secondName)}");
            }
        }
抱歉,我使用了Linq,因为它是习惯的力量,而我忘记了为论坛编写它。但这就像简单地使用foreach或for循环一样。...我确定您会解决的-哦,该死,我心情很好。试试这个 :
C#:
        private void button3_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < IEnum.Count; i++)
            {
                Console.WriteLine(IEnum[i][0]);
                /* [i] iterates the IEnum, while [0] (if changed) will give you a different result, first name [0] second name be [1] etc */
            }
        }
这样,您现在不再需要继续读取文件。并结合以上内容与此:
You should start by reading the file into a DataTable, using either an OleDbDataAdapter or a TextFieldParser. The latter is declared in the Microsoft.VisualBasic.dll assembly, so you'd need to reference that. As with any object that you need to access at arbitrary times, you should assign the DataTable to a member variable, i.e. a field. You can then bind the DataTable to a BindingSource 和 bind that to your DataGridView. You can then filter the data by setting the Filter property of BindingSource, e.g.
C#:
myBindingSource.Filter = "Gender = 'Female'";
或者:
C#:
var ageThreshold = Convert.ToInt32(ageNumericUpDown.Value);
var dateThreshold = DateTime.Today.AddYears(-ageThreshold);

myBindingSource.Filter = $"[Date of birth] <= #{dateThreshold:M/dd/yyyy}#";
您应该按照要求拥有一个可以正常运行的应用程序。如果您遇到困难或需要更多信息,请发回信给我们。

哦,不,我才刚开始第一年,我们只涉及C#的基础知识。这个学期我们不会处理任何非常困难的事情,因此文本文件将始终保持相同的格式。
这纯粹是一厢情愿的想法,我永远不会抱怨,但是我希望学校在给予更多实际任务时会付出更多的努力。请记住我对上面有关文件结构的评论所说的内容。如果您的老师决定在文件中添加一个人的中间名,这将使我所做的所有事情变得毫无用处,并且将无法按预期运行。因此,我认为您的任务相当差。

希望能帮助到你。
 
Last edited:
最佳 底部