如何在C#上使用FileMode.Append?

如何在C#上使用FileMode.Append?,c#,C#,我一直在试图找到一种方法,让我的代码打开一个文件或创建一个文件(如果我给定的文件名不存在的话)。之后,它将运行一个程序,最终创建一个数组,我希望将该数组的内容转换为字符串并附加到我正在创建和打开的文件中。除了“附加”部分,我什么都做对了。它最后说“对象引用未设置为对象的实例”。你能告诉我这一点吗?非常感谢您的帮助 try { FileStream fs = new FileStream("inventory.ini", FileMode.O

我一直在试图找到一种方法,让我的代码打开一个文件或创建一个文件(如果我给定的文件名不存在的话)。之后,它将运行一个程序,最终创建一个数组,我希望将该数组的内容转换为字符串并附加到我正在创建和打开的文件中。除了“附加”部分,我什么都做对了。它最后说“对象引用未设置为对象的实例”。你能告诉我这一点吗?非常感谢您的帮助

        try
        {
            FileStream fs = new FileStream("inventory.ini", FileMode.OpenOrCreate, FileAccess.Read);
            StreamReader reader = new StreamReader(fs);

            while (!reader.EndOfStream)
            {
                string line = reader.ReadLine();
                string[] data = line.Split('|');
                int code = int.Parse(data[0]);
                string name = data[1];
                double price = double.Parse(data[2]);

                Item item = new Item(code, name, price);
                app.array[inventoryCount++] = item;    
            }

            reader.Close();
            fs.Close();
        }

        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

        app.Run();

        try
        {
            FileStream fs = new FileStream("inventory.ini", FileMode.Append, FileAccess.Write);
            StreamWriter writer = new StreamWriter(fs);

            foreach (Item item in app.array)
            {
                writer.WriteLine(item.Code + "|" + item.Name + "|" + item.Price);
            }

            writer.Close();
            fs.Close();
        }

        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        Console.ReadLine();
    }

您可以使用的另一个构造函数,该构造函数允许追加,然后按如下方式编写:

StreamWriter writer = new StreamWriter("inventory.ini", true);
app.list.Add(item);
try
{
    using (var writer = File.AppendText("inventory.ini"))
    {
        foreach (Item item in app.array)
        {
            if (item != null)
                writer.WriteLine(item.Code + "|" + item.Name + "|" + item.Price);
        }
    }
}

catch (Exception e)
{
    Console.WriteLine(e.Message);
}
我从未在我的应用程序中使用过FileStream,但StreamWriter非常可靠。您也可以使用语句切换到
,这样就不需要
Close()

此外,我建议切换到,这样您将始终在
app.array
中拥有所需的确切数量的项目(顺便说一句,需要更好的名称)。因此:

app.array[inventoryCount++] = item;
将更改为以下内容:

StreamWriter writer = new StreamWriter("inventory.ini", true);
app.list.Add(item);
try
{
    using (var writer = File.AppendText("inventory.ini"))
    {
        foreach (Item item in app.array)
        {
            if (item != null)
                writer.WriteLine(item.Code + "|" + item.Name + "|" + item.Price);
        }
    }
}

catch (Exception e)
{
    Console.WriteLine(e.Message);
}
除了减轻内存管理方面的头痛之外,您不再需要
inventoryCount
变量,因为您可以从
list.Count
中获取此值


这里的一般方法是在相同的功能量下,尽量减少需要编写的代码量。这样就没有地方潜伏错误了。

您可以使用另一个允许追加的构造函数,然后这样写:

StreamWriter writer = new StreamWriter("inventory.ini", true);
app.list.Add(item);
try
{
    using (var writer = File.AppendText("inventory.ini"))
    {
        foreach (Item item in app.array)
        {
            if (item != null)
                writer.WriteLine(item.Code + "|" + item.Name + "|" + item.Price);
        }
    }
}

catch (Exception e)
{
    Console.WriteLine(e.Message);
}
我从未在我的应用程序中使用过FileStream,但StreamWriter非常可靠。您也可以使用
语句切换到
,这样就不需要
Close()

此外,我建议切换到,这样您将始终在
app.array
中拥有所需的确切数量的项目(顺便说一句,需要更好的名称)。因此:

app.array[inventoryCount++] = item;
将更改为以下内容:

StreamWriter writer = new StreamWriter("inventory.ini", true);
app.list.Add(item);
try
{
    using (var writer = File.AppendText("inventory.ini"))
    {
        foreach (Item item in app.array)
        {
            if (item != null)
                writer.WriteLine(item.Code + "|" + item.Name + "|" + item.Price);
        }
    }
}

catch (Exception e)
{
    Console.WriteLine(e.Message);
}
除了减轻内存管理方面的头痛之外,您不再需要
inventoryCount
变量,因为您可以从
list.Count
中获取此值


这里的一般方法是在相同的功能量下,尽量减少需要编写的代码量。然后您就没有地方潜伏错误了。

注意,您也可以在附加模式下使用打开一个
StreamWriter

您还应该使用
using
而不是
.Close()
来关闭流,这样即使发生异常,它也会工作

因此,您的代码看起来更像这样:

StreamWriter writer = new StreamWriter("inventory.ini", true);
app.list.Add(item);
try
{
    using (var writer = File.AppendText("inventory.ini"))
    {
        foreach (Item item in app.array)
        {
            if (item != null)
                writer.WriteLine(item.Code + "|" + item.Name + "|" + item.Price);
        }
    }
}

catch (Exception e)
{
    Console.WriteLine(e.Message);
}

请注意,您也可以在附加模式下使用打开
StreamWriter

您还应该使用
using
而不是
.Close()
来关闭流,这样即使发生异常,它也会工作

因此,您的代码看起来更像这样:

StreamWriter writer = new StreamWriter("inventory.ini", true);
app.list.Add(item);
try
{
    using (var writer = File.AppendText("inventory.ini"))
    {
        foreach (Item item in app.array)
        {
            if (item != null)
                writer.WriteLine(item.Code + "|" + item.Name + "|" + item.Price);
        }
    }
}

catch (Exception e)
{
    Console.WriteLine(e.Message);
}
为什么不使用using语句呢

为什么不使用using语句呢

您正在用这样的异常处理为自己挖一个相当深的洞。捕获异常的一个硬规则是,在处理程序时恢复程序的状态。你没有。特别是,您忘记关闭文件。之后,当您再次尝试打开文件进行写入时,就会出现错误。不幸的是,异常消息是误导性的,它谈论的是另一个进程已经打开了文件。不是这样,是您的进程仍然打开了文件

针对这一失败有很多对策。您应该使用using语句来确保即使出现异常,文件也已关闭。您需要修复EndOfStream测试,它对文本文件不准确,使用while(true)循环,并在ReadLine()返回null时中断。这解决了原来的问题

但真正的解决办法是不要隐瞒一个令人不快的事实。当一个配置文件被破坏时,允许你的程序继续运行只会在它不能做你希望它做的事情时带来更多的麻烦。你无法分辨,因为你写在控制台上的信息已经从屏幕上滚了下来非常难以诊断

从此代码中删除try/catch。现在你要解决真正的问题了

您正在用这样的异常处理为自己挖一个相当深的洞。捕获异常的一个硬规则是,在处理程序时恢复程序的状态。你没有。特别是,您忘记关闭文件。之后,当您再次尝试打开文件进行写入时,就会出现错误。不幸的是,异常消息是误导性的,它谈论的是另一个进程已经打开了文件。不是这样,是您的进程仍然打开了文件

针对这一失败有很多对策。您应该使用using语句来确保即使出现异常,文件也已关闭。您需要修复EndOfStream测试,它对文本文件不准确,使用while(true)循环,并在ReadLine()返回null时中断。这解决了原来的问题

但真正的解决办法是不要隐瞒一个令人不快的事实。当一个配置文件被破坏时,允许你的程序继续运行只会在它不能做你希望它做的事情时带来更多的麻烦。你无法分辨,因为你写在控制台上的信息已经从屏幕上滚了下来非常难以诊断


从此代码中删除try/catch。现在您可以解决真正的问题了。

异常发生在哪一行?它发生在app.Run()之后。它说该文件无法访问,因为它正被另一个进程使用。但在问题中,您说它是“对象引用未设置为对象的实例”。@KendallFrey:请参阅我的答案。这是他的另一个例子。异常发生在哪一行?它发生在app.Run()之后。它说无法访问该文件,因为它正被另一个进程使用。但在问题中,您说它是“对象引用未设置为对象的实例”。@KendallFrey:请参阅