একটি স্ট্রিম থেকে বাইট অ্যারে তৈরি করা হচ্ছে


911

ইনপুট স্ট্রিম থেকে বাইট অ্যারে তৈরি করার জন্য পছন্দের পদ্ধতিটি কী?

.NET 3.5 এর সাথে আমার বর্তমান সমাধান।

Stream s;
byte[] b;

using (BinaryReader br = new BinaryReader(s))
{
    b = br.ReadBytes((int)s.Length);
}

স্রোতের অংশগুলি পড়া এবং লেখার জন্য এটি কি আরও ভাল ধারণা?


60
অবশ্যই, আরেকটি প্রশ্ন হ'ল আপনার যদি একটি স্ট্রিম থেকে একটি বাইট [] তৈরি করা উচিত ... বড় ডেটার জন্য, স্ট্রিমের পাশাপাশি ভাল, একটি স্ট্রিমকে চিকিত্সা করা ভাল!
মার্ক গ্র্যাভেল

2
আসলে আপনার সম্ভবত বাইটের পরিবর্তে একটি স্ট্রিম ব্যবহার করা উচিত []। তবে কিছু সিস্টেম এপিআই রয়েছে যা স্ট্রিমগুলি সমর্থন করে না। উদাহরণস্বরূপ, আপনি একটি প্রবাহ থেকে একটি X509 সার্টিফিকেট 2 তৈরি করতে পারবেন না , আপনাকে এটিকে একটি বাইট [] বা একটি স্ট্রিং দিতে হবে। এই ক্ষেত্রে এটি ঠিক আছে যেহেতু x509 শংসাপত্রটি সম্ভবত বড় ডেটা নয়
0xced

উত্তর:


1292

এটি নির্ভর করে আপনি নির্ভর করতে পারেন কিনা তার উপর s.Length। অনেকগুলি স্ট্রিমের জন্য, আপনি কেবল জানেন না যে সেখানে কতটা ডেটা থাকবে। এই জাতীয় ক্ষেত্রে - এবং নেট 4 এর আগে - আমি এই জাতীয় কোড ব্যবহার করতাম:

public static byte[] ReadFully(Stream input)
{
    byte[] buffer = new byte[16*1024];
    using (MemoryStream ms = new MemoryStream())
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, read);
        }
        return ms.ToArray();
    }
}

.NET 4 এবং উপরের সাথে, আমি ব্যবহার করব Stream.CopyTo, যা মূলত আমার কোডের লুপের সমান - MemoryStreamকলটি তৈরি করুন stream.CopyTo(ms)এবং তারপরে ফিরে আসুন ms.ToArray()। কাজ শেষ.

আমার উত্তরটি কেন অন্যের চেয়ে দীর্ঘ হয় তা সম্ভবত আমার ব্যাখ্যা করা উচিত। Stream.Readগ্যারান্টি দেয় না যে এটি যা চাওয়া হয়েছে তা পড়বে। আপনি যদি কোনও নেটওয়ার্ক স্ট্রিম থেকে পড়েন, উদাহরণস্বরূপ, এটি একটি প্যাকেটের মূল্য পড়তে পারে এবং তারপরে ফিরে আসতে পারে, যদি খুব শীঘ্রই আরও ডেটা থাকে। BinaryReader.Readস্ট্রিম বা আপনার নির্দিষ্ট আকারের শেষ হওয়া অবধি চলতে থাকবে, তবে আপনাকে এখনও আকারটি শুরু করতে হবে।

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

আরও তথ্যের জন্য এই নিবন্ধটি দেখুন (এবং একটি বিকল্প বাস্তবায়ন)।



6
@ জেফ: আমাদের এখানে সত্যিই প্রসঙ্গটি নেই, তবে আপনি যদি কোনও স্ট্রিমে লিখছেন, তবে হ্যাঁ পড়ার আগে আপনাকে এটি "রিওয়াইন্ড" করা দরকার। স্রোতের মধ্যে আপনি যেখানে আছেন সেখানে কেবল একটি "কার্সর" রয়েছে - পড়ার জন্য একটি নয় এবং লেখার জন্য পৃথক কোনও নেই।
জন স্কিটি

5
@ জেফ: এটি আহ্বানের দায়িত্ব। সর্বোপরি, স্ট্রিমটি অন্বেষণযোগ্য নাও হতে পারে (যেমন একটি নেটওয়ার্ক স্ট্রিম) অথবা এটি পুনরায় রিন্ডাইন্ড করার দরকার নেই।
জন স্কিটি

18
আমি জিজ্ঞাসা করতে পারি কেন 16*1024বিশেষভাবে?
কোনও নাম ডোনটকেয়ার

5
@ ঠিক_নাম: আমি জানিনা এর এর কোন তাত্পর্য আছে কিনা তবে (16 * 1024)
ইনট

733

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

public static byte[] ReadFully(Stream input)
{
    using (MemoryStream ms = new MemoryStream())
    {
        input.CopyTo(ms);
        return ms.ToArray();
    }
}

6
এটি আপনার উত্তর এবং জনের মধ্যে কী আলাদা? এছাড়াও আমাকে অবশ্যই এই ইনপুটটি করতে হবে the কপিরাইটোর কাজ করার জন্য অবস্থান = 0।
জেফ

1
@ নাথান, ওয়েব ক্লায়েন্ট (ফাইলাইজাইজ = 1 এমবি) থেকে একটি ফাইল রিডিগ করুন - আইআইএসকে পুরো 1 এমবি এর স্মৃতিতে লোড করতে হবে?
রই নমির

5
@ জেফ, আমার উত্তরটি কেবলমাত্র কাজ করবে et নেট বা 4 বা তার বেশি, জোনস পরবর্তী সংস্করণে আমাদের সরবরাহিত কার্যকারিতা পুনর্লিখনের মাধ্যমে নিম্ন সংস্করণে কাজ করবে। আপনি ঠিক বলেছেন যে কপিরাইটো কেবল বর্তমান অবস্থান থেকে অনুলিপি করবে, যদি আপনার কাছে সন্ধানযোগ্য স্ট্রিম থাকে এবং আপনি শুরু থেকে অনুলিপি করতে চান তবে আপনি আপনার কোড বা ইনপুট ব্যবহার করে শুরুতে যেতে পারেন e অনুসন্ধান করুন (0, সিকঅরগিন.বিগিন), যদিও অনেক ক্ষেত্রে আপনার স্ট্রিম সন্ধানযোগ্য নাও হতে পারে।
নাথান ফিলিপস

5
এটি inputইতিমধ্যে একটি MemorySteamসংক্ষিপ্ত সার্কিট কিনা তা পরীক্ষা করার উপযুক্ত হতে পারে । আমি জানি যে একজনকে পাস করার জন্য এটি কলকারীর বোকামি হবে MemoryStream...
জোডরেল

3
@ জোডরেল, ঠিক তাই আপনি মেমরিতে ছোট স্ট্রিম লক্ষ লক্ষ কপি করছি এবং তাদের মধ্যে একজন একটি হলে MemoryStreamতারপর অপ্টিমাইজেশান আপনার প্রেক্ষাপটে জ্ঞান করে তোলে কিনা সময় সময় নিয়েছে বিরুদ্ধে টাইপ ধর্মান্তর লক্ষ লক্ষ করতে নিয়ে যাওয়া তুলনা একজন যে কপি হয় MemoryStreamমধ্যে অন্য MemoryStream
নাথান ফিলিপস

114

কেবল এটিই উল্লেখ করতে চাই memorystream.ToArray()যে আপনার যদি ইতিমধ্যে মেমোরিস্ট্রিম পান তবে আপনার কাছে এটির জন্য রয়েছে।

এছাড়াও, আপনি যদি অজানা বা বিভিন্ন উপ-প্রকারের স্ট্রিমগুলির সাথে কাজ করে থাকেন এবং আপনি কোনওটি পেতে MemoryStreamপারেন তবে আপনি সেই মামলার জন্য উল্লিখিত পদ্ধতিটি রিলে করতে পারেন এবং এখনও অন্যের জন্য গ্রহণযোগ্য উত্তরটি ব্যবহার করতে পারেন:

public static byte[] StreamToByteArray(Stream stream)
{
    if (stream is MemoryStream)
    {
        return ((MemoryStream)stream).ToArray();                
    }
    else
    {
        // Jon Skeet's accepted answer 
        return ReadFully(stream);
    }
}

1
হু, সমস্ত উপক্রম কি? এমনকি সবচেয়ে উদার অনুমান সহ, এটি কেবল ইতিমধ্যে স্ট্রিমগুলির জন্য কাজ করে MemoryStream। অবশ্যই উদাহরণটি স্পষ্টতই অসম্পূর্ণ, এটি কীভাবে একটি অবিচ্ছিন্ন ভেরিয়েবল ব্যবহার করছে।
রোমান স্টারকভ

3
এটা ঠিক, এটি নির্দেশ করার জন্য ধন্যবাদ। পয়েন্টটি এখনও মেমরিস্ট্রিমের জন্য দাঁড়িয়েছে, তাই আমি এটি প্রতিফলিত করার জন্য এটি স্থির করেছি।
ফার্নান্দো নীরা

কেবল উল্লেখ করুন যে মেমরিস্ট্রিমের জন্য আরেকটি সম্ভাবনা হ'ল মেমরিস্ট্রিম et গেটবফার () যদিও এর সাথে জড়িত কিছু গ্যাটাচ রয়েছে। দেখুন stackoverflow.com/questions/1646193/... এবং krishnabhargav.blogspot.dk/2009/06/...
RenniePet

4
এটি আসলে স্কিটের কোডে একটি বাগ প্রবর্তন করে; আপনি যদি কল করেন stream.Seek(1L, SeekOrigin.Begin), আপনি পড়ার সাথে ডাকার আগে, স্ট্রিমটি যদি একটি মেমরি স্ট্রিম হয় তবে এটি অন্য কোনও স্ট্রিমের চেয়ে 1 বাইট বেশি পাবেন। যদি কলার বর্তমান অবস্থানটি স্ট্রিমের শেষের দিক থেকে পড়ার প্রত্যাশা করে তবে আপনি অবশ্যই ব্যবহার করবেন না CopyToবা ToArray(); বেশিরভাগ ক্ষেত্রে এটি কোনও সমস্যা হবে না, তবে যদি কলার এই উদ্দীপনাজনক আচরণ সম্পর্কে না জানেন তবে তারা বিভ্রান্ত হবেন।
লিট করুন

67
MemoryStream ms = new MemoryStream();
file.PostedFile.InputStream.CopyTo(ms);
var byts = ms.ToArray();
ms.Dispose();

9
মেমরি স্ট্রিমেন্টেশন এড়ানোর জন্য মেমোরিস্ট্রিমটি "নতুন মেমরিস্ট্রিম (ফাইল.পোস্টেডফিল.সন্টেন্টলেন্ট)" তৈরি করা উচিত।
ড্যান র‌্যান্ডল্ফ

52

কেবল আমার দম্পতি সেন্ট ... আমি প্রায়শই যে অনুশীলনটি ব্যবহার করি তা হ'ল এই পদ্ধতিগুলি কাস্টম সহায়ক হিসাবে সংগঠিত করা

public static class StreamHelpers
{
    public static byte[] ReadFully(this Stream input)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            input.CopyTo(ms);
            return ms.ToArray();
        }
    }
}

কনফিগার ফাইলে নেমস্পেস যুক্ত করুন এবং এটি আপনার ইচ্ছামত যে কোনও জায়গায় ব্যবহার করুন


5
নোট করুন যে এটি .NET 3.5 এবং নীচে হিসাবে কাজ করবে না যা 4.0 অবধি CopyToউপলব্ধ ছিল না Stream
টিম

15

প্রাক্তন- এর জন্য আপনি কেবল মেমরিস্ট্রিম ক্লাসের টোআরাই () পদ্ধতিটি ব্যবহার করতে পারেন-

MemoryStream ms = (MemoryStream)dataInStream;
byte[] imageBytes = ms.ToArray();

10

আপনি এটি এক্সটেনশানগুলির সাথে কল্পিতও করতে পারেন:

namespace Foo
{
    public static class Extensions
    {
        public static byte[] ToByteArray(this Stream stream)
        {
            using (stream)
            {
                using (MemoryStream memStream = new MemoryStream())
                {
                     stream.CopyTo(memStream);
                     return memStream.ToArray();
                }
            }
        }
    }
}

এবং তারপরে এটিকে একটি নিয়মিত পদ্ধতি হিসাবে কল করুন:

byte[] arr = someStream.ToByteArray()

67
আমি মনে করি একটি ইনপুট স্ট্রিমটিকে একটি ব্যবহারের ব্লকে রেখে দেওয়া খারাপ ধারণা। এই দায়িত্বটি কলিং পদ্ধতি সহ বিশ্রাম করা উচিত।
জেফ

7

আমি ববসের (অর্থাত্ প্রশ্নকারী) কোড সহ একটি সংকলন সময় ত্রুটি পেয়েছি। Stream.Length একটি দীর্ঘ যেখানে বাইনারিআডার। রিডবাইটস একটি পূর্ণসংখ্যার পরামিতি নেয়। আমার ক্ষেত্রে, লম্বা নির্ভুলতার প্রয়োজনের জন্য পর্যাপ্ত স্ট্রিমগুলির সাথে व्यवहार করার আমি আশা করি না, তাই আমি নিম্নলিখিতটি ব্যবহার করি:

Stream s;
byte[] b;

if (s.Length > int.MaxValue) {
  throw new Exception("This stream is larger than the conversion algorithm can currently handle.");
}

using (var br = new BinaryReader(s)) {
  b = br.ReadBytes((int)s.Length);
}

5

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

public static class StreamHelpers
{
    public static byte[] ReadFully(this Stream input)
    {
        var ms = new MemoryStream();
        input.CopyTo(ms);
        return ms.ToArray();
    }
}

3

উপরেরটি ঠিক আছে ... তবে আপনি এসএমটিপি-র মাধ্যমে জিনিস পাঠানোর সময় আপনি ডেটা দুর্নীতির মুখোমুখি হবেন (যদি আপনার প্রয়োজন হয়)। আমি অন্য কোনও কিছুতে পরিবর্তন করেছি যা বাইটের জন্য সঠিকভাবে বাইট প্রেরণে সহায়তা করবে: '

using System;
using System.IO;

        private static byte[] ReadFully(string input)
        {
            FileStream sourceFile = new FileStream(input, FileMode.Open); //Open streamer
            BinaryReader binReader = new BinaryReader(sourceFile);
            byte[] output = new byte[sourceFile.Length]; //create byte array of size file
            for (long i = 0; i < sourceFile.Length; i++)
                output[i] = binReader.ReadByte(); //read until done
            sourceFile.Close(); //dispose streamer
            binReader.Close(); //dispose reader
            return output;
        }'

আমি দেখতে পাচ্ছি না যে এই কোডটি ডেটা দুর্নীতি এড়ায়। তুমি কি এটা ব্যাখ্যা করতে পারবে?
নিপ্পি

ধরা যাক যে আপনার কাছে একটি ছবি আছে এবং আপনি এটি এসএমটিপি এর মাধ্যমে প্রেরণ করতে চান। আপনি সম্ভবত বেস 64 এনকোডিং ব্যবহার করবেন। কোনও কারণে, ফাইলটি বাইট হিসাবে ভেঙে ফেলা হলে ফাইলটি কলুষিত হয়ে যায়। তবে, বাইনারি রিডার ব্যবহার করে ফাইলটি সফলভাবে প্রেরণের অনুমতি দেবে।
NothinRandom

3
কিছুটা পুরানো, তবে আমি এই বিষয়টি উল্লেখ করে অনুভব করেছি - বাস্তবায়ন @ নথিনর্যান্ডম স্ট্রিমের সাথে নয়, স্ট্রিংয়ের সাথে কাজ করে। তবে কেবল ফাইলটি ব্যবহার করা খুব সহজ হবে this তবে এ ক্ষেত্রে অ্যালবাইটগুলি পড়ুন।
XwipeoutX

1
বিপজ্জনক কোড শৈলীর কারণে ডাউনভোট (কোনও স্বয়ংক্রিয় নিষ্পত্তি / ব্যবহার নেই)।
আরনি

দুঃখের সাথে কেবল -১ অনুমোদিত, প্রশ্নের সাথে কিছুই করার নেই, ফাইল নেম প্যারামিটারের নামযুক্ত ইনপুট, নিষ্পত্তি করা হচ্ছে না, রিডিং বাফার নেই, ফাইলমোড নেই, এবং বাইনারি রিডারকে বাইট বাইতে পড়তে হবে কেন?
এরিডানে Áলামো

2

একটি সহায়ক শ্রেণি তৈরি করুন এবং আপনি যে কোনও জায়গায় এটি ব্যবহার করতে চান তা উল্লেখ করুন।

public static class StreamHelpers
{
    public static byte[] ReadFully(this Stream input)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            input.CopyTo(ms);
            return ms.ToArray();
        }
    }
}

2

নেমস্পেসে রেস্টশার্প. এক্সটেনশনগুলিতে পদ্ধতিটি ReadAsBytes রয়েছে। এই পদ্ধতির অভ্যন্তরে মেমরিস্ট্রিম ব্যবহৃত হয় এবং এই পৃষ্ঠায় কিছু উদাহরণের মতো একই কোড রয়েছে তবে আপনি যখন রেস্টশার্প ব্যবহার করছেন তখন এটি সবচেয়ে সহজ উপায়।

using RestSharp.Extensions;
var byteArray = inputStream.ReadAsBytes();

1

আপনি এই এক্সটেনশন পদ্ধতিটি ব্যবহার করতে পারেন।

public static class StreamExtensions
{
    public static byte[] ToByteArray(this Stream stream)
    {
        var bytes = new List<byte>();

        int b;
        while ((b = stream.ReadByte()) != -1)
            bytes.Add((byte)b);

        return bytes.ToArray();
    }
}

1

এটি আমি ফাংশন যা ব্যবহার করছি, পরীক্ষা করেছি এবং ভালভাবে কাজ করেছি। দয়া করে মনে রাখবেন যে 'ইনপুট' শূন্য হওয়া উচিত নয় এবং 'ইনপুট.পজিশন' পড়ার আগে '0' এ পুনরায় সেট করা উচিত অন্যথায় এটি পড়ার লুপটি ভেঙে ফেলবে এবং অ্যারেতে রূপান্তর করতে কিছুই পড়বে না।

    public static byte[] StreamToByteArray(Stream input)
    {
        if (input == null)
            return null;
        byte[] buffer = new byte[16 * 1024];
        input.Position = 0;
        using (MemoryStream ms = new MemoryStream())
        {
            int read;
            while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }
            byte[] temp = ms.ToArray();

            return temp;
        }
    }

-1
public static byte[] ToByteArray(Stream stream)
    {
        if (stream is MemoryStream)
        {
            return ((MemoryStream)stream).ToArray();
        }
        else
        {
            byte[] buffer = new byte[16 * 1024];
            using (MemoryStream ms = new MemoryStream())
            {
                int read;
                while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }
                return ms.ToArray();
            }
        }            
    }

আপনি মূল্যবান কিছু যোগ না করে সবেমাত্র # 1 এবং # 3 উত্তর থেকে কোডটি অনুলিপি করেছেন। দয়া করে এটি করবেন না। :)
কোডকাস্টার

আপনি যখন একটি কোড যুক্ত করবেন, শীঘ্রই আপনার প্রস্তাবিত সমাধানটিও বর্ণনা করুন।
ইয়াকোবম

-5

আমি এটি একটি লাইনে কাজ করতে সক্ষম হয়েছি:

byte [] byteArr= ((MemoryStream)localStream).ToArray();

জননিরোজ দ্বারা স্পষ্ট হিসাবে , উপরের কোডটি কেবল মেমরিস্ট্রিমের জন্য কাজ করবে


2
localStreamনা হলে কি হবে MemoryStream? এই কোড ব্যর্থ হবে।
johnnyRose

লোকালস্ট্রিম স্ট্রিম ভিত্তিক অবজেক্ট হতে হবে। স্ট্রিম ভিত্তিক অবজেক্ট সম্পর্কে আরও এখানে স্ট্যাকওভারফ্লো.com
আব্বা

1
আমি যা প্রস্তাব দেওয়ার চেষ্টা করছিলাম তা হ'ল, আপনি যদি কাস্ট localStreamকরার চেষ্টা করেন MemoryStreamতবে localStreamএটি একটি না হন তবে MemoryStreamএটি ব্যর্থ হবে । এই কোডটি সূক্ষ্ম সংকলন করবে, তবে এটি রানটাইমের সময় আসল প্রকারের উপর নির্ভর করে ব্যর্থ হতে পারে localStream। আপনি সর্বদা নির্বিচারে একটি শিশু টাইপ একটি বেস টাইপ নিক্ষেপ করতে পারবেন না; এখানে আরও পড়ুনএটি অন্য ভাল উদাহরণ যা ব্যাখ্যা কেন আপনি সবসময় এই কাজ করতে পারবে না।
johnnyRose

আমার উপরের মন্তব্যটি বিশদভাবে জানাতে: সমস্ত মেমরি স্ট্রিমগুলি স্ট্রিম তবে সমস্ত স্ট্রিম মেমরিস্ট্রিম নয়।
johnnyRose

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