C#控制台如何保存输出最简单的版本?



我对C#很陌生;有人知道如何在不启动新进程的情况下将所有输出行写入.txt文件吗?

此代码仅写入最后一条记录:

class Program
{
static void Main(string[] args)
{
WezKomponent("Win32_DiskDrive", "Model");
Console.ReadKey();
}
private static void WezKomponent(string ass, string sax)
{
ManagementObjectSearcher wez = new ManagementObjectSearcher("root\CIMV2", "SELECT * FROM " + ass);
foreach (ManagementObject pie in wez.Get())
{
Console.WriteLine(Convert.ToString(pie[sax]));
StreamWriter SW = new StreamWriter(@"HDD.txt");
SW.WriteLine(Convert.ToString(pie[sax]));
SW.Close();
}
}
}

实际上,它确实将所有记录写入文件,问题是您每次都覆盖文件,因此您观察到的是只保留最后一条记录。

对此有两种解决方案:

  1. 在循环之前打开文件,写入所有记录,然后关闭文件
  2. 在循环中打开文件,但这样做的方式将附加新内容

一般来说,把第一个做对比较容易,所以这里是怎么做到的:

  1. 将流的开口向上移出循环
  2. 将流的闭合向下移出循环

本质上,您采用以下代码行:

private static void WezKomponent(string ass, string sax)
{
ManagementObjectSearcher wez = new ManagementObjectSearcher("root\CIMV2", "SELECT * FROM " + ass);
foreach (ManagementObject pie in wez.Get())
{
Console.WriteLine(Convert.ToString(pie[sax]));
StreamWriter SW = new StreamWriter(@"HDD.txt");
SW.WriteLine(Convert.ToString(pie[sax]));
SW.Close();
}
}

并将它们更改为:

private static void WezKomponent(string ass, string sax)
{
ManagementObjectSearcher wez = new ManagementObjectSearcher("root\CIMV2", "SELECT * FROM " + ass);
StreamWriter SW = new StreamWriter(@"HDD.txt");
foreach (ManagementObject pie in wez.Get())
{
Console.WriteLine(Convert.ToString(pie[sax]));
SW.WriteLine(Convert.ToString(pie[sax]));
}
SW.Close();
}

此外,为了在发生错误时更加故障安全,最好使用以下语法:

using (... = new SomethingThatImplementsIDisposable(...))
{
}

比这个:

... = new SomethingThatImplementsIDisposable(...);
...
...Close(); // or .Dispose();

因此,这是您的方法的更好版本:

private static void WezKomponent(string ass, string sax)
{
using (ManagementObjectSearcher wez = new ManagementObjectSearcher("root\CIMV2", "SELECT * FROM " + ass))
using (StreamWriter SW = new StreamWriter(@"HDD.txt"))
{
foreach (ManagementObject pie in wez.Get())
{
Console.WriteLine(Convert.ToString(pie[sax]));
SW.WriteLine(Convert.ToString(pie[sax]));
}
}
}

这更好的原因是因为代码中出现异常的可能性。如果发生这种情况,SW.Close();将不会执行,这意味着您将流和文件保持打开状态,至少比预期时间长。对于这样的using子句,如果内部发生异常,将调用这些对象上的Dispose方法,关闭文件,在本例中也关闭ManagementObjectSearcher对象。


那么有没有办法进一步改进你的代码呢?是的,但前提是您知道我将要展示的其他语法,或者愿意学习。既然你说你是 C# 的新手,你可能不知道它,你可能希望熟悉现有的代码,然后再从你的角度来看它变得更加复杂。

有几种方法可以写入文本文件,StreamWriter是其中之一,File.WriteAllLines是另一种,但这需要将要写入的内容作为字符串集合提供,这些字符串将作为一系列行写入文件。

那么我们如何才能从您的ManagementObjectSearcher对象到字符串列表呢?

通过一组语法和 .NET 类统称为"LINQ"或"语言输入查询"。

下面是方法的较短版本:

private static void WezKomponent(string ass, string sax)
{
using (ManagementObjectSearcher wez = new ManagementObjectSearcher("root\CIMV2", "SELECT * FROM " + ass))
{
File.WriteAllLines(@"HDD.txt", wez
.Get()
.Select(pie => ConvertToString(pie[sax])));
}
}

这甚至可以缩短为在每行上放置更多内容并删除一些不必要的大括号,并在可以从周围的代码中轻松识别确切类型时使用var

private static void WezKomponent(string ass, string sax)
{
using (var wez = new ManagementObjectSearcher("root\CIMV2", "SELECT * FROM " + ass))
File.WriteAllLines(@"HDD.txt", wez.Get().Select(pie => ConvertToString(pie[sax])));
}
class Program
{
static void Main(string[] args)
{
WezKomponent("Win32_DiskDrive", "Model");
Console.ReadKey();
}
private static void WezKomponent(string ass, string sax)
{
ManagementObjectSearcher wez = new ManagementObjectSearcher("root\CIMV2", "SELECT * FROM " + ass);
StreamWriter SW = new StreamWriter(@"HDD.txt");
foreach (ManagementObject pie in wez.Get())


{
Console.WriteLine(Convert.ToString(pie[sax]));
SW.WriteLine(Convert.ToString(pie[sax]));

}
SW.Close();
}

尝试以不同的方式初始化 StreamWriter。

StreamWriter SW = new StreamWriter(@"HDD.txt", append: true);

注意构造函数调用中的append: true

最新更新