Prawidłowe usuwanie obiektów zostało usunięte dla zwięzłości, ale jestem zszokowany, jeśli jest to najprostszy sposób zakodowania obiektu jako UTF-8 w pamięci. Musi być łatwiejszy sposób, prawda?
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();
c#
xml
utf-8
xml-serialization
Garry Shutler
źródło
źródło
utf8EncodedXml
UTF-16.Odpowiedzi:
Twój kod nie umieszcza UTF-8 w pamięci, gdy odczytujesz go z powrotem w łańcuchu, więc nie jest już w UTF-8, ale z powrotem w UTF-16 (chociaż najlepiej byłoby rozważyć łańcuchy na wyższym poziomie niż jakiekolwiek kodowanie, z wyjątkiem sytuacji, gdy jest to do tego zmuszone).
Aby uzyskać rzeczywiste oktety UTF-8, możesz użyć:
Pominąłem tę samą dyspozycję, którą zostawiłeś. Nieznacznie preferuję następujące (z pozostawieniem normalnej utylizacji):
Jest to mniej więcej taka sama złożoność, ale pokazuje, że na każdym etapie istnieje rozsądny wybór zrobienia czegoś innego, z czego najpilniejszą jest serializacja do innego miejsca niż do pamięci, na przykład do pliku TCP / IP strumień, baza danych itp. Podsumowując, nie jest to aż tak szczegółowe.
źródło
XmlWriter.Create(memoryStream, new XmlWriterSettings { Encoding = new UTF8Encoding(false) })
.Nie, możesz użyć a,
StringWriter
aby pozbyć się półproduktuMemoryStream
. Jednak, aby wymusić na XML, musisz użyć a,StringWriter
który zastępujeEncoding
właściwość:Lub jeśli jeszcze nie używasz C # 6:
Następnie:
Oczywiście możesz uczynić
Utf8StringWriter
bardziej ogólną klasę, która akceptuje dowolne kodowanie w swoim konstruktorze - ale z mojego doświadczenia wynika, że UTF-8 jest zdecydowanie najczęściej wymaganym "niestandardowym" kodowaniem dlaStringWriter
:)Teraz, jak mówi Jon Hanna, nadal będzie to wewnętrznie UTF-16, ale prawdopodobnie w pewnym momencie przekażesz go do czegoś innego, aby przekonwertować go na dane binarne ... w tym momencie możesz użyć powyższego ciągu, przekonwertuj go na bajty UTF-8 i wszystko będzie dobrze - ponieważ deklaracja XML określi "utf-8" jako kodowanie.
EDYCJA: Krótki, ale kompletny przykład pokazujący, jak działa:
Wynik:
Zwróć uwagę na deklarowane kodowanie „utf-8”, które, jak sądzę, było tym, czego chcieliśmy.
źródło
TextWriter.Encoding
Właściwość jest używana przez serializatora XML w celu określenia, które kodowanie nazwa określić w samym dokumencie.XmlWriter
to z metodą fabryczną, która przyjmujeXmlWriterSettings
obiekt i maOmitXmlDeclaration
właściwość ustawioną natrue
.Utf8StringWriter
rozwiązanie jest niezwykle ładne i czysteBardzo dobra odpowiedź wykorzystująca dziedziczenie, pamiętaj tylko o nadpisaniu inicjalizatora
źródło
Znalazłem ten wpis na blogu, który bardzo dobrze wyjaśnia problem i definiuje kilka różnych rozwiązań:
(usunięto martwy link)
Zdecydowałem się na pomysł, że najlepszym sposobem na to jest całkowite pominięcie deklaracji XML w pamięci. W rzeczywistości i tak jest to UTF-16, ale deklaracja XML nie wydaje się sensowna, dopóki nie zostanie zapisana w pliku z określonym kodowaniem; i nawet wtedy deklaracja nie jest wymagana. Przynajmniej nie wydaje się przerywać deserializacji.
Jak wspomina @Jon Hanna, można to zrobić za pomocą XmlWriter utworzonego w następujący sposób:
źródło