gdi+ - Image.FromFile कभी-कभी फ़ाइल संभाल को क्यों खोलता है?




filehandle (6)

Image.FromFile फ़ाइल संभाल तब तक खुला रहता है जब तक छवि का निपटारा नहीं किया जाता है। MSDN :

"जब तक छवि का निपटारा नहीं किया जाता है तब तक फाइल लॉक रहती है।"

Image.FromStream का उपयोग करें, और आपको समस्या नहीं होगी।

using(var fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
    return Image.FromStream(fs);
}

संपादित करें: (एक वर्ष और थोड़ी देर बाद)

उपर्युक्त कोड खतरनाक है क्योंकि यह अप्रत्याशित है, कुछ समय पर (फाइलस्ट्रीम बंद करने के बाद) आप डर सकते हैं "जीडीआई + में एक सामान्य त्रुटि हुई" । मैं इसे संशोधित करूंगा:

Image tmpImage;
Bitmap returnImage;

using(var fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
    tmpImage = Image.FromStream(fs);
    returnImage = new Bitmap(tmpImage);
    tmpImage.Dispose();
}

return returnImage;

मैं एक एएसपी.नेट आवेदन में .NET में जीडीआई + में बहुत सारी छवि प्रसंस्करण कर रहा हूं।

मुझे अक्सर यह पता चलता है कि Image.FromFile () एक फ़ाइल हैंडल खोल रहा है।

ऐसा क्यों है? फाइल हैंडल बनाए रखने के बिना छवि खोलने का सबसे अच्छा तरीका क्या है।

  • एनबी: मैं छवि वस्तु को चारों ओर झूठ बोलने की तरह बेवकूफ कुछ नहीं कर रहा हूं - और यहां तक ​​कि अगर मैं था तो मैं फ़ाइल संभाल सक्रिय होने की उम्मीद नहीं करता

जैसा कि ऊपर बताया गया है, माइक्रोसॉफ्ट के काम के आसपास कई छवियों को लोड करने के बाद एक जीडीआई + त्रुटि का कारण बनता है। स्टीवन द्वारा ऊपर वर्णित मेरे लिए वीबी समाधान है

picTemp.Image = Image.FromStream(New System.IO.MemoryStream(My.Computer.FileSystem.ReadAllBytes(strFl)))

मुझे कचरा कलेक्टर में अपनी अंगुली को इंगित करना होगा। यदि आप कचरा संग्रह की दया पर हैं तो इसे चारों ओर छोड़ना वास्तव में मुद्दा नहीं है।

इस लड़के की एक ही complaint ... और उसे फ़ाइल से सीधे लोड करने के बजाय फ़ाइलस्ट्रीम ऑब्जेक्ट का उपयोग करने का काम मिला।

public static Image LoadImageFromFile(string fileName)
{
    Image theImage = null;

    fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
    {
        byte[] img;
        img = new byte[fileStream.Length];
        fileStream.Read(img, 0, img.Length);
        fileStream.Close();
        theImage = Image.FromStream(new MemoryStream(img));
        img = null;
    }

...

यह एक पूर्ण हैक की तरह लगता है ...


मुझे बस एक ही समस्या का सामना करना पड़ा, जहां मैं एकाधिक, सिंगल-पेज टीआईएफएफ फ़ाइलों को एक मल्टीपार्ट टीआईएफएफ छवि में विलय करने की कोशिश कर रहा था। मुझे Image.Save() और 'Image.SaveAdd () `: https://msdn.microsoft.com/en-us/library/windows/desktop/ms533839%28v=vs.85%29.aspx का उपयोग करने की आवश्यकता है

मेरे मामले में समाधान प्रत्येक छवियों के लिए "डिस्प्ले ()" को कॉल करना था, जैसे ही मैं उनके साथ किया गया था:

' Iterate through each single-page source .tiff file
Dim initialTiff As System.Drawing.Image = Nothing
For Each filePath As String In srcFilePaths

    Using fs As System.IO.FileStream = File.Open(filePath, FileMode.Open, FileAccess.Read)
        If initialTiff Is Nothing Then
            ' ... Save 1st page of multi-part .TIFF
            initialTiff = Image.FromStream(fs)
            encoderParams.Param(0) = New EncoderParameter(Encoder.Compression, EncoderValue.CompressionCCITT4)
            encoderParams.Param(1) = New EncoderParameter(Encoder.SaveFlag, EncoderValue.MultiFrame)
            initialTiff.Save(outputFilePath, encoderInfo, encoderParams)
        Else
            ' ... Save subsequent pages
            Dim newTiff As System.Drawing.Image = Image.FromStream(fs)
            encoderParams = New EncoderParameters(2)
            encoderParams.Param(0) = New EncoderParameter(Encoder.Compression, EncoderValue.CompressionCCITT4)
            encoderParams.Param(1) = New EncoderParameter(Encoder.SaveFlag, EncoderValue.FrameDimensionPage)
            initialTiff.SaveAdd(newTiff, encoderParams)
            newTiff.Dispose()
        End If
    End Using

Next

' Make sure to close the file
initialTiff.Dispose()

मैंने आपकी सभी युक्तियों को भी आजमाया (ReadAllBytes, FileStream => FromStream => newBitmap () एक प्रतिलिपि बनाने के लिए, आदि) और वे सभी काम करते थे। हालांकि, मुझे आश्चर्य हुआ, अगर आप कुछ कम खोज सकते हैं, और

using (Image temp = Image.FromFile(path))
{
    return new Bitmap(temp);
}

काम करने के लिए प्रतीत होता है, क्योंकि यह फ़ाइल हैंडल के साथ-साथ मूल छवि-ऑब्जेक्ट का निपटान करता है और एक नई बिटमैप-ऑब्जेक्ट बनाता है, जो मूल फ़ाइल से स्वतंत्र है और इसलिए त्रुटियों के बिना स्ट्रीम या फ़ाइल में सहेजा जा सकता है।


सुनिश्चित करें कि आप ठीक से निपट रहे हैं।

using (Image.FromFile("path")) {}

उपयोग अभिव्यक्ति के लिए लघुरूप है

IDisposable obj;
try { }
finally 
{
    obj.Dispose();
}

छवि के मामले में @Rex। मान लीजिए कि यह GdipDisposeImage बाहरी / देशी Win32 कॉल को इसके निपटान () में कॉल करता है।

IDISposable मुक्त अप्रबंधित संसाधनों के लिए एक तंत्र के रूप में प्रयोग किया जाता है (कौन सा फ़ाइल हैंडल हैं)