【问题标题】:How to write a list to a text file. Write 50 items per line如何将列表写入文本文件。每行写 50 个项目
【发布时间】:2018-10-03 20:56:28
【问题描述】:

我正在开发一个程序,我从文件中读取数据,将该数据存储在一个列表中,并将该数据以特殊格式写入一个新文件。我已经创建了读取原始文件并将其存储在列表中的方法。

我从中读取的文件是一个数字列表。每行一个数字。

我的写入新文件的方法有问题。 我在取 50 个项目并将它们写入一行,然后取下 50 个项目并在下一行写入时遇到问题。该方法将前 50 个项目写入并在每行重复这 50 个项目。我知道这是因为我的第二个 for 循环。只是不知道如何解决。任何帮助,将不胜感激。以下是我的代码:

public static void WriteFormattedTextToNewFile(List<string> groupedStrings)
{
    string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
    StreamWriter sw = new StreamWriter(file, true);

    for (int i = 0; i < ReadFile.GroupedStrings.Count; i++)
    {
        sw.Write($"{DateTime.Now:yyyy MM dd  hh:mm:ss}\t\t");

        for (int j = 0; j < 50; j++)
        {
            sw.Write($"{ReadFile.GroupedStrings[j]}\t");
        }
        sw.WriteLine();
    }
    sw.Close();
}

【问题讨论】:

  • 为什么你将一个字符串列表传递给这个方法,然后在写入文件时完全忽略这个变量?
  • 代码中的 50 在哪里?您希望循环通过ReadFile.GroupedStrings.Count 为您做什么? ReadFile.GroupedStrings 来自哪里,它的类型是什么?
  • ReadFile.GroupedStrings 是我传递给此方法的字符串列表。我没有忽略这个变量。当我运行此方法时,它是 WriteFile.WriteFormattedTextToNewFile(ReadFile.GroupedStrings);
  • ReadFile.GroupedStrings 不是您传递给此方法的字符串列表。 groupedStrings 是。
  • NetMage,我刚刚将代码块更新为 50。我复制了错误的块。

标签: c# list writetofile


【解决方案1】:

我会给你三个选择(和奖金)。

第一个选项。使用使用迭代器块的自定义 Chunk(int) linq 运算符。诀窍是内部方法使用与外部相同的枚举器。看起来代码很多,但是一旦你有了Chunk() 方法,你就可以在任何地方使用它。另请注意,此选项甚至不需要List&lt;string&gt;。它适用于 any IEnumerable&lt;string&gt;,因为我们从不通过索引引用任何元素。

public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> values, int chunkSize)
{
    var e = values.GetEnumerator();
    while (e.MoveNext())
    {
        yield return innerChunk(e, chunkSize);
    }
}

private static IEnumerable<T> innerChunk<T>(IEnumerator<T> e, int chunkSize)
{
    //If we're here, MoveNext() was already called once to advance between batches
    // Need to yield the value from that call.
    yield return e.Current;

    //start at 1, not 0, for the first yield above  
    int i = 1; 
    while(i++ < chunkSize && e.MoveNext()) //order of these conditions matters
    {
        yield return e.Current;
    }
}
    
public static void WriteFormattedTextToNewFile(IEnumerable<string> groupedStrings)
{
    string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
    using (var sw = new StreamWriter(file, true))
    {   
        foreach(var strings in groupedStrings.Chunk(50))
        {
            sw.Write($"{DateTime.Now:yyyy MM dd  hh:mm:ss}\t\t");
            foreach(var item in strings)
            {
               sw.Write($"{item}\t");
            }
            sw.WriteLine();
        } 
    }
}

这是一个基本的proof of concept Chunk() actually works

作为奖励选项,这是使用第一个选项中的 Chunk() 方法的另一种方法。请注意实际方法变得多么小而直接,但是长整行字符串的构造可能会降低效率。

public static void WriteFormattedTextToNewFile(IEnumerable<string> groupedStrings)
{
    string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
    using (var sw = new StreamWriter(file, true))
    {   
        foreach(var strings in groupedStrings.Chunk(50))
        {
            sw.Write($"{DateTime.Now:yyyy MM dd  hh:mm:ss}\t\t");
            sw.WriteLine(string.Join("\t", strings));
        } 
    }
}

第二个选项。使用单独的整数/循环跟踪。注意内部循环的额外条件,仍然使用i 值而不是j 来引用当前位置,并在内部循环中递增i。这称为控制/中断循环。请注意我们如何能够在每一行上写入结束行和初始日期值,以便它们在代码中也以正确的顺序出现:首先是页眉,然后是项目,然后是页脚,并且我们无需复杂的条件检查即可完成.

public static void WriteFormattedTextToNewFile(List<string> groupedStrings)
{
    string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
    using (var sw = new StreamWriter(file, true))
    {   
        int i = 0;
        while(i < groupedStrings.Count)
        {
           sw.Write($"{DateTime.Now:yyyy MM dd  hh:mm:ss}\t\t");
           for(int j = 0; j < 50 && i < groupedStrings.Count; j++)
           {
              sw.Write($"{groupedStrings[i]}\t");
              i++;
           }
           sw.WriteLine();
        }
    }
}

第三个选项。使用模数运算符 (%) 跟踪。此选项(或在同一循环中使用第二个 j 值的类似选项)是许多人首先转向的地方,但要小心;这个选项看起来很难正确,尤其是当问题变得更加复杂时。

public static void WriteFormattedTextToNewFile(List<string> groupedStrings)
{
    string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
    using (var sw = new StreamWriter(file, true))
    {
        for(int i = 0; i < groupedStrings.Count;i++)
        {
            if (i % 50 == 0)
            {
                if (i > 0) sw.WriteLine();
                sw.Write($"{DateTime.Now:yyyy MM dd  hh:mm:ss}\t\t");
            }

            sw.Write($"{groupedStrings[i]}\t");
        }
        sw.WriteLine();
    }
}

更新:

Chunk() 的变体现在包含在 .Net 6 的开箱即用中。

【讨论】:

  • 非常感谢乔尔!我选择了第二个选项,因为它是我更熟悉的。以后我会考虑使用 Chunk()。
猜你喜欢
  • 2020-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-20
  • 2018-02-04
  • 2020-01-26
  • 1970-01-01
相关资源
最近更新 更多