C #: Why am I getting "the process cannot access the file * because it is being used by another process" with this code?

I am trying to convert BMP files to a folder in jpg and then delete old files. The code works fine, except that it cannot remove 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(); 

These files are not used by another program / process, as the error indicates, so I assume the problem is here. But for me, the code seems beautiful, as I do everything sequentially. This is all there is in the program, so the error cannot be caused by code elsewhere.

+4
source share
6 answers

Try cropping bitmaps with using :

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

This will destroy the bitmap objects immediately after they are saved.

+5
source
 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; } 
+1
source

A Bitmap object encapsulates a file descriptor. You must call Dispose on the raster object after calling Save.

You see the problem because those Bitmap objects have not yet been garbage collected.

0
source

After bm.Save you should free your raster object. Try adding bm.Dispose(); after bm.Save(newFile, ImageFormat.Jpeg)

0
source

From MSDN :

Always invoke Dispose before releasing your last image link. Otherwise, the resources that it uses will not be freed until the garbage collector calls the Image object Method of completion.

I'm not sure what you do with these images after that, but sometimes you also need to set the image link to zero and then call GC.Collect ().

0
source

The best way to solve the problem with Image.FromFile in which it leaves open file descriptors is to use Image.FromStream.

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

Using the explicit Dispose () operator, using (), or setting it to null does not solve the problem until garbage collection occurs (and forced garbage collection is usually a bad idea).

0
source

Source: https://habr.com/ru/post/1304598/


All Articles