C#:为什么我得到“进程无法访问文件*因为正被另一个进程使用”这段代码?

时间:2010-03-19 18:41:57

标签: c# image-processing

我正在尝试将文件夹中的bmp文件转换为jpg,然后删除旧文件。代码工作正常,但它不能删除bmp。

DirectoryInfo di = new DirectoryInfo(args[0]);
FileInfo[] files = di.GetFiles("*.bmp");
foreach (FileInfo file in files)
{
    string newFile = file.FullName.Replace("bmp", "jpg");
    Bitmap bm = (Bitmap)Image.FromFile(file.FullName);
    bm.Save(newFile, ImageFormat.Jpeg);
}
for (int i = 0; i < files.Length; i++)
    files[i].Delete();

文件未被其他程序/进程使用,如错误所示,所以我假设问题在这里。但对我来说,代码看起来很好,因为我按顺序执行所有操作。这也是程序的全部内容,因此错误不会由其他地方的代码引起。

6 个答案:

答案 0 :(得分:5)

尝试使用using包裹位图:

using (Bitmap bm = (Bitmap)Image.FromFile(file.FullName))
{
    bm.Save(newFile, ImageFormat.Jpeg);
}

这将在保存位图对象之后对其进行处理。

答案 1 :(得分:1)

public static Image LoadImage( string fileFullName )
{
    Stream fileStream = File.OpenRead( fileFullName );
    Image image       = Image.FromStream( fileStream );

    // PropertyItems seem to get lost when fileStream is closed to quickly (?); perhaps
    // this is the reason Microsoft didn't want to close it in the first place.
    PropertyItem[] items = image.PropertyItems;

    fileStream.Close();

    foreach ( PropertyItem item in items )
    {
        image.SetPropertyItem( item );
    }

    return image;
}

答案 2 :(得分:0)

Bitmap对象封装了一个文件句柄。调用Save后,必须在位图对象上调用Dispose。

您遇到了问题,因为那些Bitmap对象尚未被垃圾回收。

答案 3 :(得分:0)

在bm.Save之后,你应该释放你的位图对象。尝试在bm.Dispose();

之后添加bm.Save(newFile, ImageFormat.Jpeg)

答案 4 :(得分:0)

来自MSDN

  

在发布之前始终调用Dispose   您对图像的最后一次引用。   否则,它正在使用的资源   直到垃圾才会被释放   collector调用Image对象   最终确定方法。

我不确定在这之后您对这些图像做了什么,但有时您还需要将图像引用设置为null然后调用GC.Collect()。

答案 5 :(得分:0)

使用Image.FromFile解决问题的最佳方法是将文件句柄保持打开状态,而不是使用Image.FromStream。

using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
   using (Image original = Image.FromStream(fs))
   {
     ...

使用显式的Dispose(),using()语句或将值设置为null并不能解决问题,直到垃圾收集发生(并且强制执行垃圾收集通常是一个坏主意)。