简体   繁体   中英

How can I replace a file which is locked by the same process?

I'm trying to resize an image. Firstly I read the image into a byte array, resize it in memory and write it back to the same file:

    public static void CropAndResizeImage(EntryImage image, int left, int top, int right, int bottom)
    {
        Size newSize = new Size();
        string imagePathAndFilename = HttpContext.Current.Server.MapPath(image.URL);

        //byte[] photoBytes = File.ReadAllBytes(imagePathAndFilename);
        using (FileStream fs = new FileStream(imagePathAndFilename, FileMode.Open, FileAccess.ReadWrite))
        {
            fs.Position = 0;
            var photoBytes = new byte[fs.Length];
            int read = fs.Read(photoBytes, 0, photoBytes.Length);

            // Process photo and resize
            using (MemoryStream inStream = new MemoryStream(photoBytes))
            using (MemoryStream outStream = new MemoryStream())
            {
                using (ImageFactory imageFactory = new ImageFactory(preserveExifData: true))// Initialize the ImageFactory using the overload to preserve EXIF metadata.
                {

                    ISupportedImageFormat format = new JpegFormat { Quality = 75 }; // Format is automatically detected though can be changed.
                    Size maxSize = new Size(1024, 1024);
                    ResizeLayer layer = new ResizeLayer(maxSize, upscale: false, resizeMode: ResizeMode.Max);
                    layer.Upscale = false;

                    // Load, resize, set the format and quality and save an image.
                    imageFactory.Load(inStream)
                                .Crop(new CropLayer(left, top, right - left, bottom - top, CropMode.Pixels)) // Crop is relative to image edge, not absolute coords.
                                .Resize(layer)
                                .Format(format)
                                .Save(outStream);

                    newSize.Width = imageFactory.Image.Width;
                    newSize.Height = imageFactory.Image.Height;
                }

                // Write back to the same file
                fs.Position = 0;
                fs.SetLength(photoBytes.Length);
                fs.Write(photoBytes, 0, photoBytes.Length);
            }
        }
    }

However usually get the following error:

The process cannot access the file: 'C:\\folder\\image.jpg' because it is being used by another process.

Why is this? I would have presumed that File.ReadAllBytes() would close the file automatically?

No file handles or locks are shown for the file in Process Explorer (which seems odd).

Even if I add some delays in a while loop, the loop never completes, implying the file is permanently locked:

bool saved = false;
while (!saved)
{
    try
    {
        SaveImageToFile(imagePathAndFilename, outStream);
        saved = true;
    }
    catch (IOException ex)
    {
        System.Threading.Thread.Sleep(1000);
    }
}

EDIT: Updated to show the full code and incorporated Mechanic's answer into my code above to show my implementation.

Instead of Reading all Bytes could you use a FileStream and maintain a hold on the file? Sorry if this code isn't exact, and you may need to trim the access bytes if your file length shortens using the fs.SetLength function

using (FileStream fs = new FileStream(imagePathAndFilename, FileMode.Open, FileAccess.ReadWrite))   
{
    fs.Position = 0;
    var buffer = new byte[fs.Length];
    int read = fs.Read(buffer, 0, buffer.Length);

    // Manipulate bytes here

    fs.Position = 0;
    fs.SetLength(buffer.Length);
    fs.Write(buffer, 0, buffer.Length);
}

EDIT: Added the SetLength to change the stream size

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM