2016-06-10 4 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()가 파일을 자동으로 닫을 것이라고 추정했을 것이다.

프로세스 탐색기에서 파일에 대한 파일 핸들이나 잠금이 표시되지 않습니다 (이상하게 보임). 전체 코드를 표시하도록 업데이트 내 코드에 정비공의 답변을 통합 :

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

편집 :

은 내가 while 루프에서 약간의 지연을 추가하더라도, 루프 파일을 의미하는 것은 영구적으로 고정되지 않은이 완료 결코 내 구현을 보여주는 위의.

+1

그것을 그렇다면, 프로그램의 다른 부분, 예를 들어 코드의 'Bitmap.FromStream (imagePathAndFilename)'과 같은 파일을 만질 수 있습니까? 이 코드는 문제의 *** 원인 ***이되지는 않지만 문제의 영향을받을 수는 있지만 문제의 원인이 아닙니다. –

+1

[docs] (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

관련 문제