স্ট্রাইমাইটারটির বেসস্ট্রিমটি বন্ধ না করে বন্ধ করার কোনও উপায় আছে কি?


117

আমার মূল সমস্যাটি হ'ল যখন usingএকটিকে কল করা Disposeহয় তখন StreamWriterএটি BaseStream(একই সমস্যা Close) নিষ্পত্তি করে ।

আমার এটির জন্য একটি কার্যনির্বাহী কাজ রয়েছে তবে আপনি দেখতে পাচ্ছেন এটিতে স্ট্রিমটি অনুলিপি করা জড়িত। স্ট্রিমটি অনুলিপি না করে এটি করার কোনও উপায় আছে কি?

এর উদ্দেশ্য হ'ল স্ট্রিংয়ের বিষয়বস্তুগুলি (মূলত একটি ডাটাবেস থেকে পড়া) একটি স্ট্রিমে পাওয়া যায়, যাতে কোনও তৃতীয় পক্ষের উপাদান স্ট্রিমটি পড়তে পারে।
নোট : আমি তৃতীয় পক্ষের উপাদানটি পরিবর্তন করতে পারি না।

public System.IO.Stream CreateStream(string value)
{
    var baseStream = new System.IO.MemoryStream();
    var baseCopy = new System.IO.MemoryStream();
    using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
    {
        writer.Write(value);
        writer.Flush();
        baseStream.WriteTo(baseCopy); 
    }
    baseCopy.Seek(0, System.IO.SeekOrigin.Begin);
    return baseCopy;
}

হিসাবে ব্যবহার

public void Noddy()
{
    System.IO.Stream myStream = CreateStream("The contents of this string are unimportant");
    My3rdPartyComponent.ReadFromStream(myStream);
}

আদর্শভাবে আমি একটি কল্পিত পদ্ধতি খুঁজছি BreakAssociationWithBaseStream, যেমন

public System.IO.Stream CreateStream_Alternate(string value)
{
    var baseStream = new System.IO.MemoryStream();
    using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
    {
        writer.Write(value);
        writer.Flush();
        writer.BreakAssociationWithBaseStream();
    }
    return baseStream;
}

এটি একটি অনুরূপ প্রশ্ন: স্ট্যাকওভারফ্লো.com
জেনস গ্রান্লুন্ড

আমি এটি একটি ওয়েবআরকিউয়েস্টের একটি স্ট্রিমের সাথে করছিলাম, মজার বিষয়, এনকোডিংটি ASCII নয় তবে ইউটিএফ 8 না থাকলে আপনি এটি বন্ধ করতে পারেন। রহস্যময়।
তোফুটিম

তবে, আমি আমার ASCII হিসাবে এনকোড করেছি এবং এটি এখনও অন্তর্নিহিত প্রবাহটি নিষ্পত্তি করে ..
জেরার্ড ওনিল

উত্তর:


121

যদি আপনি .NET ফ্রেমওয়ার্ক 4.5 ব্যবহার করেন বা তার পরে, একটি স্ট্রিম রাইটার ওভারলোড রয়েছে যা ব্যবহার করে আপনি লেখক বন্ধ হয়ে গেলে বেস স্ট্রিমটি খোলার জন্য বলতে পারেন

.NET ফ্রেমওয়ার্ক 4.5 এর পূর্ববর্তী সংস্করণগুলিতে, StreamWriter ধরে নেওয়া হয় যে এটি স্ট্রিমের মালিক। বিকল্প:

  • নিষ্পত্তি করবেন না StreamWriter; শুধু এটি ফ্লাশ।
  • একটি স্ট্রিম মোড়ক তৈরি করুন যা কলগুলিকে উপেক্ষা করে Close/ Disposeকিন্তু পাশাপাশি সমস্ত কিছুকেই প্রক্সি করে। আমি মিসকিলটিতে এর একটি বাস্তবায়ন করেছি , আপনি যদি সেখান থেকে এটি দখল করতে চান।

15
স্পষ্টতই 4.5 ওভারলোডটি একটি চিন্তাভাবনা ছাড় ছাড় ছিল - ওভারলোডের জন্য বাফার আকারের প্রয়োজন হয়, যা 0 বা নাল হতে পারে না। অভ্যন্তরীণভাবে আমি জানি যে 128 টি অক্ষর ন্যূনতম আকার, তাই আমি কেবল এটি 1 এ সেট করেছি Otherwise নইলে এই 'বৈশিষ্ট্যটি' আমাকে খুশি করে।
জেরার্ড ওনিল

সেই leaveOpenপরামিতিটি StreamWriterতৈরি করার পরে কি কোনও উপায় আছে ?
c00000fd

@ c00000fd: এটি সম্পর্কে আমি অবগত নই।
জন স্কিটি

1
@ ইপিকেই: "যদি আমি একটি উপ-পদ্ধতিতে একটি স্ট্রিমটি পাস করি এবং সেই উপ-পদ্ধতিটি স্ট্রিমরাইটার তৈরি করে, তবে সেই উপ-পদ্ধতিটি কার্যকর করার পরে তা নিষ্পত্তি করা হবে" না, এটি কেবল সত্য নয়। এটির জন্য কেবল কোনওরাই ফোন দিলে তা নিষ্পত্তি Disposeহবে। পদ্ধতিটি সমাপ্তি স্বয়ংক্রিয়ভাবে তা করে না। এটির চূড়ান্তকরণকারী থাকলে এটি পরে চূড়ান্ত করা যেতে পারে তবে এটি একই জিনিস নয় - এবং আপনি কী বিপদের আশঙ্কা করছেন তা এখনও পরিষ্কার নয়। আপনি যদি ভাবেন যে StreamWriterকোনও পদ্ধতি থেকে কোনওটি ফেরত দেওয়া অনিরাপদ কারণ এটি জিসি দ্বারা স্বয়ংক্রিয়ভাবে নিষ্পত্তি হতে পারে, এটি ঠিক সত্য নয়।
জন স্কিটি

1
@ ইয়েপিকাই: এবং আইআইআরসি'র StreamWriterফাইনালাইজার নেই - এই কারণেই আমি আশা করব না।
জন স্কিটি

44

.NET 4.5 নতুন পদ্ধতি পেল যে!

http://msdn.microsoft.com/EN-US/library/gg712853(v=VS.110,d=hv.2).aspx

public StreamWriter(
    Stream stream,
    Encoding encoding,
    int bufferSize,
    bool leaveOpen
)

ধন্যবাদ বন্ধু! এটি জানতেন না, এবং এমন কিছু যদি আমার পক্ষে টার্গেট করা শুরু করার পক্ষে ভাল কারণ হয় N
ভেক্টোভক্স

22
লজ্জা নেই এমন কোনও ওভারলোড নেই যা বাফার সাইজ সেট করার প্রয়োজন হয় না। আমি সেখানে ডিফল্ট খুশি। আমি নিজেই এটি পাস করতে হবে। জগতের নয় শেষ।
অ্যান্ডি ম্যাকক্লাগেজ

3
ডিফল্ট bufferSizeহয় 1024বিশদ এখানে
অ্যালেক্স ক্লাউস

35

কেবল ডাকে Disposeনা StreamWriter। এই শ্রেণিটি নিষ্পত্তিযোগ্য হওয়ার কারণটি নয় যে এটিতে নিয়ন্ত্রিত সংস্থান রয়েছে তবে সেই ধারাটি নিষ্পত্তি করার অনুমতি দেয় যা নিজেই নিয়ন্ত্রণহীন সংস্থান রাখতে পারে। অন্তর্নিহিত স্রোতের জীবন যদি অন্য কোথাও পরিচালনা করা হয় তবে লেখককে নিষ্পত্তি করার দরকার নেই।


2
@ মার্ক, Flushডেটা বাফার করার ক্ষেত্রে এই কলিং কি কাজ করবে না ?
দারিন দিমিত্রভ

3
ভাল, তবে একবার আমরা ক্রিয়েটস্ট্রিম থেকে প্রস্থান করার পরে, স্ট্রিমওয়ারটি সংগ্রহযোগ্য, তৃতীয় অংশের পাঠককে জিসির বিরুদ্ধে প্রতিযোগিতা করতে বাধ্য করল, যা আমি ছেড়ে যেতে চাই না এমন পরিস্থিতি নয় বা আমি কিছু মিস করছি?
বাইনারি ওয়ারিয়ার

9
@ বাইনারিওরিয়ার: না, রেসের কোনও শর্ত নেই: স্ট্রিম রাইটারের ফাইনালাইজার নেই (এবং প্রকৃতপক্ষে হওয়া উচিত নয়)।
জন স্কিটি

10
@ বাইনারি ওয়ারিয়ার: আপনার যদি সরাসরি সংস্থান থাকে তবে আপনার ফাইনালাইজারটি থাকা উচিত । এই ক্ষেত্রে, স্ট্রিম রাইটিংকে ধরে নেওয়া উচিত যে স্ট্রিমের প্রয়োজন হলে নিজেকে পরিষ্কার করে দেবে।
জন স্কিটি

2
দেখে মনে হচ্ছে স্ট্রিম রাইটারের 'ক্লোজ' পদ্ধতিটি স্ট্রিমটি বন্ধ করে দেয় এবং নিষ্পত্তি করে। সুতরাং একজনকে অবশ্যই ফ্লাশ করতে হবে, তবে স্ট্রাইটারকে বন্ধ বা নিষ্পত্তি করতে হবে না, সুতরাং এটি স্ট্রিমটি বন্ধ করে না, যা প্রবাহকে নিষ্পত্তি করার সমতুল্য করবে। এপিআই থেকে খুব বেশি "সহায়তা" করুন।
জেরার্ড ওনিল

5

মেমরি স্ট্রিমের একটি ToArray বৈশিষ্ট্য রয়েছে যা স্ট্রিম বন্ধ থাকা অবস্থায়ও ব্যবহার করা যেতে পারে। অ্যারেতে পজিশনের সম্পত্তি নির্বিশেষে কোনও বাইট অ্যারে স্ট্রিমের লিখিত সামগ্রী লিখেছেন। আপনি লিখেছেন স্ট্রিমের উপর ভিত্তি করে আপনি একটি নতুন স্ট্রিম তৈরি করতে পারেন।

public System.IO.Stream CreateStream(string value)
{
    var baseStream = new System.IO.MemoryStream();
    var baseCopy = new System.IO.MemoryStream();
    using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
    {
        writer.Write(value);
        writer.Flush();
        baseStream.WriteTo(baseCopy); 
    }
    var returnStream = new System.IO.MemoryStream( baseCopy.ToArray());
    return returnStream;
}

এটি কি সঠিকভাবে ফিরে আসা অ্যারেগুলি সামগ্রীর আকারের মধ্যে সীমাবদ্ধ করে? কারণ এটি নিষ্পত্তি হওয়ার পরে বলা Stream.Positionযাবে না
নায়ারগডস

2

আপনার স্ট্রিম রাইটারের বংশধর তৈরি করতে হবে এবং এর নিষ্পত্তি পদ্ধতিটিকে ওভাররাইড করতে হবে, সর্বদা ডিসপোসিং প্যারামিটারের কাছে মিথ্যাভাবে পাঠিয়ে, এটি স্ট্রিম লেখককে বন্ধ না করতে বাধ্য করে, স্ট্রিম রাইটার কেবল নিকট পদ্ধতিতে নিষ্পত্তি কল করে, তাই করার দরকার নেই এটিকে ওভাররাইড করুন (অবশ্যই আপনি চাইলে সমস্ত কন্সট্রাক্টর যুক্ত করতে পারেন, আমার কেবল একটি আছে):

public class NoCloseStreamWriter : StreamWriter
{
    public NoCloseStreamWriter(Stream stream, Encoding encoding)
        : base(stream, encoding)
    {
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(false);
    }
}

3
আমি বিশ্বাস করি এটি আপনার যা মনে করে তা তা করে না। disposingপতাকার অংশ প্যাটার্ন । সর্বদা ক্ষণস্থায়ী থেকে মূলত সংকেত বেস ক্লাসের পদ্ধতি এটি finalizer থেকে আহবান করা হয় (যা নয় আপনি কল যখন স্পষ্টভাবে), এবং এইভাবে পরিচালিত কোনো বস্তু অ্যাক্সেস করা উচিত নয়। এই কারণেই এটি বেস স্ট্রিমটি নিষ্পত্তি করবে না। তবে আপনি যেভাবে এটি অর্জন করেছেন তা হ্যাক; প্রথম স্থানটিতে কেবল কল করা সহজ হবে না ! IDisposablefalseDispose(bool)StreamWriterDispose()Dispose
স্টাকেক্স

আসলে সিম্যানটেকের সত্যিই, আপনি স্ট্রিমিং পুরোপুরি স্ক্র্যাচ থেকে পুনরায় লেখার বাইরে যা কিছু করেন তা হ্যাক হতে চলেছে। অবশ্যই যদিও, আপনি কেবল বেসকে কল করতে পারেন নি isবিহীন (মিথ্যা) মোটেও, তবে কোনও কার্যকরী পার্থক্য থাকবে না এবং আমি আমার উদাহরণটির স্পষ্টতা পছন্দ করি। যাইহোক, এটি মনে রাখবেন, স্ট্রিমাইটার শ্রেণীর ভবিষ্যতের সংস্করণটি স্রোতকে নিষ্ক্রিয় করার সময় কেবল স্ট্রিমটি বন্ধ করার চেয়ে আরও বেশি কিছু করতে পারে, তাই এটি নিষ্পত্তি (মিথ্যা) ভবিষ্যতের প্রমাণগুলিও কল করে। কিন্তু প্রতিটি তার নিজস্ব।
অ্যারন মুরগাট্রয়েড

2
এটি করার আরেকটি উপায় হ'ল আপনার নিজস্ব স্ট্রিম র‍্যাপার তৈরি করা যাতে আরও একটি স্ট্রিম থাকে যেখানে ক্লোজ পদ্ধতিটি অন্তর্নিহিত স্ট্রিমটি বন্ধ করার পরিবর্তে কেবল কিছুই করে না, এটি হ্যাকের চেয়ে কম তবে আরও কাজ।
অ্যারন মুরগাট্রয়েড

আশ্চর্যজনক সময়: আমি ঠিক একই জিনিসটি প্রস্তাব করতে যাচ্ছিলাম (সাজসজ্জার শ্রেণি, সম্ভবত নামকরণ করা হয়েছে OwnedStream, যা উপেক্ষা করে Dispose(bool)এবং Close)।
স্টাকেক্স -

হ্যাঁ, উপরের কোডটি কীভাবে আমি তাড়াতাড়ি এবং নোংরা পদ্ধতির জন্য এটি করি, তবে আমি যদি বাণিজ্যিক অ্যাপ্লিকেশন বা আমার সাথে কিছু গুরুত্বপূর্ণ হয়ে থাকে তবে আমি স্ট্রিমের মোড়কের ক্লাসটি ব্যবহার করে এটি সঠিকভাবে করব। ব্যক্তিগতভাবে আমি মনে করি মাইক্রোসফ্ট এখানে ভুল করেছে, স্ট্রাইট্রাইটারের পরিবর্তে অন্তর্নিহিত স্ট্রিমটি বন্ধ করার জন্য একটি বুলিয়ান সম্পত্তি থাকা উচিত ছিল, তবে তখন আমি মাইক্রোসফ্টে কাজ করি না তাই তারা যা পছন্দ করে আমার ধারণা: ডি
অ্যারন মুরগাট্রয়েড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.