c# मैं स्ट्रीम को सी#में एक फ़ाइल में कैसे सहेजूं?




.net sql-server (8)

मेरे पास StreamReader ऑब्जेक्ट है जिसे मैंने स्ट्रीम के साथ शुरू किया है, अब मैं इस स्ट्रीम को डिस्क पर सहेजना चाहता हूं (स्ट्रीम एक .gif या .jpg या .pdf हो सकती है)।

मौजूदा कोड:

StreamReader sr = new StreamReader(myOtherObject.InputStream);
  1. मुझे इसे डिस्क पर सहेजने की ज़रूरत है (मेरे पास फ़ाइल नाम है)।
  2. भविष्य में मैं इसे SQL सर्वर में संग्रहीत करना चाहता हूं।

मेरे पास एन्कोडिंग प्रकार भी है, जिसे मैं इसे SQL सर्वर में संग्रहीत करने की आवश्यकता होगी, सही?


मुझे CopyTo का उपयोग करके सभी उत्तरों नहीं मिलते हैं, जहां शायद ऐप का उपयोग करने वाले सिस्टम को .NET 4.0+ में अपग्रेड नहीं किया जा सकता है। मुझे पता है कि कुछ लोगों को अपग्रेड करने के लिए मजबूर करना चाहते हैं, लेकिन संगतता भी अच्छी है।

एक और बात, मुझे पहली जगह में दूसरी स्ट्रीम से कॉपी करने के लिए स्ट्रीम का उपयोग नहीं मिलता है। क्यों न करें:

byte[] bytes = myOtherObject.InputStream.ToArray();

एक बार आपके पास बाइट्स हो जाने पर, आप उन्हें आसानी से फ़ाइल में लिख सकते हैं:

public static void WriteFile(string fileName, byte[] bytes)
{
    string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    if (!path.EndsWith(@"\")) path += @"\";

    if (File.Exists(Path.Combine(path, fileName)))
        File.Delete(Path.Combine(path, fileName));

    using (FileStream fs = new FileStream(Path.Combine(path, fileName), FileMode.CreateNew, FileAccess.Write)
    {
        fs.Write(bytes, 0, (int)bytes.Length);
        fs.Close();
    }
}

यह कोड काम करता है क्योंकि मैंने इसे .jpg फ़ाइल के साथ परीक्षण किया है, हालांकि मैं मानता हूं कि मैंने इसे केवल छोटी फ़ाइलों (1 एमबी से कम) के साथ उपयोग किया है। एक स्ट्रीम, स्ट्रीम के बीच कोई प्रतिलिपि नहीं, कोई एन्कोडिंग आवश्यक नहीं है, बस बाइट्स लिखें! StreamReader साथ चीजों को अधिक जटिल करने की आवश्यकता नहीं है यदि आपके पास पहले से कोई स्ट्रीम है तो आप सीधे bytes कनवर्ट कर सकते हैं। .ToArray() !

केवल संभावित डाउनसाइड्स मैं इसे इस तरह से करने में देख सकता हूं यदि आपके पास एक बड़ी फ़ाइल है, जो इसे स्ट्रीम के रूप में .CopyTo() और इसका उपयोग कर रहा है। .CopyTo() या समकक्ष .CopyTo() को बाइट सरणी का उपयोग करने और बाइट्स को पढ़ने के बजाय इसे स्ट्रीम करने की अनुमति देता है एक। नतीजतन, यह इस तरह से धीमा हो सकता है। लेकिन यह तब से .Write() नहीं होना चाहिए जब .Write() की .Write() विधि बाइट्स लिखती है, और यह केवल एक बार एक बाइट कर रही है, इसलिए यह स्मृति को बंद नहीं करेगा, सिवाय इसके कि आपको पर्याप्त मेमोरी होगी स्ट्रीम को byte[] ऑब्जेक्ट के रूप में रखें । मेरी परिस्थिति में जहां मैंने इसका इस्तेमाल किया, OracleBlob प्राप्त कर रहा था, मुझे एक byte[] जाना पड़ा, यह काफी छोटा था, और इसके अलावा, मेरे लिए कोई स्ट्रीमिंग उपलब्ध नहीं थी, वैसे भी, इसलिए मैंने अपने बाइट्स को मेरे फ़ंक्शन पर भेजा, ऊपर।

एक स्ट्रीम का उपयोग करके एक और विकल्प, जॉन स्कीट के CopyStream फ़ंक्शन के साथ इसका उपयोग करना होगा जो कि किसी अन्य पोस्ट में था - यह इनपुट स्ट्रीम लेने और सीधे फ़ाइल को बनाने के लिए CopyStream का उपयोग करता है। यह File.Create उपयोग नहीं करता है, जैसा कि उसने किया था (जो शुरू में मेरे लिए समस्याग्रस्त प्रतीत होता था, लेकिन बाद में पाया गया कि यह केवल एक वीएस बग था ...)।

/// <summary>
/// Copies the contents of input to output. Doesn't close either stream.
/// </summary>
public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[8 * 1024];
    int len;
    while ( (len = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write(buffer, 0, len);
    }    
}

public static void WriteFile(string fileName, Stream inputStream)
{
    string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    if (!path.EndsWith(@"\")) path += @"\";

    if (File.Exists(Path.Combine(path, fileName)))
        File.Delete(Path.Combine(path, fileName));

    using (FileStream fs = new FileStream(Path.Combine(path, fileName), FileMode.CreateNew, FileAccess.Write)
    {
        CopyStream(inputStream, fs);
    }

    inputStream.Close();
    inputStream.Flush();
}

फ़ाइलस्ट्रीम ऑब्जेक्ट का उपयोग क्यों न करें?

public void SaveStreamToFile(string fileFullPath, Stream stream)
{
    if (stream.Length == 0) return;

    // Create a FileStream object to write a stream to a file
    using (FileStream fileStream = System.IO.File.Create(fileFullPath, (int)stream.Length))
    {
        // Fill the bytes[] array with the stream data
        byte[] bytesInStream = new byte[stream.Length];
        stream.Read(bytesInStream, 0, (int)bytesInStream.Length);

        // Use FileStream object to write to the specified file
        fileStream.Write(bytesInStream, 0, bytesInStream.Length);
     }
}

public void CopyStream(Stream stream, string destPath)
{
  using (var fileStream = new FileStream(destPath, FileMode.Create, FileAccess.Write))
  {
    stream.CopyTo(fileStream);
  }
}

public void testdownload(stream input)
{
    byte[] buffer = new byte[16345];
    using (FileStream fs = new FileStream(this.FullLocalFilePath,
                        FileMode.Create, FileAccess.Write, FileShare.None))
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
             fs.Write(buffer, 0, read);
        }
    }
}

private void SaveFileStream(String path, Stream stream)
{
    var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
    stream.CopyTo(fileStream);
    fileStream.Dispose();
}

एक और विकल्प है कि स्ट्रीम को byte[] और File.WriteAllBytes उपयोग File.WriteAllBytes । यह करना चाहिए:

using (var stream = new MemoryStream())
{
    input.CopyTo(stream);
    File.WriteAllBytes(file, stream.ToArray());
}

एक विस्तार विधि में इसे लपेटना इसे बेहतर नामकरण देता है:

public void WriteTo(this Stream input, string file)
{
    //your fav write method:

    using (var stream = File.Create(file))
    {
        input.CopyTo(stream);
    }

    //or

    using (var stream = new MemoryStream())
    {
        input.CopyTo(stream);
        File.WriteAllBytes(file, stream.ToArray());
    }

    //whatever that fits.
}

आपको बाइनरी फ़ाइलों (जैसे gifs या jpgs) के लिए StreamReader उपयोग नहीं करना चाहिएStreamReader टेक्स्ट डेटा के लिए है। यदि आप इसे मनमाने ढंग से बाइनरी डेटा के लिए उपयोग करते हैं तो आप लगभग निश्चित रूप से डेटा खो देंगे। (यदि आप एन्कोडिंग का उपयोग करते हैं। GetEncoding (28591) आप शायद ठीक रहेगा, लेकिन बिंदु क्या है?)

आपको StreamReader का उपयोग करने की आवश्यकता क्यों है? बाइनरी डेटा को बाइनरी डेटा के रूप में क्यों न रखें और इसे वापस डिस्क (या एसक्यूएल) में बाइनरी डेटा के रूप में लिखें?

संपादित करें: जैसा कि ऐसा लगता है कि कुछ लोग देखना चाहते हैं ... यदि आप सिर्फ एक स्ट्रीम को दूसरी फ़ाइल में कॉपी करना चाहते हैं (उदाहरण के लिए फ़ाइल में) इस तरह कुछ उपयोग करें:

/// <summary>
/// Copies the contents of input to output. Doesn't close either stream.
/// </summary>
public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[8 * 1024];
    int len;
    while ( (len = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write(buffer, 0, len);
    }    
}

किसी फ़ाइल को स्ट्रीम में डंप करने के लिए इसका उपयोग करने के लिए, उदाहरण के लिए:

using (Stream file = File.Create(filename))
{
    CopyStream(input, file);
}

ध्यान दें कि Stream.CopyTo को .NET 4 में पेश किया गया था, जो मूल रूप से एक ही उद्देश्य की सेवा करता था।


जैसा कि जॉन स्कीट के जवाब में टिलेंडर द्वारा हाइलाइट किया गया है, धाराओं में .NET 4 के बाद से CopyTo विधि है।

var fileStream = File.Create("C:\\Path\\To\\File");
myOtherObject.InputStream.Seek(0, SeekOrigin.Begin);
myOtherObject.InputStream.CopyTo(fileStream);
fileStream.Close();

या using वाक्यविन्यास के साथ:

using (var fileStream = File.Create("C:\\Path\\To\\File"))
{
    myOtherObject.InputStream.Seek(0, SeekOrigin.Begin);
    myOtherObject.InputStream.CopyTo(fileStream);
}






stream