2016-06-10 71 views
0

我正在嘗試調整圖像大小。首先,我讀的圖像轉換爲字節數組,調整它在內存中,並把它寫回同一個文件:如何替換被同一進程鎖定的文件?

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); 
      } 
     } 
    } 

但是通常出現以下錯誤:

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

這是爲什麼?我會假定File.ReadAllBytes()會自動關閉文件?

Process Explorer中的文件沒有文件句柄或鎖(這看起來很奇怪)。

即使我在while循環增加一些延遲,循環永遠不會結束,這意味着該文件將被永久鎖定:

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

編輯:更新,以顯示完整的代碼並納入技工的回答了我的代碼上面來展示我的實現。

+1

它那麼,你的程序中是否還有其他可能會觸及該文件的內容,例如在代碼中的某個位置存在「Bitmap.FromStream(imagePathAndFilename)」?這段代碼根本不會成爲問題的原因,它可能會受到問題的影響,但不會導致問題。 –

+1

每[文檔](https://msdn.microsoft.com/en-us/library/system.io.file.readallbytes(v = vs.110).aspx)和[參考源](http:///referencesource.microsoft.com/#mscorlib/system/io/file.cs,4b24188ee62795aa),它的確如此。你的問題可能在其他地方。 –

+0

雖然沒有任何讀取文件的代碼。調整圖像大小的代碼直接在photoBytes字節數組上。 – NickG

回答

1

而不是讀取所有字節你可以使用FileStream並保持文件上的保留?很抱歉,如果這個代碼是不準確的,你可能需要,如果你的文件長度縮短使用fs.SetLength功能

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); 
} 

編輯修剪訪問字節:增加了SetLength改變流大小

+0

我會小心這個,如果新文件比舊文件小,你會在最後有垃圾字節 –

+0

謝謝!添加了一個編輯器,將FileStream的大小重置爲被操縱的緩衝區的長度 - 儘管我實際上會計算這個值,因爲您可能會修剪並且不創建單獨的緩衝區,您將需要跟蹤該文件實際上有多少字節 – Mechanic

+0

@Mechanic謝謝,但除非我犯了一個錯誤實現這個(請參閱我的問題中更新的代碼),那麼這並不能解決我的問題。我仍然收到「正在使用的文件」異常。 – NickG

相關問題