Wie konvertiere ich eine string
in eine byte[]
in .NET (C #), ohne manuell eine bestimmte Codierung anzugeben?
Ich werde die Zeichenfolge verschlüsseln. Ich kann es verschlüsseln, ohne es zu konvertieren, aber ich möchte trotzdem wissen, warum hier die Codierung zum Tragen kommt.
Warum sollte die Kodierung überhaupt berücksichtigt werden? Kann ich nicht einfach abrufen, in welchen Bytes die Zeichenfolge gespeichert wurde? Warum besteht eine Abhängigkeit von Zeichenkodierungen?
c#
.net
string
character-encoding
Agnel Kurian
quelle
quelle
Antworten:
Im Gegensatz zu den Antworten hier müssen Sie sich keine Gedanken über die Codierung machen, wenn die Bytes nicht interpretiert werden müssen!
Wie Sie bereits erwähnt haben, besteht Ihr Ziel einfach darin, "herauszufinden, in welchen Bytes die Zeichenfolge gespeichert wurde" .
(Und natürlich, um den String aus den Bytes rekonstruieren zu können.)
Für diese Ziele verstehe ich ehrlich gesagt nicht , warum die Leute Ihnen immer wieder sagen, dass Sie die Kodierungen benötigen. Sie müssen sich hierfür KEINE Gedanken über Codierungen machen.
Tun Sie dies stattdessen einfach:
Solange Ihr Programm (oder andere Programme) nicht versucht, die Bytes irgendwie zu interpretieren , was Sie offensichtlich nicht erwähnt haben, ist an diesem Ansatz nichts auszusetzen! Wenn Sie sich um Kodierungen sorgen, wird Ihr Leben ohne wirklichen Grund komplizierter.
Zusätzlicher Vorteil dieses Ansatzes:
Es spielt keine Rolle, ob die Zeichenfolge ungültige Zeichen enthält, da Sie die Daten trotzdem abrufen und die ursprüngliche Zeichenfolge rekonstruieren können!
Es wird trotzdem codiert und decodiert, da Sie nur die Bytes betrachten .
Wenn Sie jedoch eine bestimmte Codierung verwendet hätten, hätten Sie Probleme beim Codieren / Decodieren ungültiger Zeichen.
quelle
GetString
undGetBytes
auf einem System mit der gleichen Endianness ausgeführt werden müssen, um zu arbeiten. Sie können dies also nicht verwenden, um Bytes abzurufen, die Sie an anderer Stelle in eine Zeichenfolge umwandeln möchten. Es fällt mir also schwer, Situationen zu finden, in denen ich dies nutzen möchte.Dies hängt von der Codierung Ihrer Zeichenfolge ab ( ASCII , UTF-8 , ...).
Zum Beispiel:
Ein kleines Beispiel, warum Codierung wichtig ist:
ASCII ist einfach nicht für Sonderzeichen gerüstet.
Intern verwendet das .NET-Framework UTF-16 zur Darstellung von Zeichenfolgen. Wenn Sie also einfach die genauen Bytes abrufen möchten, die .NET verwendet, verwenden Sie
System.Text.Encoding.Unicode.GetBytes (...)
.Weitere Informationen finden Sie unter Zeichenkodierung in .NET Framework (MSDN).
quelle
Die akzeptierte Antwort ist sehr, sehr kompliziert. Verwenden Sie dazu die enthaltenen .NET-Klassen:
Erfinden Sie das Rad nicht neu, wenn Sie nicht ...
quelle
System.Text.Encoding.Unicode
der Antwort von Mehrdad entsprechen.System.Text.Encoding.Unicode.GetBytes
wäre wahrscheinlich genauer.quelle
Sie müssen die Codierung berücksichtigen, da 1 Zeichen durch 1 oder mehr Bytes (bis zu etwa 6) dargestellt werden kann und unterschiedliche Codierungen diese Bytes unterschiedlich behandeln.
Joel hat einen Beitrag dazu:
quelle
Dies ist eine beliebte Frage. Es ist wichtig zu verstehen, was der Autor der Frage stellt und dass es sich von dem unterscheidet, was wahrscheinlich am häufigsten benötigt wird. Um den Missbrauch des Codes dort zu verhindern, wo er nicht benötigt wird, habe ich den späteren zuerst beantwortet.
Gemeinsames Bedürfnis
Jede Zeichenfolge hat einen Zeichensatz und eine Codierung. Wenn Sie ein
System.String
Objekt in ein Array von konvertieren,System.Byte
haben Sie immer noch einen Zeichensatz und eine Codierung. Für die meisten Anwendungen wissen Sie, welchen Zeichensatz und welche Codierung Sie benötigen, und .NET macht es einfach, "mit Konvertierung zu kopieren". Wählen Sie einfach die entsprechendeEncoding
Klasse.Die Konvertierung muss möglicherweise Fälle behandeln, in denen der Zielzeichensatz oder die Codierung kein Zeichen in der Quelle unterstützt. Sie haben einige Möglichkeiten: Ausnahme, Ersetzung oder Überspringen. Die Standardrichtlinie besteht darin, ein '?' Zu ersetzen.
Conversions sind natürlich nicht unbedingt verlustfrei!
Hinweis:
System.String
Der Quellzeichensatz ist Unicode.Das einzig Verwirrende ist, dass .NET den Namen eines Zeichensatzes für den Namen einer bestimmten Codierung dieses Zeichensatzes verwendet.
Encoding.Unicode
sollte aufgerufen werdenEncoding.UTF16
.Das war's für die meisten Verwendungen. Wenn Sie das brauchen, hören Sie hier auf zu lesen. Lesen Sie den lustigen Artikel von Joel Spolsky, wenn Sie nicht verstehen, was eine Codierung ist.
Spezifischer Bedarf
Nun fragt der Autor der Frage: "Jede Zeichenfolge wird als Array von Bytes gespeichert, richtig? Warum kann ich diese Bytes nicht einfach haben?"
Er will keine Bekehrung.
Aus der C # -Spezifikation :
Wir wissen also, dass wir das gewünschte Ergebnis erhalten, wenn wir nach der Nullkonvertierung fragen (dh von UTF-16 nach UTF-16):
Aber um die Erwähnung von Kodierungen zu vermeiden, müssen wir es anders machen. Wenn ein Zwischendatentyp akzeptabel ist, gibt es dafür eine konzeptionelle Verknüpfung:
Das bringt uns nicht den gewünschten Datentyp, aber Mehrdads Antwort zeigt, wie dieses Char-Array mit BlockCopy in ein Byte-Array konvertiert wird . Dies kopiert die Zeichenfolge jedoch zweimal! Außerdem wird explizit codierungsspezifischer Code verwendet: der Datentyp
System.Char
.Der einzige Weg, um zu den tatsächlichen Bytes zu gelangen, in denen der String gespeichert ist, ist die Verwendung eines Zeigers. Die
fixed
Anweisung ermöglicht die Angabe der Adresse von Werten. Aus der C # -Spezifikation:Zu diesem Zweck schreibt der Compiler Code, der die anderen Teile des Zeichenfolgenobjekts mit überspringt
RuntimeHelpers.OffsetToStringData
. Um die Rohbytes zu erhalten, erstellen Sie einfach einen Zeiger auf die Zeichenfolge und kopieren Sie die Anzahl der benötigten Bytes.Wie @CodesInChaos hervorhob, hängt das Ergebnis von der Endianness der Maschine ab. Aber der Fragesteller befasst sich nicht damit.
quelle
Length
Eigenschaft [vonString
] gibt die Anzahl derChar
Objekte in dieser Instanz zurück, nicht die Anzahl der Unicode-Zeichen." Ihr Beispielcode ist daher wie geschrieben korrekt.new String(new []{'\uD800', '\u0030'})
Globalization.SortKey
,KeyData
die resultierenden Bytes extrahiert und die resultierenden Bytes von jedem in einString
[zwei Bytes pro Zeichen, MSB zuerst ] packt sogar diese Instanzen aufrufen . Da frage ich mich , warum eine zurückkehrt , anstatt ein ?String.CompareOrdinal
SortKey.Compare
SortKey
memcmp
KeyData
Byte[]
String
Der erste Teil Ihrer Frage (wie man die Bytes erhält) wurde bereits von anderen beantwortet: Schauen Sie in den
System.Text.Encoding
Namespace.Ich werde auf Ihre Folgefrage eingehen: Warum müssen Sie eine Codierung auswählen? Warum können Sie das nicht von der String-Klasse selbst bekommen?
Die Antwort besteht aus zwei Teilen.
Erstens spielen die von der Zeichenfolgenklasse intern verwendeten Bytes keine Rolle , und wann immer Sie davon ausgehen, dass dies der Fall ist, führen Sie wahrscheinlich einen Fehler ein.
Wenn sich Ihr Programm vollständig in der .NET-Welt befindet, müssen Sie sich keine Gedanken darüber machen, ob Sie Byte-Arrays für Zeichenfolgen erhalten, selbst wenn Sie Daten über ein Netzwerk senden. Verwenden Sie stattdessen .Net Serialization, um sich Gedanken über die Übertragung der Daten zu machen. Sie kümmern sich nicht mehr um die tatsächlichen Bytes: Der Serialisierungsformatierer erledigt dies für Sie.
Was ist andererseits, wenn Sie diese Bytes an einen Ort senden, von dem Sie nicht garantieren können, dass sie Daten aus einem serialisierten .Net-Stream abrufen? In diesem Fall müssen Sie sich definitiv um die Codierung kümmern, da sich dieses externe System offensichtlich darum kümmert. Auch hier spielen die von der Zeichenfolge verwendeten internen Bytes keine Rolle: Sie müssen eine Codierung auswählen, damit Sie diese Codierung auf der Empfangsseite explizit angeben können, selbst wenn es sich um dieselbe Codierung handelt, die intern von .Net verwendet wird.
Ich verstehe, dass Sie in diesem Fall möglicherweise die tatsächlichen Bytes verwenden möchten, die von der Zeichenfolgenvariablen im Speicher gespeichert werden, wenn dies möglich ist, mit der Idee, dass dadurch möglicherweise etwas Arbeit beim Erstellen Ihres Bytestreams gespart wird. Ich sage es Ihnen jedoch, es ist einfach nicht wichtig, um sicherzustellen, dass Ihre Ausgabe am anderen Ende verstanden wird, und um sicherzustellen, dass Sie mit Ihrer Codierung explizit sein müssen . Wenn Sie wirklich mit Ihren internen Bytes übereinstimmen möchten, können Sie bereits die
Unicode
Codierung auswählen und so Leistungseinsparungen erzielen.Das bringt mich zum zweiten Teil ... die Kommissionierung
Unicode
Codierung wird sagen , .Net , die zugrunde liegende Bytes zu verwenden. Sie müssen diese Codierung auswählen, da die .Net-Laufzeit frei sein muss, um dieses neuere, bessere Codierungsmodell zu verwenden, ohne Ihr Programm zu beschädigen, wenn ein neues Unicode-Plus herauskommt. Für den Moment (und die absehbare Zukunft) erhalten Sie jedoch nur das, was Sie möchten, wenn Sie nur die Unicode-Codierung auswählen.Es ist auch wichtig zu verstehen, dass Ihre Zeichenfolge neu in Wire geschrieben werden muss, und dies beinhaltet zumindest eine gewisse Übersetzung des Bitmusters, selbst wenn Sie eine passende Codierung verwenden . Der Computer muss Dinge wie Big vs Little Endian, Netzwerkbyte-Reihenfolge, Paketierung, Sitzungsinformationen usw. berücksichtigen.
quelle
Um zu demonstrieren, dass Mehrdrads fundierte Antwort funktioniert, kann sein Ansatz sogar die ungepaarten Ersatzzeichen beibehalten (von denen sich viele gegen meine Antwort geeinigt hatten, von denen jedoch alle gleichermaßen schuldig sind, z. B.
System.Text.Encoding.UTF8.GetBytes
könnenSystem.Text.Encoding.Unicode.GetBytes
diese Codierungsmethoden das hohe Ersatzzeichen nicht beibehalten Zeichend800
zum Beispiel, und diese ersetzen lediglich hohe Ersatzzeichen durch Wertfffd
):Ausgabe:
Versuchen Sie dies mit System.Text.Encoding.UTF8.GetBytes oder System.Text.Encoding.Unicode.GetBytes . Sie ersetzen lediglich hohe Ersatzzeichen durch den Wert fffd
Jedes Mal, wenn sich diese Frage bewegt, denke ich immer noch an einen Serializer (sei es von Microsoft oder von einer Komponente eines Drittanbieters), der Zeichenfolgen beibehalten kann, selbst wenn er ungepaarte Ersatzzeichen enthält. Ich google dies ab und zu: Serialisierung ungepaartes Ersatzzeichen .NET . Das lässt mich keinen Schlaf verlieren, aber es ist irgendwie ärgerlich, wenn ab und zu jemand meine Antwort kommentiert, dass sie fehlerhaft ist, aber ihre Antworten sind ebenso fehlerhaft, wenn es um ungepaarte Ersatzcharaktere geht.
Verdammt, Microsoft hätte gerade
System.Buffer.BlockCopy
in seinemBinaryFormatter
ツ verwenden sollen谢谢!
quelle
System.Buffer.BlockCopy
intern verwendet wird, sind alle Argumente der Kodierungsanwälte umstrittenFFFD
bei diesem Zeichen führt. Wenn Sie eine manuelle Zeichenfolgenmanipulation durchführen möchten, verwenden Sie wie empfohlen ein Zeichen [].System.String
ist eine unveränderliche Folge vonChar
; .NET hat immer zugelassen, dass einString
Objekt aus einem beliebigen Objekt erstelltChar[]
und sein Inhalt in ein Objekt exportiert wirdChar[]
, das dieselben Werte enthält, auch wenn das OriginalChar[]
ungepaarte Ersatzzeichen enthält.Versuchen Sie dies, viel weniger Code:
quelle
System.Text.Encoding.UTF8.GetBytes("Árvíztűrő tükörfúrógép);
und weinen Sie! Es wird funktionieren, aberSystem.Text.Encoding.UTF8.GetBytes("Árvíztűrő tükörfúrógép").Length != System.Text.Encoding.UTF8.GetBytes("Arvizturo tukorfurogep").Length
während"Árvíztűrő tükörfúrógép".Length == "Arvizturo tukorfurogep".Length
Nun, ich habe alle Antworten gelesen und es ging um die Verwendung von Codierung oder um Serialisierung, bei der ungepaarte Surrogate gelöscht werden.
Es ist schlecht, wenn die Zeichenfolge beispielsweise von SQL Server stammt, wo sie aus einem Byte-Array erstellt wurde, in dem beispielsweise ein Kennwort-Hash gespeichert ist. Wenn wir etwas daraus löschen, wird ein ungültiger Hash gespeichert, und wenn wir ihn in XML speichern möchten, möchten wir ihn intakt lassen (da der XML-Writer eine Ausnahme für jeden gefundenen ungepaarten Ersatz löscht).
In solchen Fällen verwende ich die Base64- Codierung von Byte-Arrays, aber hey, im Internet gibt es nur eine Lösung für dieses Problem in C #, und es enthält einen Fehler und ist nur eine Möglichkeit. Deshalb habe ich den Fehler behoben und zurückgeschrieben Verfahren. Hier sind Sie, zukünftige Googler:
quelle
Convert.ToBase64String(arr);
für die base64-Konvertierungen verwendetbyte[] (data) <-> string (serialized data to store in XML file)
. Aber um die Initialebyte[] (data)
zu erhalten, musste ich etwas mit einem machenString
, das Binärdaten enthielt (so hat MSSQL es mir zurückgegeben). SO sind die obigen Funktionen fürString (binary data) <-> byte[] (easy accessible binary data)
.Weil es so etwas wie "die Bytes der Zeichenfolge" nicht gibt.
Eine Zeichenfolge (oder allgemeiner ein Text) besteht aus Zeichen: Buchstaben, Ziffern und anderen Symbolen. Das ist alles. Computer wissen jedoch nichts über Zeichen; Sie können nur Bytes verarbeiten. Wenn Sie Text mithilfe eines Computers speichern oder übertragen möchten, müssen Sie die Zeichen in Bytes umwandeln. Wie machst du das? Hier kommen Kodierungen ins Spiel.
Eine Codierung ist nichts anderes als eine Konvention, um logische Zeichen in physische Bytes zu übersetzen. Die einfachste und bekannteste Codierung ist ASCII, und es ist alles, was Sie brauchen, wenn Sie auf Englisch schreiben. Für andere Sprachen benötigen Sie vollständigere Codierungen, da jede der Unicode-Varianten heutzutage die sicherste Wahl ist.
Kurz gesagt, der Versuch, "die Bytes einer Zeichenfolge ohne Verwendung von Codierungen abzurufen", ist ebenso unmöglich wie "das Schreiben eines Textes ohne Verwendung einer Sprache".
Übrigens empfehle ich Ihnen (und jedem anderen) dringend, dieses kleine Stück Weisheit zu lesen: Das absolute Minimum, das jeder Softwareentwickler unbedingt über Unicode- und Zeichensätze wissen muss (keine Ausreden!)
quelle
C #, um a
string
in einbyte
Array zu konvertieren :quelle
quelle
Sie können den folgenden Code für die Konvertierung zwischen Zeichenfolge und Byte-Array verwenden.
quelle
Mit dem Aufkommen der
Span<T>
Veröffentlichung mit C # 7.2 lautet die kanonische Technik zum Erfassen der zugrunde liegenden Speicherdarstellung eines Strings in einem verwalteten Byte-Array:Das Zurückkonvertieren sollte kein Starter sein, da dies bedeutet, dass Sie die Daten tatsächlich irgendwie interpretieren, aber der Vollständigkeit halber:
Die Namen
NonPortableCast
undDangerousGetPinnableReference
sollten das Argument fördern, dass Sie dies wahrscheinlich nicht tun sollten.Beachten Sie, dass für die Arbeit mit
Span<T>
das System.Memory NuGet-Paket installiert werden muss .Unabhängig davon implizieren die eigentliche ursprüngliche Frage und die nachfolgenden Kommentare, dass der zugrunde liegende Speicher nicht "interpretiert" wird (was meiner Meinung nach bedeutet, dass das Mittel nicht geändert oder gelesen wird, ohne dass es so geschrieben werden muss, wie es ist), was auf eine gewisse Implementierung der
Stream
Klasse hinweist sollte verwendet werden, anstatt über die Daten als Zeichenfolgen nachzudenken.quelle
Ich bin nicht sicher, aber ich denke, der String speichert seine Informationen als Array von Zeichen, was mit Bytes ineffizient ist. Insbesondere lautet die Definition eines Zeichens "Repräsentiert ein Unicode-Zeichen".
Nehmen Sie dieses Beispielbeispiel:
Beachten Sie, dass die Unicode-Antwort in beiden Fällen 14 Byte beträgt, während die UTF-8-Antwort für die erste nur 9 Byte und für die zweite nur 7 Byte beträgt.
Wenn Sie also nur die von der Zeichenfolge verwendeten Bytes möchten, verwenden Sie einfach
Encoding.Unicode
, aber der Speicherplatz ist ineffizient.quelle
Das Hauptproblem besteht darin, dass eine Glyphe in einer Zeichenfolge 32 Bit benötigt (16 Bit für einen Zeichencode), ein Byte jedoch nur 8 Bit übrig hat. Eine Eins-zu-Eins-Zuordnung gibt es nur, wenn Sie sich auf Zeichenfolgen beschränken, die nur ASCII-Zeichen enthalten. System.Text.Encoding bietet viele Möglichkeiten, eine Zeichenfolge Byte [] zuzuordnen. Sie müssen eine auswählen, die Informationsverlust vermeidet und von Ihrem Client einfach verwendet werden kann, wenn er das Byte [] wieder einer Zeichenfolge zuordnen muss .
Utf8 ist eine beliebte Codierung, kompakt und nicht verlustbehaftet.
quelle
Verwenden:
Das Ergebnis ist:
quelle
Schnellste Weg
EDIT als Makotosan kommentierte dies ist jetzt die beste Art und Weise:
quelle
Eine Zeichenfolge in .NET stellt Text als Folge von UTF-16-Codeeinheiten dar, sodass die Bytes bereits in UTF-16 im Speicher codiert sind.
Mehrdads Antwort
Sie können Mehrdads Antwort verwenden , aber es wird tatsächlich eine Codierung verwendet, da die Zeichen UTF-16 sind. Es ruft ToCharArray auf, das beim Betrachten der Quelle ein erstellt
char[]
und den Speicher direkt darauf kopiert. Anschließend werden die Daten in ein Byte-Array kopiert, das ebenfalls zugewiesen ist. Unter der Haube werden also die zugrunde liegenden Bytes zweimal kopiert und ein char-Array zugewiesen, das nach dem Aufruf nicht verwendet wird.Tom Blodgets Antwort
Die Antwort von Tom Blodget ist 20 bis 30% schneller als die von Mehrdad, da der Zwischenschritt des Zuweisens eines char-Arrays und des Kopierens der Bytes übersprungen wird. Sie müssen jedoch mit der
/unsafe
Option kompilieren . Wenn Sie absolut keine Codierung verwenden möchten, ist dies meiner Meinung nach der richtige Weg. Wenn Sie Ihr Verschlüsselungs-Login in denfixed
Block einfügen, müssen Sie nicht einmal ein separates Byte-Array zuweisen und die Bytes darauf kopieren.Weil das der richtige Weg ist.
string
ist eine Abstraktion.Die Verwendung einer Codierung kann zu Problemen führen, wenn Sie Zeichenfolgen mit ungültigen Zeichen haben. Dies sollte jedoch nicht passieren. Wenn Sie Daten mit ungültigen Zeichen in Ihre Zeichenfolge aufnehmen, machen Sie es falsch. Sie sollten wahrscheinlich zunächst ein Byte-Array oder eine Base64-Codierung verwenden.
Wenn Sie verwenden
System.Text.Encoding.Unicode
, ist Ihr Code widerstandsfähiger. Sie müssen sich keine Sorgen um die Endianness machen des Systems machen, auf dem Ihr Code ausgeführt wird. Sie müssen sich keine Sorgen machen, wenn die nächste Version der CLR eine andere interne Zeichenkodierung verwendet.Ich denke, die Frage ist nicht, warum Sie sich um die Codierung kümmern möchten, sondern warum Sie sie ignorieren und etwas anderes verwenden möchten. Die Codierung soll die Abstraktion einer Zeichenfolge in einer Folge von Bytes darstellen.
System.Text.Encoding.Unicode
Sie erhalten eine kleine Codierung der Endian-Byte-Reihenfolge und können dies jetzt und in Zukunft auf jedem System tun.quelle
Der Ansatz, der dem OP am nächsten kommt, ist der von Tom Blodget, der tatsächlich in das Objekt geht und die Bytes extrahiert. Ich sage am nächsten, weil es von der Implementierung des String-Objekts abhängt.
Sicher, aber hier entsteht der grundlegende Fehler in der Frage. Der String ist ein Objekt, das eine interessante Datenstruktur haben könnte. Wir wissen es bereits, weil es ermöglicht, ungepaarte Surrogate zu speichern. Es könnte die Länge speichern. Es könnte einen Zeiger auf jeden der 'gepaarten' Surrogate behalten, was ein schnelles Zählen ermöglicht. Alle diese zusätzlichen Bytes sind nicht Teil der Zeichendaten.
Was Sie wollen, sind die Bytes jedes Zeichens in einem Array. Und hier kommt die 'Codierung' ins Spiel. Standardmäßig erhalten Sie UTF-16LE. Wenn Sie sich nicht für die Bytes selbst interessieren, außer für den Roundtrip, können Sie eine beliebige Codierung einschließlich der 'Standardcodierung' auswählen und später wieder konvertieren (unter der Annahme derselben Parameter wie Standardcodierung, Codepunkte und Fehlerkorrekturen) , Dinge erlaubt wie ungepaarte Leihmütter, etc.
Aber warum sollte man die "Kodierung" der Magie überlassen? Warum nicht die Codierung angeben, damit Sie wissen, welche Bytes Sie erhalten werden?
Codierung (in diesem Zusammenhang) bedeutet einfach die Bytes, die Ihre Zeichenfolge darstellen. Nicht die Bytes des String-Objekts. Sie wollten die Bytes, in denen die Zeichenfolge gespeichert wurde - hier wurde die Frage naiv gestellt. Sie wollten die Zeichenfolgenbytes in einem zusammenhängenden Array, das die Zeichenfolge darstellt, und nicht alle anderen Binärdaten, die ein Zeichenfolgenobjekt enthalten kann.
Was bedeutet, wie eine Zeichenfolge gespeichert wird, ist irrelevant. Sie möchten eine Zeichenfolge, die in Bytes in einem Byte-Array "codiert" ist.
Ich mag die Antwort von Tom Bloget, weil er Sie in Richtung "Bytes des String-Objekts" geführt hat. Es hängt jedoch von der Implementierung ab, und da er sich Interna ansieht, kann es schwierig sein, eine Kopie der Zeichenfolge wiederherzustellen.
Mehrdads Antwort ist falsch, weil sie auf konzeptioneller Ebene irreführend ist. Sie haben noch eine Liste von codierten Bytes. Seine spezielle Lösung ermöglicht es, ungepaarte Surrogate zu erhalten - dies ist implementierungsabhängig. Seine spezielle Lösung würde die Bytes der Zeichenfolge nicht genau erzeugen, wenn
GetBytes
die Zeichenfolge standardmäßig in UTF-8 zurückgegeben würde.Ich habe meine Meinung dazu geändert (Mehrdads Lösung) - dies bekommt nicht die Bytes der Zeichenfolge; Vielmehr werden die Bytes des Zeichenarrays abgerufen, das aus der Zeichenfolge erstellt wurde. Unabhängig von der Codierung hat der Datentyp char in c # eine feste Größe. Dies ermöglicht die Erzeugung eines Byte-Arrays mit konsistenter Länge und die Wiedergabe des Zeichen-Arrays basierend auf der Größe des Byte-Arrays. Wenn also die Codierung UTF-8 wäre, aber jedes Zeichen 6 Byte groß wäre, um den größten utf8-Wert aufzunehmen, würde es immer noch funktionieren. In der Tat spielt die Kodierung des Zeichens keine Rolle.
Es wurde jedoch eine Konvertierung verwendet - jedes Zeichen wurde in ein Feld mit fester Größe (Zeichentyp von c #) eingefügt. Was diese Darstellung ist, spielt jedoch keine Rolle, was technisch die Antwort auf das OP ist. Also - wenn Sie trotzdem konvertieren wollen ... Warum nicht "codieren"?
quelle
&(Char) 55906
&(Char) 55655
. Sie können sich also irren und Mehrdads Antwort ist eine sichere Konvertierung, ohne zu berücksichtigen, welche Art von Codierungen verwendet werden.Sie können den folgenden Code verwenden, um
string
abyte array
in .NET zu konvertierenquelle
Wenn Sie wirklich eine Kopie der zugrunde liegenden Bytes einer Zeichenfolge möchten, können Sie eine Funktion wie die folgende verwenden. Sie sollten jedoch nicht weiterlesen, um herauszufinden, warum.
Mit dieser Funktion erhalten Sie ziemlich schnell eine Kopie der Bytes, die Ihrer Zeichenfolge zugrunde liegen. Sie erhalten diese Bytes auf jede Art und Weise, die sie auf Ihrem System codieren. Diese Codierung ist mit ziemlicher Sicherheit UTF-16LE, aber das ist ein Implementierungsdetail, um das Sie sich nicht kümmern sollten.
Es wäre sicherer, einfacher und zuverlässiger , einfach anzurufen.
Höchstwahrscheinlich führt dies zum gleichen Ergebnis, ist einfacher zu tippen und die Bytes werden immer mit einem Aufruf an umgeschaltet
quelle
Hier ist meine unsichere Umsetzung
String
zuByte[]
konvertieren:Es ist viel schneller als das der akzeptierten Antwort, auch wenn es nicht so elegant ist wie es ist. Hier sind meine Stoppuhr-Benchmarks über 10000000 Iterationen:
Um es zu verwenden, müssen Sie in Ihren Projekterstellungseigenschaften "Unsicheren Code zulassen" ankreuzen. Gemäß .NET Framework 3.5 kann diese Methode auch als Zeichenfolgenerweiterung verwendet werden:
quelle
RuntimeHelpers.OffsetToStringData
eines Vielfachen von 8 in den Itanium-Versionen von .NET? Andernfalls schlägt dies aufgrund der nicht ausgerichteten Lesevorgänge fehl.memcpy
? stackoverflow.com/a/27124232/659190Verwenden Sie einfach dies:
quelle
System.Text.ASCIIEncoding.Default.GetBytes("Árvíztűrő tükörfúrógép.").ToString();
gibt"Árvizturo tukörfurogép."
verlorene Informationen zurück, die nicht abgerufen werden können. (Und ich habe noch keine asiatischen Sprachen erwähnt, in denen Sie alle ZeichenDie Zeichenfolge kann aus folgenden Gründen auf verschiedene Weise in ein Byte-Array konvertiert werden: .NET unterstützt Unicode, und Unicode standardisiert mehrere Differenzcodierungen, die als UTFs bezeichnet werden. Sie haben unterschiedliche Längen der Bytedarstellung, sind jedoch in dem Sinne äquivalent, dass eine Zeichenfolge, wenn sie codiert wird, zurück in die Zeichenfolge codiert werden kann. Wenn die Zeichenfolge jedoch mit einer UTF codiert und unter der Annahme einer anderen UTF decodiert wird, wenn sie geschraubt werden kann oben.
Außerdem unterstützt .NET Nicht-Unicode-Codierungen, diese sind jedoch im Allgemeinen nicht gültig (nur gültig, wenn eine begrenzte Teilmenge des Unicode-Codepunkts in einer tatsächlichen Zeichenfolge wie ASCII verwendet wird). Intern unterstützt .NET UTF-16, für die Stream-Darstellung wird jedoch normalerweise UTF-8 verwendet. Es ist auch ein Standard für das Internet.
Es überrascht nicht, dass die Serialisierung von Zeichenfolgen in ein Array von Bytes und die Deserialisierung von der Klasse unterstützt wird
System.Text.Encoding
, die eine abstrakte Klasse ist. Die abgeleiteten Klassen unterstützen konkrete Codierungen:ASCIIEncoding
und vier UTFs (System.Text.UnicodeEncoding
unterstützt UTF-16)Ref diesen Link.
Zur Serialisierung in ein Array von Bytes mit
System.Text.Encoding.GetBytes
. Für die inverse Operation verwendenSystem.Text.Encoding.GetChars
. Diese Funktion gibt ein Array von Zeichen zurück. Um eine Zeichenfolge abzurufen, verwenden Sie einen ZeichenfolgenkonstruktorSystem.String(char[])
.Ref diese Seite.
Beispiel:
quelle
Es hängt davon ab, was Sie die Bytes für wollen
Dies liegt daran, wie Tyler so treffend sagte : "Strings sind keine reinen Daten. Sie haben auch Informationen ." In diesem Fall handelt es sich bei den Informationen um eine Codierung, die beim Erstellen der Zeichenfolge angenommen wurde.
Angenommen, Sie haben Binärdaten (anstelle von Text) in einer Zeichenfolge gespeichert
Dies basiert auf dem Kommentar von OP zu seiner eigenen Frage und ist die richtige Frage, wenn ich die Hinweise von OP auf den Anwendungsfall verstehe.
Das Speichern von Binärdaten in Strings ist aufgrund der oben erwähnten angenommenen Codierung wahrscheinlich der falsche Ansatz! Welches Programm oder welche Bibliothek diese Binärdaten in einem
string
(anstelle einesbyte[]
besser geeigneten Arrays) gespeichert hat, hat den Kampf bereits verloren, bevor er begonnen hat. Wenn sie die Bytes in einer REST-Anfrage / Antwort oder irgendetwas, das Zeichenfolgen übertragen muss, an Sie senden, wäre Base64 der richtige Ansatz.Wenn Sie eine Textzeichenfolge mit einer unbekannten Codierung haben
Alle anderen haben diese falsche Frage falsch beantwortet.
Wenn die Zeichenfolge so wie sie ist gut aussieht, wählen Sie einfach eine Codierung aus (vorzugsweise eine, die mit UTF beginnt), verwenden Sie die entsprechende
System.Text.Encoding.???.GetBytes()
Funktion und teilen Sie mit, wem Sie die Bytes für die ausgewählte Codierung geben.quelle
Auf die Frage, was Sie mit den Bytes machen wollen, antworteten Sie :
Unabhängig davon, ob Sie diese verschlüsselten Daten über das Netzwerk senden, später wieder in den Speicher laden oder auf einen anderen Prozess übertragen möchten, beabsichtigen Sie eindeutig, sie irgendwann zu entschlüsseln . In diesem Fall lautet die Antwort, dass Sie ein Kommunikationsprotokoll definieren. Ein Kommunikationsprotokoll sollte nicht definiert in Bezug auf den Details der Implementierung Ihrer Programmiersprache und die damit verbundene Laufzeit. Dafür gibt es mehrere Gründe:
Für die Kommunikation (entweder mit einem völlig unterschiedlichen Prozess oder mit demselben Programm in der Zukunft) müssen Sie Ihr Protokoll streng definieren, um die Schwierigkeit zu minimieren, damit zu arbeiten oder versehentlich Fehler zu verursachen. Abhängig von der internen Darstellung von .NET ist dies keine strikte, klare oder sogar garantiert konsistente Definition. Eine Standardkodierung ist eine strenge Definition, die Sie in Zukunft nicht enttäuschen wird.
Mit anderen Worten, Sie können Ihre Anforderungen an die Konsistenz nicht erfüllen, ohne eine Codierung anzugeben.
Sie können sich sicherlich für die direkte Verwendung von UTF-16 entscheiden, wenn Sie feststellen, dass Ihr Prozess eine erheblich bessere Leistung erbringt, da .NET ihn intern oder aus einem anderen Grund verwendet. Sie müssen diese Codierung jedoch explizit auswählen und diese Konvertierungen explizit in Ihrem Code durchführen, anstatt davon abhängig zu sein zur internen Implementierung von .NET.
Wählen Sie also eine Codierung und verwenden Sie sie:
Wie Sie sehen können, ist es auch weniger Code, nur die integrierten Codierungsobjekte zu verwenden, als Ihre eigenen Lese- / Schreibmethoden zu implementieren.
quelle
Zwei Wege:
Und,
Ich neige dazu, die untere öfter als die obere zu verwenden, habe sie nicht auf Geschwindigkeit gemessen.
quelle
quelle