The process cannot access the file because it is

.Net技术 码拜 7年前 (2014-12-28) 1205次浏览 0个评论
错误:The process cannot access the file because it is being used by another process.
问题描述:将五万左右的数据量,从数据库读取出来,按照一定格式要求打包成.txt文件(文件大小20M),生成文件后,将该文件打包成.zip文件,文件大小(5M左右)。大部分情况下,会打包成功,但有时会报上述错误,会生成一个0KB的.zip文件。打包代码如下:
Crc32 crc = new Crc32();
ZipOutputStream s = new ZipOutputStream(File.Create(zipName));
s.SetLevel(6); // 0 – store only to 9 – means best compression
string fileName = string.Empty;
foreach (string file in filenames)
{
//打开压缩文件 在此处会报上述错误
FileStream fs = File.OpenRead(file);byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fileName = Path.GetFileName(file);
ZipEntry entry = new ZipEntry(fileName);
entry.DateTime = DateTime.Now;
// set Size and the crc, because the information
// about the size and crc should be stored in the header
// if it is not set it is automatically written in the footer.
// (in this case size == crc == -1 in the header)
// Some ZIP programs have problems with zip files that don’t store
// the size and crc in the header.
entry.Size = fs.Length;
fs.Close();
crc.Reset();
crc.Update(buffer);
entry.Crc = crc.Value;
s.PutNextEntry(entry);
s.Write(buffer, 0, buffer.Length);
}
s.Finish();
s.Close();
—- 20分

中间出错的时候,后面的Close得不到执行,文件无法释放,下次打包必然会报那个错
在使用Stream的时候,建议这么用
using(var s = new XXXStream)
{
打包操作,using等同于try catch,会自动close掉流
}

—- 20分

using(ZipOutputStream s = new ZipOutputStream(File.Create(zipName)))
{
s.SetLevel(6); // 0 – store only to 9 – means best compression
string fileName = string.Empty;
foreach (string file in filenames)
{
//打开压缩文件 在此处会报上述错误
using(FileStream fs = File.OpenRead(file))
{
}
}

—- 20分

using 语句定义一个范围,在此范围的末尾将处理对象。
using (expression | type identifier = initializer) statement
其中:
expression 希望在退出 using 语句时调用 Dispose 的表达式。
type identifier 的类型。
identifier
type 类型的名称或标识符。定义一个以上 type 类型的 identifier 是可以的。在每一个 identifier = initializer 的前边都有一个逗号。 initializer 创建对象的表达式。
statement 嵌入的语句或要执行的语句。备注
在 using 语句中创建一个实例,确保退出 using 语句时在对象上调用 Dispose。当到达 using 语句的末尾,或者如果在语句结束之前引发异常并且控制离开语句块,都可以退出 using 语句。
实例化的对象必须实现 System.IDisposable 接口。
实现Dispose接口的对象,调用Dispose,是标记资源释放,告诉垃圾回收器可以进行回收。

调用Close后,最好Dispose一下。
使用using表达式Close、Dispose的活都给你干了

—- 10分

using块在编译后,在功能上等效于:
FileStream fs = null;
try
{
fs = File.OpenRead(file);
//fs操作
}
finally
{
if(fs != null) fs.Close();
}
.Net对using的封装会比这个更严密,好处就是:即使线程发生异常或者被abort,也会保证finally块始终得到执行
也许你会说,try中没有异常。但这也不代表就不会问题,比如:
是在双方通信过程中,由于打包时间过长或者其他原因,导致通信超时,对方关闭连接,你的线程里就可能抛异常退出,导致资源得不到释放

—- 10分

不用using也行,不过你需要把close放到foreach里面去,而不是连续执行open,而只执行一次close
s是个引用类型,它相当于文件的指针,或句柄,可以通过它操作文件,但是你不close,直接重新new,之前的并没有关闭,你这样写,其实只有最后一个文件执行了关闭操作
其他的如果不报错误,那也是因为恰好被GC回收了

—-

都是由于打开了没有CLOSE造成的。或者close的代码根本就没有执行。

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明The process cannot access the file because it is
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!