2016-06-10 2 views
0

Ich versuche, ein Bild in der Größe zu ändern. Erstens ich das Bild in einen Byte-Array gelesen, es im Speicher skalieren und es wieder auf die gleiche Datei schreiben:Wie kann ich eine Datei ersetzen, die durch denselben Prozess gesperrt ist?

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

jedoch in der Regel die folgende Fehlermeldung erhalten:

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

Warum ist das? Ich hätte angenommen, dass File.ReadAllBytes() die Datei automatisch schließen würde?

Im Prozess-Explorer werden keine Datei-Handles oder Sperren für die Datei angezeigt (was seltsam erscheint).

Auch wenn ich einige Verzögerungen in einer while-Schleife hinzufügen, wird die Schleife nie abgeschlossen ist, wird die Datei impliziert dauerhaft gesperrt:

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

EDIT: Aktualisiert den vollständigen Code zu erhalten und Mechaniker Antwort in meinen Code eingebaut oben, um meine Implementierung zu zeigen.

+1

Es zu ändern Haben Sie etwas anderes in Ihrem Programm, das die Datei berühren könnte, zum Beispiel eine Bitmap.FromStream (imagePathAndFilename) irgendwo in Ihrem Code? Dieser Code wird einfach nicht die *** Ursache *** des Problems sein, es kann die Auswirkungen des Problems leiden, aber es verursacht es nicht. –

+1

Per [die Dokumente] (https://msdn.microsoft.com/en-us/library/system.io.file.readallbytes (v = vs.110) .aspx) und [die Referenzquelle] (http://referencesource.microsoft.com/#mscorlib/system/io/file.cs,4b24188ee62795aa), tut es. Ihr Problem ist wahrscheinlich woanders. –

+0

Es gibt keinen Code, der Dateien liest. Der Code zum Ändern der Größe des Bilds erfolgt direkt im Byte-Array von photoBytes. – NickG

Antwort

1

Anstatt alle Bytes zu lesen, könnten Sie einen FileStream verwenden und die Datei behalten? Sorry, wenn dieser Code nicht exakt ist, und Sie können die Zugriffs Bytes trimmen müssen, wenn Ihre Dateilänge der fs.SetLength Funktion

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 verkürzt werden: die SetLength hinzugefügt, um den Strom Größe

+0

Ich würde vorsichtig sein, wenn die neue Datei kleiner als die alte Datei ist, werden Sie am Ende Junk-Bytes haben –

+0

Danke!Eine Bearbeitung hinzugefügt, um die Größe des FileStreams auf die Länge des manipulierten Puffers zurückzusetzen - obwohl ich dies tatsächlich berechnen würde, da Sie wahrscheinlich trimmen werden und ohne das Erstellen eines separaten Puffers wollen Sie verfolgen, wie viele Bytes die Datei tatsächlich ist – Mechanic

+0

@Mechanic Danke, aber wenn ich nicht einen Fehler bei der Implementierung gemacht habe (siehe meinen aktualisierten Code in der Frage), behebt das das Problem nicht für mich. Ich bekomme immer noch die Ausnahme "Datei in Benutzung". – NickG

Verwandte Themen