如何读取文本文件并计算相同的名称

时间:2012-07-26 09:35:15

标签: c# file

我想创建每行包含一个名称的文本文件。计算任何名称出现的次数。为文件中的每个名称输出一行,并在每行上输出出现次数,后跟名称。

我可以使用此代码打开文件

private void button1_Click(object sender, EventArgs e)
{
    using (OpenFileDialog dlgOpen = new OpenFileDialog())
    {
        try
        {
            // Available file extensions
            openFileDialog1.Filter = "All files(*.*)|*.*";
            // Initial directory
            openFileDialog1.InitialDirectory = "D:";
            // OpenFileDialog title
            openFileDialog1.Title = "Open";
            // Show OpenFileDialog box
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                // Create new StreamReader
                StreamReader sr = new StreamReader(openFileDialog1.FileName, Encoding.Default);
                // Get all text from the file
                string str = sr.ReadToEnd();
                // Close the StreamReader
                sr.Close();
                // Show the text in the rich textbox rtbMain

            }
        }
        catch (Exception errorMsg)
        {
            MessageBox.Show(errorMsg.Message);
        }
    }
}

但我想要的是使用相同的按钮来阅读并在组框中显示它。

5 个答案:

答案 0 :(得分:3)

由于这是作业,我不打算给你代码,但希望有足够的信息指出你正确的方向。

我建议你使用File.ReadAllLines将文件读入一个字符串数组,数组中的每个项目都是文件中的一行。这意味着您不必自己拆分文件内容。然后,您可以循环遍历字符串数组,并将每行添加到Dictionary中,其中键是从文件读取的行,值是出现次数。您需要检查密钥是否已经在字典中 - 如果不是添加计数为1,否则更新现有计数(+1)。在该循环之后,使用第二个循环遍历Dictionary内容,使用名称及其计数更新文本框。

答案 1 :(得分:1)

(假设这是一个家庭作业)我使用了File.ReadAllLineDictionary<TKey, TValue>

var nameCount = new Dictionary<string, int>();

foreach (String s in File.ReadAllLines("filename"))
{
    if (nameCount.ContainsKey(s))
    {
        nameCount[s] = nameCount[s] + 1;
    }
    else
    {
        nameCount.Add(s, 1);
    }
}

// and printing
foreach (var pair in nameCount)
{
    Console.WriteLine("{0} count:{1}", pair.Key, pair.Value);
}

答案 2 :(得分:0)

以前曾提出过类似的问题: A method to count occurrences in a list

在我看来,使用LINQ查询是一个不错的选择。

string[] file = File.ReadAllLines(openFileDialog1.FileName, Encoding.Default);

IEnumerable<string> groupQuery =
    from name in file
    group name by name into g
    orderby g.Key
    select g;

foreach (var g in groupQuery)
{
    MessageBox.Show(g.Count() + " " + g.Key);
}

答案 3 :(得分:0)

好的,像这样的函数会为你建立不同的名字。

private static IDictionary<string, int> ParseNameFile(string filename)
{
    var names = new Dictionary<string, int>();
    using (var reader = new StreamReader(filename))
    {
        var line = reader.ReadLine();
        while (line != null)
        {
            if (names.ContainsKey(line))
            {
                names[line]++;
            }
            else
            {
                names.Add(line, 1);
            }
            line = reader.ReadLine(); 
        }
    }
}

或者你可以用linq和readAllLines做一些闪光。

private static IDictionary<string, int> ParseNameFile(string filename)
{
    return File.ReadAllLines(filename)
        .OrderBy(n => n)
        .GroupBy(n => n)
        .ToDictionary(g => g.Key, g => g.Count);
}

第一个选项确实具有不将整个文件加载到内存中的优点。

至于输出信息,

var output = new StringBuilder();
foreach (valuePair in ParseNameFile(openFileDialog1.FileName))
{
    output.AppendFormat("{0} {1}\n", valuePair.Key, valuePair.Value); 
}

然后您在输出上ToString()将数据放入任何您想要的位置。如果行数非常多,则首选StreamWriter方法。

答案 4 :(得分:0)

您可以使用Linq执行此操作,而无需增加int变量。最终有一个包含姓名和计数的字典

string names = sr.ReadAllLines();
Dictionary<string, int> namesAndCount = new Dictionary<string, int>();

foreach(var name in names)
{
    if(namesAndCount.ContainsKey(name))
        continue;

    var count = (from n in names
                where n == name
                select n).Count();

    namesAndCount.Add(name, count);
}