【问题标题】:Overwrite file only works once覆盖文件只工作一次
【发布时间】:2015-11-26 16:28:17
【问题描述】:

我有一个简单的程序,可以将文件和目录从一个地方复制到另一个地方。我设置了如果有任何异常(例如,如果访问路径被拒绝),它将创建一个带有错误的日志文件。

我有一个按钮,按下时会执行复制操作。我第一次按下按钮时一切正常,日志文件要么被创建,要么被相应的错误消息覆盖。

但是,如果我再次按下该按钮,文本文件不会被覆盖,而是会附加错误消息。如果我关闭程序并再次运行它,文件将在第一次按下按钮时被覆盖。任何想法将不胜感激。

target 是一个字符串文件路径,我从FolderBrowserDialog 获取并获取所选路径并将其设置为文本框。 loglist 只是一个简单的 List<string> 我用来存储复制过程中发生的任何异常的错误消息。

public partial class Form1 : Form
{

    static List<string> logList = new List<string>();

    public Form1()
    {
        InitializeComponent();
    }


    private static void CopyAll(DirectoryInfo source, DirectoryInfo target)
    {


        if (source.FullName.ToLower() == target.FullName.ToLower())
            return;

        if (Directory.Exists(target.FullName) == false)
        {
            Directory.CreateDirectory(target.FullName);
        }





        foreach (FileInfo fi in source.GetFiles())
        {
            try
            {
                fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
            }
            catch (Exception ex)
            {
                logList.Add(ex.Message);


            }


        }

        foreach (DirectoryInfo diSourceSub in source.GetDirectories())
        {
            DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSub.Name);
            CopyAll(diSourceSub, nextTargetSubDir);

        }



    }


    private void directoryPickerBtn1_Click(object sender, EventArgs e)
    {
        FolderBrowserDialog folderDialog = new FolderBrowserDialog();

        DialogResult folderResult = folderDialog.ShowDialog();
        if (folderResult == DialogResult.OK)
        {

            directoryTextbox1.Text = folderDialog.SelectedPath;
        }


    }

    private void directoryPickerBtn2_Click(object sender, EventArgs e)
    {
        FolderBrowserDialog folderDialog = new FolderBrowserDialog();

        DialogResult folderResult = folderDialog.ShowDialog();
        if (folderResult == DialogResult.OK)
        {
            directoryTextbox2.Text = folderDialog.SelectedPath;
        }
    }

    private void copyBtn_Click(object sender, EventArgs e)
    {
        string source = (directoryTextbox1.Text);
        string target = (directoryTextbox2.Text);



        DirectoryInfo dirSource = new DirectoryInfo(source);
        DirectoryInfo dirTarget = new DirectoryInfo(target);

        try
        {
            CopyAll(dirSource, dirTarget);

            if (logList.Count > 0)
            {
                using (StreamWriter sw = new StreamWriter(target + @"\log.txt", false))
                {
                    foreach (string error in logList)
                    {
                        sw.WriteLine(error);

                    }


                }
            }


            DialogResult result = MessageBox.Show("Copy Succeeded", "Success");
            if (result == DialogResult.OK)
            {
                string myPath = dirTarget.ToString();
                System.Diagnostics.Process prc = new System.Diagnostics.Process();
                prc.StartInfo.FileName = myPath;
                prc.Start();
            }
        }
        catch (Exception)
        {
            MessageBox.Show("Copy Failed", "Failed");
        }


    }
}

}

【问题讨论】:

  • 您展示的代码每次都会创建一个新文件。请显示所有相关代码,从按钮单击事件处理程序开始。
  • 我不确定该链接是否有帮助,@Mate。
  • 您是否删除了日志列表中的条目?还是文件实际上只是每次都被覆盖?
  • 这两种方法都可以正常工作,似乎问题出在您的 logList 上,您可能只将消息附加到它并且它始终包含所有消息。
  • 感谢大家这么快回答这个问题......所以是最好的!

标签: c# winforms filestream streamwriter overwrite


【解决方案1】:

作为@Reza Aghaeipointed out in comments,问题是你没有清除logList

文件每次都会重新创建,但每次单击“复制”按钮时,日志列表仍会包含上一次复制操作的结果。

所以开始新副本时需要清空列表:

private static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
    logList.Clear();

    // ...

【讨论】:

  • 谢谢!这么愚蠢的小东西要错过……我希望我能给每个人打上绿色的复选标记。只与上面的 James 一起使用,因为我将 clear 放在按钮中,而不是 CopyAll 方法(但我认为它仍然可以工作)..感谢您的帮助!
  • @CodeCaster 就是这样 +1 ;)
  • @Matt James 方法的问题在于it breaks SOLID。 (好吧,整个代码都可以,但那是另一回事)。假设您想在屏幕上显示日志列表并且将其写入文件,您将再次遇到同样的问题。在填充它的方法中清除它。这是该方法的责任。
  • hmm ..good point ...我在这一点上只是一个业余爱好者,所以我对 SOLID 不太熟悉..打算读一下...但这是有道理的。再次感谢!
  • @CodeCaster 故意的。记录自上次写入磁盘以来的日志,但很好。这就是我喜欢日志框架的原因!
【解决方案2】:

从您的代码看来,您从未清除过 logList,这意味着文件似乎正在附加,因为 logList 仍然包含所有旧条目。

如果您只想要该副本的相关条目,则需要清除副本之间的列表,无论是在开始复制之前还是在完成文件写入之后。

作为单独的方法会更好

    try
    {
        CopyAll(dirSource, dirTarget);

        SaveLog(target + @"\log.txt");

        ClearLog();
        //...
    }

    private void SaveLog(string filename)
    {
        if (logList.Count > 0)
        {
            FileStream fs = File.Open(target + @"\log.txt", FileMode.Create);
            using (StreamWriter sw = new StreamWriter(fs))
            {
                foreach (string error in logList)
                {
                    sw.WriteLine(error);
                }
            }
        }
    }

【讨论】:

  • 谢谢!愚蠢的小东西要错过......欣赏它!
  • @JamesBarrass 通常建议使用日志框架as you said,但对于小型应用程序,也请保持简单,System.IO.File.WriteAllLinesSystem.IO.File.AppendAllLines 可以使用simply。 +1 :)
  • 谁能给我一些关于日志框架的信息,也许是一些你自己喜欢使用的框架或者一个简单的框架,这样我就可以开始学习它们了?
  • @Matt 如果您想了解更多关于日志框架的信息,可以查看Log4NetNLogEnterprise Library Logging Application Block。但是对于一个小型应用程序,在您获得有关使用日志框架的必要知识之前,您可以继续使用自己的解决方案。您也可以使用System.IO.File.WriteAllLinesSystem.IO.File.AppendAllLines 使其更简单。
  • 感谢将研究这些框架以及 System.IO.File 类
猜你喜欢
  • 2012-02-06
  • 1970-01-01
  • 2015-06-18
  • 2018-01-26
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 2017-01-06
相关资源
最近更新 更多