如何将列表写入文本文件.每行写入 50 个项目



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

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

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

public static void WriteFormattedTextToNewFile(List<string> groupedStrings)
{
string file = @"C:Userse011691DesktopNew folderformatted.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}tt");
for (int j = 0; j < 50; j++)
{
sw.Write($"{ReadFile.GroupedStrings[j]}t");
}
sw.WriteLine();
}
sw.Close();
}

我会给你三个选项(和一个奖金(。

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

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:Userse011691DesktopNew folderformatted.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}tt");
foreach(var item in strings)
{
sw.Write($"{item}t");
}
sw.WriteLine();
} 
}
}

这是一个基本的概念证明 Chunk(( 实际工作。

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

public static void WriteFormattedTextToNewFile(IEnumerable<string> groupedStrings)
{
string file = @"C:Userse011691DesktopNew folderformatted.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}tt");
sw.WriteLine(string.Join("t", strings));
} 
}
}

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

public static void WriteFormattedTextToNewFile(List<string> groupedStrings)
{
string file = @"C:Userse011691DesktopNew folderformatted.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}tt");
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:Userse011691DesktopNew folderformatted.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}tt");
}
sw.Write($"{groupedStrings[i]}t");
}
sw.WriteLine();
}
}
<小时 />

更新:

Chunk()的变体现在包含在 .Net 6 中

最新更新