.NET- এ কোনও অবজেক্টকে ইউটিএফ -8 এক্সএমএল হিসাবে সিরিয়াল করা হচ্ছে


112

যথাযথ অবজেক্টের নিষ্পত্তি ব্রিভিটির জন্য অপসারণ করা হয়েছে তবে আমি যদি হতবাক হয়ে যাই তবে এটি কোনও স্মৃতিতে ইউটিএফ -8 হিসাবে কোনও বস্তুকে এনকোড করার সহজতম উপায়। একটি সহজ উপায় আছে সেখানে আছে না?

var serializer = new XmlSerializer(typeof(SomeSerializableObject));

var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream, System.Text.Encoding.UTF8);

serializer.Serialize(streamWriter, entry);

memoryStream.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(memoryStream, System.Text.Encoding.UTF8);
var utf8EncodedXml = streamReader.ReadToEnd();


1
আমি বিভ্রান্ত ... ডিফল্ট এনকোডিং ইউটিএফ -8 না?
flq

@ এফএলকিউ, হ্যাঁ ডিফল্টটি ইউটিএফ -৮, যদিও সে এটি আবার স্ট্রিংয়ে পড়ে আবার পড়েছে তাই ইউটিএফ -১ is এর থেকে বেশি কিছু আসে যায় না utf8EncodedXml
জন হান্না

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

@ জন ফিরে পড়া, আমার প্রশ্নে অস্পষ্টতা আছে। আমার এটি বেশিরভাগ ডিবাগিংয়ের উদ্দেশ্যে স্ট্রিংয়ে আউটপুট দেয়। অনুশীলনে আমি সম্ভবত ডিস্কে বা HTTP এর উপরে বাইটগুলি প্রবাহিত করব যা আপনার উত্তরটিকে আমার সমস্যার সাথে সরাসরি প্রাসঙ্গিক করে তোলে। আমার প্রধান সমস্যাটি ছিল এক্সএমএল-তে ইউটিএফ -8 ঘোষণা, তবে আরও সঠিক হতে হবে আমার একটি স্ট্রিংয়ের মধ্যস্থতাকারী এড়ানো উচিত যাতে আমি প্ল্যাটফর্ম নির্ভরতার পরিবর্তে ইউটিএফ -8 বাইটগুলি প্রকৃত প্রেরণ / চালিয়ে যেতে পারি (আমার মনে হয়) এনকোডিং।
গ্যারি শাটলার

উত্তর:


55

আপনার কোডটি ইউটিএফ -8 মেমরির সাথে পুনরায় স্ট্রিংতে পড়বে না, সুতরাং এটি আর ইউটিএফ -8 এ থাকবে না, তবে ইউটিএফ -16 এ ফিরে আসবে (যদিও আদর্শের চেয়ে উচ্চতর স্তরের স্ট্রিংগুলি বিবেচনা করার পক্ষে এটি সর্বোত্তম কোনও এনকোডিং, যখন তা করতে বাধ্য করা ব্যতীত)।

আসল ইউটিএফ -8 অক্টেটগুলি পেতে আপনি ব্যবহার করতে পারেন:

var serializer = new XmlSerializer(typeof(SomeSerializableObject));

var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream, System.Text.Encoding.UTF8);

serializer.Serialize(streamWriter, entry);

byte[] utf8EncodedXml = memoryStream.ToArray();

আপনি যে একই ব্যবস্থা রেখে গেছেন তা আমি ফেলে রেখেছি। আমি সামান্য নীচের পক্ষে (সাধারণ নিষ্পত্তি বাকি):

var serializer = new XmlSerializer(typeof(SomeSerializableObject));
using(var memStm = new MemoryStream())
using(var  xw = XmlWriter.Create(memStm))
{
  serializer.Serialize(xw, entry);
  var utf8 = memStm.ToArray();
}

যা জটিলতার অনেকটাই সমান, তবে এটি দেখায় যে প্রতিটি পর্যায়ে অন্য কিছু করার জন্য যুক্তিসঙ্গত পছন্দ রয়েছে, যার মধ্যে সবচেয়ে বেশি চাপ মেমোরি বাদে অন্য কোথাও যেমন সিরিয়াল করা যেমন একটি ফাইল, টিসিপি / আইপি স্ট্রিম, ডাটাবেস, ইত্যাদি সব মিলিয়ে, এটি সত্যই ভারবস নয়।


4
এছাড়াও। আপনি বিওএম দমন করতে চাইলে আপনি ব্যবহার করতে পারেন XmlWriter.Create(memoryStream, new XmlWriterSettings { Encoding = new UTF8Encoding(false) })
ony

যদি কাউকে (আমার মতো) জোন শোয়ের মতো তৈরি এক্সএমএল পড়তে হয় তবে মেমরি স্ট্রিমটি 0 এ প্রতিস্থাপন করতে ভুলবেন না, তবে "রুটের উপাদান অনুপস্থিত" বলে আপনি একটি ব্যতিক্রম পাবেন। সুতরাং এটি করুন: memStm.Position = 0; XMLReader xmlReader = XMLReader.Create (memStm)
সুধাংশু মিশ্র

276

না, আপনি StringWriterমধ্যবর্তী থেকে মুক্তি পেতে একটি ব্যবহার করতে পারেন MemoryStream। তবে এটি XML এ জোর করার জন্য আপনাকে এমন একটি জিনিস ব্যবহার করতে হবে StringWriterযা Encodingসম্পত্তিটিকে ওভাররাইড করে :

public class Utf8StringWriter : StringWriter
{
    public override Encoding Encoding => Encoding.UTF8;
}

অথবা আপনি যদি এখনও সি # 6 ব্যবহার করছেন না:

public class Utf8StringWriter : StringWriter
{
    public override Encoding Encoding { get { return Encoding.UTF8; } }
}

তারপর:

var serializer = new XmlSerializer(typeof(SomeSerializableObject));
string utf8;
using (StringWriter writer = new Utf8StringWriter())
{
    serializer.Serialize(writer, entry);
    utf8 = writer.ToString();
}

স্পষ্টতই আপনি Utf8StringWriterআরও সাধারণ শ্রেণি তৈরি করতে পারেন যা এর নির্মাতায় যে কোনও এনকোডিং গ্রহণ করে - তবে আমার অভিজ্ঞতায় ইউটিএফ -8 হ'ল একেবারে সাধারণভাবে প্রয়োজনীয় একটি "কাস্টম" এনকোডিং StringWriter:) এর জন্য :)

এখন জো হান্না যেমন বলেছেন, এটি অভ্যন্তরীণভাবে ইউটিএফ -১ 16 হবে, তবে সম্ভবত আপনি এটিকে বাইনারি ডেটাতে রূপান্তর করতে কোনও এক সময় এটি অন্য কোনও কিছুতে পাঠিয়ে যাচ্ছেন ... সেই সময়ে আপনি উপরের স্ট্রিংটি ব্যবহার করতে পারেন, এটিকে ইউটিএফ -8 বাইটে রূপান্তর করুন এবং সমস্ত কিছু ঠিকঠাক হবে - কারণ এক্সএমএল ঘোষণাটি "utf-8" কে এনকোডিং হিসাবে নির্দিষ্ট করবে।

সম্পাদনা: এই কাজটি দেখানোর জন্য একটি সংক্ষিপ্ত তবে সম্পূর্ণ উদাহরণ:

using System;
using System.Text;
using System.IO;
using System.Xml.Serialization;

public class Test
{    
    public int X { get; set; }

    static void Main()
    {
        Test t = new Test();
        var serializer = new XmlSerializer(typeof(Test));
        string utf8;
        using (StringWriter writer = new Utf8StringWriter())
        {
            serializer.Serialize(writer, t);
            utf8 = writer.ToString();
        }
        Console.WriteLine(utf8);
    }


    public class Utf8StringWriter : StringWriter
    {
        public override Encoding Encoding => Encoding.UTF8;
    }
}

ফলাফল:

<?xml version="1.0" encoding="utf-8"?>
<Test xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <X>0</X>
</Test>

"Utf-8" এর ঘোষিত এনকোডিংটি নোট করুন যা আমরা যা চেয়েছিলাম তা বিশ্বাস করি।


2
এমনকি আপনি যখন স্ট্রিং রাইটারে এনকোডিং প্যারামিটারটি ওভাররাইড করেন তখনও এটি স্ট্রিংবিল্ডারের কাছে লিখিত ডেটা প্রেরণ করে, তাই এটি এখনও ইউটিএফ -16 রয়েছে। এবং স্ট্রিংটি কেবল ইউটিএফ -16 হতে পারে।
জন হানা

3
@ জন: আপনি কি চেষ্টা করেছেন? আমার আছে, এবং এটি কাজ করে। এটি ঘোষিত এনকোডিং যা এখানে গুরুত্বপূর্ণ; স্পষ্টতই অভ্যন্তরীণভাবে স্ট্রিংটি এখনও ইউটিএফ -16, তবে এটি বাইনারি রূপান্তরিত হওয়া অবধি কোনও পার্থক্য তৈরি করে না (যা ইউটিএফ -8 সহ যে কোনও এনকোডিং ব্যবহার করতে পারে)। TextWriter.Encodingসম্পত্তি এক্সএমএল serializer দ্বারা ব্যবহৃত হয়, যা এনকোডিং নাম দস্তাবেজগুলির মধ্যেই নির্দিষ্ট করার নির্ধারণ।
জন স্কিটি

2
@ জন: এবং ঘোষিত এনকোডিংটি কী ছিল? আমার অভিজ্ঞতায়, এটির মতো প্রশ্নগুলি আসলেই চেষ্টা করার চেষ্টা করছে - একটি এক্সএমএল নথি তৈরি করুন যা নিজেকে ইউটিএফ -8 এ ঘোষণা করে। আপনি যেমনটি বলেছেন, আপনার প্রয়োজন না হওয়া পর্যন্ত পাঠ্যটিকে কোনও এনকোডিং হিসাবে না রাখাই ভাল ... তবে এক্সএমএল ডকুমেন্টটি একটি এনকোডিং ঘোষণা করার সাথে সাথে এটি আপনাকে বিবেচনা করা উচিত।
জন স্কিটি

2
@ গ্যারি, আমি এখনই ভাবতে পারি সবচেয়ে সহজ হ'ল আমার উত্তরের দ্বিতীয় উদাহরণটি গ্রহণ করা, কিন্তু আপনি যখন XmlWriterকারখানাটি এমন কোনও ব্যবস্থা তৈরি করেন যা কোনও XmlWriterSettingsবস্তু গ্রহণ করে এবং OmitXmlDeclarationসম্পত্তি সেট করে দেয় true
জন হান্না

4
+1 আপনার Utf8StringWriterসমাধানটি অত্যন্ত সুন্দর এবং পরিষ্কার
অ্যাড্রিয়ানো কার্নেইরো

17

উত্তরাধিকার ব্যবহার করে খুব ভাল উত্তর, কেবল আরম্ভকারীটিকে ওভাররাইড করতে মনে রাখবেন

public class Utf8StringWriter : StringWriter
{
    public Utf8StringWriter(StringBuilder sb) : base (sb)
    {
    }
    public override Encoding Encoding { get { return Encoding.UTF8; } }
}

ধন্যবাদ, আমি এটি বিকল্পগুলির মধ্যে সবচেয়ে মার্জিত বলে মনে করি
প্রোকুরার্স

5

আমি এই ব্লগ পোস্টটি পেয়েছি যা সমস্যাটি খুব ভালভাবে ব্যাখ্যা করে এবং কয়েকটি পৃথক সমাধান সংজ্ঞায়িত করে:

(মৃত লিঙ্ক সরানো হয়েছে)

আমি এই ধারণার জন্য স্থির করেছি যে এটি করার সর্বোত্তম উপায় হ'ল স্মৃতিতে থাকা অবস্থায় এক্সএমএল ঘোষণাটি পুরোপুরি বাদ দেওয়া। এটা আসলে হয় যাহাই হউক না কেন যে সময়ে হল UTF-16, কিন্তু এক্সএমএল ঘোষণা অর্থপূর্ণ বলে মনে হচ্ছে না হওয়া পর্যন্ত একটি নির্দিষ্ট এনকোডিং এর সাথে একটি ফাইলে লেখা হয়েছে; এবং তারপরেও ঘোষণার প্রয়োজন হয় না। এটি কমপক্ষে ডিসরিয়ালাইজেশন ভঙ্গ করবে বলে মনে হয় না।

@ জন হানা যেমন উল্লেখ করেছেন, এটি তৈরি করা একটি এক্সএমএল রাইটার দিয়ে এটি করা যেতে পারে:

XmlWriter writer = XmlWriter.Create (output, new XmlWriterSettings() { OmitXmlDeclaration = true });
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.