none
相同代码,2种调用方式,执行其中一种出现错误:“正由另一进程使用,因此该进程无法访问该文件。” RRS feed

  • 问题

  • 这个是一个有关文件读写的问题。

    问题场景描述:首先,将一个文件A复制为文件B,然后打开文件B,对其中的内容进行加工,将加工后的内容重新写会文件B,然后保存。

    现在出现一个很有意思的现象:假如将上面的处理流程代码,全部写在一个方法中,执行该方法,没有问题(代码段2处理方式)。

    然而,将“然后打开文件B,对其中的内容进行加工,将加工后的内容返回”这部分代码提炼为一个新的类,在调用该类的实例时,会出现“正由另一进程使用,因此该进程无法访问该文件。”错误(代码段1处理方式)。

    请问各位,为什么相同的的处理手法,写在同一个方法中时,没有问题。而将代码独立后,调用却出现错误?

    代码如下:

    private void btnOK_Click(object sender, EventArgs e)
            {
                this.errorProvider1.Clear();
    
                if (this.txtPath.Text.Length == 0 || !File.Exists(this.txtPath.Text))
                {
                    this.errorProvider1.SetError(this.txtPath,"路径无效");
                    return;
                }
                FileInfo OldFile = new FileInfo(this.txtPath.Text);
    
                string NewFilePath = Path.Combine(OldFile.DirectoryName, DateTime.Now.ToString("yyyyMMddHHmmss") + 
    
    OldFile.Name);
    
                FileInfo OldFile1 = OldFile.CopyTo(NewFilePath, false);
                OldFile1 = null;
    
                //代码段1,执行这段代码会出错
                AddRowLine NT = new AddRowLine(NewFilePath);
                StreamWriter sw = new StreamWriter(NewFilePath, false, Encoding.Default);
                sw.Write(NT.GetNeedtoWriteString());
                sw.Close();
    
                //代码段2,执行这段代码正常
                //string line;
                //StringBuilder sb = new StringBuilder();
    
                //System.IO.StreamReader file = new System.IO.StreamReader(NewFilePath, Encoding.Default);
                //while ((line = file.ReadLine()) != null)
                //{
                //    sb.AppendLine(line.Substring(line.IndexOf(".") + 1));
                //}
                //file.Close();
    
                //StreamWriter sw = new StreamWriter(NewFilePath, false, Encoding.Default);
                //sw.Write(sb.ToString());
                //sw.Close();
            }
    
     public class AddRowLine 
        {
            private string _fileName;
    
            public AddRowLine(string fileName)
            {
                this._fileName = fileName;
            }
            public string GetNeedtoWriteString()
            {
                if (!File.Exists(this._fileName))
                {
                    return string.Empty;
                }
                string line = string.Empty;
                StringBuilder sb = new StringBuilder();
                System.IO.StreamReader file = new System.IO.StreamReader(this._fileName, Encoding.Default);
                while ((line = file.ReadLine()) != null)
                {
                    sb.AppendLine(line.Substring(line.IndexOf(".") + 1));
                }
                file.Close();
                return sb.ToString();
            }
        }



    • 已编辑 jizhong 2012年8月16日 1:45 修改内容
    2012年8月16日 1:42

答案

  • 首先看看你的代码:

     //代码段1,执行这段代码会出错
    AddRowLine NT = new AddRowLine(NewFilePath);
    StreamWriter sw = new StreamWriter(NewFilePath, false, Encoding.Default);
    sw.Write(NT.GetNeedtoWriteString());
    sw.Close();
    看代码行第二行,你先对该文件申请了写权限,再看代码行第三行,你有再次申请读权限,因为该文件已被占用,并未被释放,当然申请不了。


    • 已标记为答案 jizhong 2012年8月16日 2:34
    2012年8月16日 2:15
  • 原因:你已经为StreamWriter指定了同一个文件进行写操作。因此StreamWriter等于独占了txt文件;但是你又调用了Reader方法,结果造成Reader和Writer抢占资源了。第一种注释掉的方法先读后写,故不存在问题。

    解决方法:

    namespace CSharp
    {
    
        using System;
        using System.IO;
        using System.Text;
    
        public class AddRowLine
        {
            private string _fileName;
    
            public AddRowLine(string fileName)
            {
                this._fileName = fileName;
            }
            public string GetNeedtoWriteString()
            {
                if (!File.Exists(this._fileName))
                {
                    return string.Empty;
                }
                string line = string.Empty;
                StringBuilder sb = new StringBuilder();
                System.IO.StreamReader file = new System.IO.StreamReader(this._fileName, Encoding.Default);
                while ((line = file.ReadLine()) != null)
                {
                    sb.AppendLine(line.Substring(line.IndexOf(".") + 1));
                }
                file.Close();
                return sb.ToString();
            }
        }
    
        public class ArrayClass
        {
            static void Main()
            {
                AddRowLine NT = new AddRowLine("c:\\try.txt");
                string s = NT.GetNeedtoWriteString();
                StreamWriter sw = new StreamWriter("c:\\try.txt", false, Encoding.Default);
                sw.Write(s);
                sw.Close();
    
            }
        }
    
    }

    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    • 已标记为答案 jizhong 2012年8月16日 2:34
    2012年8月16日 2:21
    版主

全部回复

  • 首先看看你的代码:

     //代码段1,执行这段代码会出错
    AddRowLine NT = new AddRowLine(NewFilePath);
    StreamWriter sw = new StreamWriter(NewFilePath, false, Encoding.Default);
    sw.Write(NT.GetNeedtoWriteString());
    sw.Close();
    看代码行第二行,你先对该文件申请了写权限,再看代码行第三行,你有再次申请读权限,因为该文件已被占用,并未被释放,当然申请不了。


    • 已标记为答案 jizhong 2012年8月16日 2:34
    2012年8月16日 2:15
  • 原因:你已经为StreamWriter指定了同一个文件进行写操作。因此StreamWriter等于独占了txt文件;但是你又调用了Reader方法,结果造成Reader和Writer抢占资源了。第一种注释掉的方法先读后写,故不存在问题。

    解决方法:

    namespace CSharp
    {
    
        using System;
        using System.IO;
        using System.Text;
    
        public class AddRowLine
        {
            private string _fileName;
    
            public AddRowLine(string fileName)
            {
                this._fileName = fileName;
            }
            public string GetNeedtoWriteString()
            {
                if (!File.Exists(this._fileName))
                {
                    return string.Empty;
                }
                string line = string.Empty;
                StringBuilder sb = new StringBuilder();
                System.IO.StreamReader file = new System.IO.StreamReader(this._fileName, Encoding.Default);
                while ((line = file.ReadLine()) != null)
                {
                    sb.AppendLine(line.Substring(line.IndexOf(".") + 1));
                }
                file.Close();
                return sb.ToString();
            }
        }
    
        public class ArrayClass
        {
            static void Main()
            {
                AddRowLine NT = new AddRowLine("c:\\try.txt");
                string s = NT.GetNeedtoWriteString();
                StreamWriter sw = new StreamWriter("c:\\try.txt", false, Encoding.Default);
                sw.Write(s);
                sw.Close();
    
            }
        }
    
    }

    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    • 已标记为答案 jizhong 2012年8月16日 2:34
    2012年8月16日 2:21
    版主
  • 说的对,没有看清代码,⊙﹏⊙b汗。
    2012年8月16日 2:35
  • 感谢耐心回复。我还以为是什么**机制呢,原来是没有看清代码。抱歉!

    只要将代码1的其中语句调整即可:

    //代码段1
    AddRowLine NT = new AddRowLine(NewFilePath);
    string s = NT.GetNeedtoWriteString();
    StreamWriter sw = new StreamWriter(NewFilePath, false, Encoding.Default);
    sw.Write(s);
    sw.Close();


    • 已编辑 jizhong 2012年8月16日 2:37 调整格式
    2012年8月16日 2:37
  • 感谢耐心回复。我还以为是什么**机制呢,原来是没有看清代码。抱歉!

    只要将代码1的其中语句调整即可:

    //代码段1
    AddRowLine NT = new AddRowLine(NewFilePath);
    string s = NT.GetNeedtoWriteString();
    StreamWriter sw = new StreamWriter(NewFilePath, false, Encoding.Default);
    sw.Write(s);
    sw.Close();



    是的,请不要标记我为答案哟:)

    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年8月16日 4:37
    版主