[求助]FileStream 导致的文件被占用问题

jzdriver 2015-01-26 09:43:25
一个文件发送端,一个文件接收端,
现在文件发送与接收都貌似正常,
问题出现在:
当接收端程序在运行时=======》接收创建的文件大小已经正常,但双击时,提示文件被其它程序占用,无法打开。
只要把接收端程序关闭=======》接收到的文件就一切OK正常。

已经尝试在接收端加了各种关闭。
也在FileStream中加了 using

现在没办法了



发送端关键代码:

                NetworkStream ns = tcpClientObj.GetStream();

FileStream fs = new FileStream(@"D:\sogou.exe", FileMode.Open);
int size = 0;//初始化读取的流量为0
long len = 0;//初始化已经读取的流量
while (len < fs.Length)
{
byte[] buffer = new byte[512];
size = fs.Read(buffer, 0, buffer.Length);
ns.Write(buffer, 0, size);
len += size;
//Pro((long)len);
}
fs.Flush();
ns.Flush();



接收端关键代码:


int size = 0;
int len = 0;
NetworkStream ns = clientMem[Thread.CurrentThread.Name].GetStream();

if (ns != null)
{

string fileSavePath = "123.exe";
using (FileStream fs = new FileStream(fileSavePath, FileMode.Create, FileAccess.Write))
{

byte[] buffer = new byte[512];


while ((size = ns.Read(buffer, 0, buffer.Length)) > 0 || ns.DataAvailable == false)
{
fs.Write(buffer, 0, size);
len += size;
}
fs.Flush();
fs.Dispose();
fs.Close();


ns.Flush();
ns.Dispose();
ns.Close();
Thread.CurrentThread.Abort(); //(接收端是多线程,其实感觉没必要关闭,没办法了,只能把所有用到的都关闭,但还是提示占用)
return;
}
}

...全文
1290 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
asia217 2015-01-30
  • 打赏
  • 举报
回复 1
亲,为什么那么复杂
File.WriteAllBytes(path, bytes);
不可以吗?
jzdriver 2015-01-30
  • 打赏
  • 举报
回复
先谢谢楼上各位的帮助,问题得到解决了。下面把关键代码分别帖出来。 -----发送端关键代码

/// <summary>
/// 发送文件
/// </summary>
/// <param name="path">文件路径</param>
        public void File(string path)
        {
            try
            {
                TcpClient tcpC = new TcpClient();
                tcpC.Connect(IPAddress.Parse(服务器IP),服务器端口);
                NetworkStream netS = tcpC.GetStream();

                string sFileName = Path.GetFileName(path);

                using (NetworkStream ns = netS)
                {

                    FileStream fs = new FileStream(path, FileMode.Open);
                    int size = 0;//初始化读取的流量为0   
                    long len = 0;//初始化已经读取的流量   
                    while (len < fs.Length)
                    {
                        byte[] buffer = new byte[512];
                        size = fs.Read(buffer, 0, buffer.Length);
                        ns.Write(buffer, 0, size);
                        len += size;
                      }
                    fs.Flush();
                    ns.Flush();
                    fs.Close();
                    ns.Close();
                }
                tcpC.Close();
                netS.Dispose();
                netS.Close();
            }
            catch
            {
            }
            finally
            {
            }
        }
-----------接收端代码

                    NetworkStream ns = clientMem[Thread.CurrentThread.Name].GetStream();  //获取属于这个线程的连接

                        
                        if (ns != null)
                        {
                            string fileSavePath = "Files//" + sNewFileName;//获得用户保存文件的路径
                            //fileSavePath = "123.exe";
                            using (FileStream fs = new FileStream(fileSavePath, FileMode.Create, FileAccess.Write))
                            {
                                byte[] buffer = new byte[512];
                                while ((size = ns.Read(buffer, 0, buffer.Length)) > 0 || ns.DataAvailable == true)
                                {
                                    fs.Write(buffer, 0, size);
                                    len += size;
                                }
                                fs.Flush();
                                fs.Dispose();
                                fs.Close();
                            }
                            
                  
其实,核心解决,就在于原来发送端的连接没有断开,结果接收端一直认为还有数据,所以就一直在接收而占用。
jzdriver 2015-01-30
  • 打赏
  • 举报
回复
引用 20 楼 wyd1520 的回复:


  private FileStream OpenOrCreate()
        {
            FileStream fs = new FileStream(
                _tmpFilePath, //_filePath,
                FileMode.OpenOrCreate,
                FileAccess.Write,
                FileShare.None,
                _partSize * 10);
            return fs;
        }



            using (FileStream fs = OpenOrCreate())
                    {
                        fs.Position = index * _partSize;
                        fs.Write(buffer, 0, buffer.Length);
                        fs.Close(); 这里要记得Close
                    }


亲,问题解决了,我楼下放代码
jzdriver 2015-01-26
  • 打赏
  • 举报
回复
引用 17 楼 Z65443344 的回复:
我觉得你还是先把客户端,服务端,线程什么的放一边 把你服务端读文件的代码粘过来,客户端从文件夹1里读文件然后写入文件夹2里,这些代码直接放主线程里 然后测试运行,看执行完还会不会占用
刚才把接收端.EXE 放到其它计算机上,也是一样结果, 好的,我一会儿就写一个DEMO程序。。 试试吧。 过一会儿回来汇报战果
於黾 2015-01-26
  • 打赏
  • 举报
回复
我觉得你还是先把客户端,服务端,线程什么的放一边 把你服务端读文件的代码粘过来,客户端从文件夹1里读文件然后写入文件夹2里,这些代码直接放主线程里 然后测试运行,看执行完还会不会占用
jzdriver 2015-01-26
  • 打赏
  • 举报
回复
引用 14 楼 Z65443344 的回复:
还有,把return拿到using外面试试,让using执行完.
最新战况: 把return移掉后,,还是一样的结果,, 尝试改这个123.exe 文件名,还是提示被 vshost-clr2.exe 占用 妹的!!逼我,,,要不,我TM换台电脑吧
jzdriver 2015-01-26
  • 打赏
  • 举报
回复
引用 13 楼 Z65443344 的回复:
你确定文件已经接收完成了,而不是接收了一半你就想给它改名?
确定文件传输完成,,我试着把这个被占用的文件,复制一份,然后改名,, 这个文件是完整的EXE 并可执行 我试一下return移出去。回来马上汇报结果
於黾 2015-01-26
  • 打赏
  • 举报
回复
还有,把return拿到using外面试试,让using执行完.
於黾 2015-01-26
  • 打赏
  • 举报
回复
你确定文件已经接收完成了,而不是接收了一半你就想给它改名?
jzdriver 2015-01-26
  • 打赏
  • 举报
回复
引用 11 楼 wyd1520 的回复:
[quote=引用 8 楼 jzdriver 的回复:] [quote=引用 4 楼 Z65443344 的回复:] 另外看你的代码,即使出错,顶多也就是通信没有释放,跟文件没啥关系,检查一下是否有其他地方也使用了文件,目测不是这段代码的问题
这个123.exe 是我每次都会在生成目录下,手动删除的。是由接收端自己创建的文件,所以除了这个程序外,其它程序是不可能占用的。[/quote] 有没有安装360或刹毒软件?要有的话我只能呵呵了,之前我也发生过类拟的,远程传输,也是用exe做保存。根楼主一样传过去发现被占用。文件流肯定是关了,但还是占用,后来想想是不是360的问题,于是把360关闭完全退出。。尽然可以了。 楼主你可以做成这样 做个临时保存文件像这样 123.exe.download 这样的 刹毒软件是不会去查这样的扩展名, 等流全接收完后再用Move或改名方式把这个文件变成123.exe就不会提示被占用了[/quote] 按照您的思路试了一下,关闭杀毒软件,也把保存的文件名改为 123.ttmp ,但当我未关闭接收端的情况下, 对这个文件进行改名, 它提示【操作无法完成,因为文件已经在vshost-clr2.exe中打开】 明显还是VS在占用。
本拉灯 2015-01-26
  • 打赏
  • 举报
回复
引用 8 楼 jzdriver 的回复:
[quote=引用 4 楼 Z65443344 的回复:] 另外看你的代码,即使出错,顶多也就是通信没有释放,跟文件没啥关系,检查一下是否有其他地方也使用了文件,目测不是这段代码的问题
这个123.exe 是我每次都会在生成目录下,手动删除的。是由接收端自己创建的文件,所以除了这个程序外,其它程序是不可能占用的。[/quote] 有没有安装360或刹毒软件?要有的话我只能呵呵了,之前我也发生过类拟的,远程传输,也是用exe做保存。根楼主一样传过去发现被占用。文件流肯定是关了,但还是占用,后来想想是不是360的问题,于是把360关闭完全退出。。尽然可以了。 楼主你可以做成这样 做个临时保存文件像这样 123.exe.download 这样的 刹毒软件是不会去查这样的扩展名, 等流全接收完后再用Move或改名方式把这个文件变成123.exe就不会提示被占用了
jzdriver 2015-01-26
  • 打赏
  • 举报
回复
引用 9 楼 Z65443344 的回复:
我什么时候说文件是被其他程序占用了 我是让你找找你的程序里是否还有其他代码去使用它 比如你是否接收到文件后又执行了move,重命名等操作
木有其它地方,,所有关于接收,然后创建,然后写入,,,,全在这一个地方!
於黾 2015-01-26
  • 打赏
  • 举报
回复
我什么时候说文件是被其他程序占用了 我是让你找找你的程序里是否还有其他代码去使用它 比如你是否接收到文件后又执行了move,重命名等操作
jzdriver 2015-01-26
  • 打赏
  • 举报
回复
引用 4 楼 Z65443344 的回复:
另外看你的代码,即使出错,顶多也就是通信没有释放,跟文件没啥关系,检查一下是否有其他地方也使用了文件,目测不是这段代码的问题
这个123.exe 是我每次都会在生成目录下,手动删除的。是由接收端自己创建的文件,所以除了这个程序外,其它程序是不可能占用的。
jzdriver 2015-01-26
  • 打赏
  • 举报
回复
引用 4 楼 Z65443344 的回复:
Thread.CurrentThread.Abort(); 不用加这句话,你执行到return,线程也就自己退出了 如果文件被占用,说明有对象没有释放,这跟你线程是否正在运行还是已经退出没有关系 已经使用了using,不必再加close和dispose 而且你的NetworkStream对象也应该套一个using包起来,而不是在using里面再使用close 因为使用using的时候即使出错也可以释放,而如果using和手动释放混用,一旦出错而你没有加try,catch,那么using的部分可以释放,而手动释放的代码可能得不到执行 另外看你的代码,即使出错,顶多也就是通信没有释放,跟文件没啥关系,检查一下是否有其他地方也使用了文件,目测不是这段代码的问题
亲,首先谢谢你这么认真的回复。 刚才听了您的建议,把接收端做了几个操作,代码改动后如下

                            string fileSavePath = "Files//" + sNewFileName;//获得用户保存文件的路径
                            fileSavePath = "123.exe";
                            using (FileStream fs = new FileStream(fileSavePath, FileMode.Create, FileAccess.Write))
                            {
                                NetworkStream ns = clientMem[Thread.CurrentThread.Name].GetStream();
                                byte[] buffer = new byte[512];


                                while ((size = ns.Read(buffer, 0, buffer.Length)) > 0 || ns.DataAvailable == false)
                                {
                                    fs.Write(buffer, 0, size);
                                    len += size;
                                }
                                fs.Flush();
                                ns.Flush();

                                //fs.Dispose();
                                //fs.Close();

                                //ns.Dispose();
                                //ns.Close();
                                return;

便结果依旧,依然是 接收端不关闭,文件就被占用,只要接收端EXE一关闭 传过来这个文件就好用。
jzdriver 2015-01-26
  • 打赏
  • 举报
回复
引用 3 楼 wyd1520 的回复:
Thread.CurrentThread.Abort(); 加这个反而会造成Fs无法正常关闭。也无法进行内存回收。。。
这是没办法时做的,,之前是没有加这个命令的,,结果还是被占用。
於黾 2015-01-26
  • 打赏
  • 举报
回复
引用 3 楼 wyd1520 的回复:
Thread.CurrentThread.Abort(); 加这个反而会造成Fs无法正常关闭。也无法进行内存回收。。。
+1 应该让线程自己退出并执行后续的逻辑,你手动强制关闭,可能造成有些异步调用无法执行
於黾 2015-01-26
  • 打赏
  • 举报
回复
Thread.CurrentThread.Abort(); 不用加这句话,你执行到return,线程也就自己退出了 如果文件被占用,说明有对象没有释放,这跟你线程是否正在运行还是已经退出没有关系 已经使用了using,不必再加close和dispose 而且你的NetworkStream对象也应该套一个using包起来,而不是在using里面再使用close 因为使用using的时候即使出错也可以释放,而如果using和手动释放混用,一旦出错而你没有加try,catch,那么using的部分可以释放,而手动释放的代码可能得不到执行 另外看你的代码,即使出错,顶多也就是通信没有释放,跟文件没啥关系,检查一下是否有其他地方也使用了文件,目测不是这段代码的问题
本拉灯 2015-01-26
  • 打赏
  • 举报
回复
Thread.CurrentThread.Abort(); 加这个反而会造成Fs无法正常关闭。也无法进行内存回收。。。
jzdriver 2015-01-26
  • 打赏
  • 举报
回复
引用 1 楼 duanzi_peng 的回复:
确定客户端的线程 彻底关闭了么
文件发送端的线程,我没有加关闭代码,但我试着关闭过 发送端的程序,还是提示被占用。 说明一下: 文件是被 接收端占用。 而在接收端,我加了Thread.CurrentThread.Abort(); 也没起作用啊
加载更多回复(3)

110,571

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧