Şifrəni əl ilə ifadə etmədən C # -də strinqlərin ardıcıl bayt təqdimini necə əldə etmək olar?

string üçün byte[] a .NET (C #)' a xüsusi bir kodlamayı əl ilə ifadə etmədən necə çevirmək olar?

Simli şifreleyeceğim. Dönüşüm olmadan onu şifreleyebilirəm, amma kodlaşdırma burada başlayan niyə bilmək istərdim.

Həmçinin, kodlaşdırma niyə nəzərdən keçirilməlidir? Yalnız simli saxlanılan baytları əldə edə bilərəmmi? Nə üçün xarakter kodlamalarından asılılıq var?

2003
23 янв. 23 yanvarda Agnel Kurian tərəfindən təyin olundu 2009-01-23 16:39 '09 at 16:39 'da 2009-01-23 16:39
@ 38 cavab
  • 1
  • 2

Burada cavablardan fərqli olaraq, baytların təfsir edilməməsi lazım deyilsə, kodlaşdırma mövzusunda narahat olmayın!

Qeyd etdiyimiz kimi, məqsədi sadəcə "baytların simli saxlanılmasını almaq" deməkdir.
(Əlbəttə ki, bayt dizesini yenidən qura bilmək üçün.)

Bu məqsədlər üçün, insanların niyə kodlaşdırmalara ehtiyac olduğunu sizə izah etməyə çalışdığımızı anlamıram. Bunun üçün kodlaşdırma mövzusunda endişelenmenize ehtiyac yoxdur.

Bunun əvəzini yerinə yetirin:

 static byte[] GetBytes(string str) { byte[] bytes = new byte[str.Length * sizeof(char)]; System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length); return bytes; } static string GetString(byte[] bytes) { char[] chars = new char[bytes.Length / sizeof(char)]; System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length); return new string(chars); } 

Proqramınız (və ya digər proqramlarınız) açıq-aydın qeyd etmədiyiniz baytları bir-birinə şərh etməyə çalışmadığı müddətcə, siz bunu etmək niyyətindəsiniz, onda bu yanaşmada heç bir şey yoxdur! Kodlaşdırma mövzusunda narahatlıq, həqiqətən, əsl səbəb olmadan həyatınızı daha mürəkkəbləşdirir.

Bu yanaşmanın əlavə üstünlüyü:

Dəmirdə yalnış simvollar varmı istəmirsiniz, çünki məlumatları hələ əldə edə və orijinal simli bərpa edə bilərsiniz!

Eyni şəkildə şifrələnir və şifrələnir, çünki baytlara baxırsınız.

Xüsusi bir kodlama istifadə etsəniz, bu, yanlış simvolların şifrələməsi / dekodlanması ilə bağlı problemlərə səbəb ola bilər.

1765
30 апр. Mehrdad tərəfindən aprelin 30-da verdiyi cavab 2012-04-30 10:44 '12 at 10:44 2012-04-30 10:44

Bu sizin simli kodlaşdırma ( ASCII , UTF-8 , ...) asılıdır.

Məsələn:

 byte[] b1 = System.Text.Encoding.UTF8.GetBytes (myString); byte[] b2 = System.Text.Encoding.ASCII.GetBytes (myString); 

Niyə kodlaşdırma məsələsinin kiçik bir nümunəsi:

border=0
 string pi = "\u03a0"; byte[] ascii = System.Text.Encoding.ASCII.GetBytes (pi); byte[] utf8 = System.Text.Encoding.UTF8.GetBytes (pi); Console.WriteLine (ascii.Length); //Will print 1 Console.WriteLine (utf8.Length); //Will print 2 Console.WriteLine (System.Text.Encoding.ASCII.GetString (ascii)); //Will print '?' 

ASCII sadəcə xüsusi simvolları idarə etmək üçün təchiz edilməmişdir.

Inside. NET, strings təmsil etmək üçün UTF-16 istifadə edir, belə ki, yalnız. NET istifadə edən tam byte almaq istəyirsinizsə, System.Text.Encoding.Unicode.GetBytes (...) istifadə edin.

Daha ətraflı məlumat üçün, .NET Framework (MSDN) -də Character Encoding-ə baxın.

1066
23 янв. Cavab bmotmans tərəfindən verilir 2009-01-23 16:43 '09 da 16:43 'da 2009-01-23 16:43

Qəbul edilən cavab çox çətindir. Bunun üçün daxil olan. NET dərslərini istifadə edin:

 const string data = "A string with international characters: Norwegian: ÆØÅæøå, Chinese: 喂 谢谢"; var bytes = System.Text.Encoding.UTF8.GetBytes(data); var decoded = System.Text.Encoding.UTF8.GetString(bytes); 

Lazım olmadıqda təkəri təkrar etməyin ...

260
30 апр. Cavab Erik A. Brandstadmoen 30 Apr 2012-04-30 10:26 '12 saat 10:26 'da 2012-04-30 10:26
 BinaryFormatter bf = new BinaryFormatter(); byte[] bytes; MemoryStream ms = new MemoryStream(); string orig = "喂 Hello 谢谢 Thank You"; bf.Serialize(ms, orig); ms.Seek(0, 0); bytes = ms.ToArray(); MessageBox.Show("Original bytes Length: " + bytes.Length.ToString()); MessageBox.Show("Original string Length: " + orig.Length.ToString()); for (int i = 0; i < bytes.Length; ++i) bytes[i] ^= 168; // pseudo encrypt for (int i = 0; i < bytes.Length; ++i) bytes[i] ^= 168; // pseudo decrypt BinaryFormatter bfx = new BinaryFormatter(); MemoryStream msx = new MemoryStream(); msx.Write(bytes, 0, bytes.Length); msx.Seek(0, 0); string sx = (string)bfx.Deserialize(msx); MessageBox.Show("Still intact :" + sx); MessageBox.Show("Deserialize string Length(still intact): " + sx.Length.ToString()); BinaryFormatter bfy = new BinaryFormatter(); MemoryStream msy = new MemoryStream(); bfy.Serialize(msy, sx); msy.Seek(0, 0); byte[] bytesy = msy.ToArray(); MessageBox.Show("Deserialize bytes Length(still intact): " + bytesy.Length.ToString()); 
107
23 янв. Cavab Michael Buen tərəfindən 23 Yanvarda verilir 2009-01-23 19:36 '09 da 19:36 'da 2009-01-23 19:36

1 ədəd 1 və ya daha çox bayt (ən çox 6) ilə təmsil edilə bilər, çünki kodlamanı nəzərə almalıyıq və müxtəlif kodlamalar bu baytları fərqli şəkildə işləyəcəkdir.

Joel bunun üçün bir kabel var:

Mütləq minimum Hər bir proqram tərtibçisi Mütləq, Unicode və xarakter dəstləri haqqında müsbət bilmək lazımdır (heç bir bəhanə!)

84
23 янв. Japh - Ben Duguid tərəfindən verilmiş cavab Yanvar 23 2009-01-23 17:03 '09 da 17:03 'da 2009-01-23 17:03

Bu məşhur bir sual. Müəllifin sual soruşduğunu anlamaq vacibdir və ən çox ehtimal olunan ən çox ehtiyacdan fərqlənir. Lazım olmayan kodun istifadəsinin qarşısını almaq üçün mən daha sonra cavablandırdım.

Ümumi ehtiyac

Hər bir xətt bir simvolu və kodlaşdırma sisteminə malikdir. Bir System.String obyektini bir System.Byte dönüştürdüğünüzde, hala karakter kümesi ve karakter kümesi var. Ən çox istifadə edilən hallarda, hansı xüsusiyyətləri müəyyənləşdirdiyinizi və kodlaşdırmanızın lazım olduğunu bilməli və .NET "çevirmə ilə tərcümə etmək" ni asanlaşdırır. Sadəcə müvafiq Encoding sinfi seçin.

 // using System.Text; Encoding.UTF8.GetBytes(".NET String to byte array") 

Dönüşüm üçün, hedef karakteri ayarlama ya da şifreleme kaynağın karakterini desteklemediği durumları ele almanız gerekebilir. Bir seçiminiz var: istisna, əvəzetmə və ya hərəkətsizlik. Standart siyasət, "?" Əvəz etməkdir.

 // using System.Text; var text = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes("You win €100")); // -> "You win ?100" 

Aydındır ki, dönüşüm mütləq kayıpsız deyil!

Qeyd System.String orijinal xarakterli set Unicode'dur.

Yalnızca anlaşılmaz bir şey. NET bu simvol müəyyən bir xüsusi kodlaşdırma adı üçün xarakterli adını istifadə edir. Encoding.Unicode adlandırılmalıdır.

Ən gömrük üçün nədir? Buna ehtiyac varsa, burada oxu dayandır. Joel Spolskinin yazdığına baxın nə kodlaşdırmanın nə olduğunu anlamırsınız.

Xüsusi ehtiyac

İndi sual soruşur: "Hər bir xətt birbaşa bir sıra bayt olaraq saxlanılır, niyə bu baytlara sahib ola bilmirəm?"

O dönüşüm istəmir.

C # xüsusiyyətindən :

C # istifadə edilən simvollar və strinqlər Unicode kodlamasını istifadə edir. Char növü UTF-16 kod blokudur və simli tip UTF-16 kod bloklarının bir ardıcıllığıdır.

Beləliklə, bilirik ki, biz natürel dönüşüm (yəni, UTF-16'dan UTF-16-a qədər) üçün istənilən nəticəni alırıq:

 Encoding.Unicode.GetBytes(".NET String to byte array") 

Ancaq kodlamaları qeyd etməmək üçün bunu fərqli bir şəkildə etməmiz lazımdır. Aralıq məlumat növü etibarlıdırsa, bunun üçün bir konseptual etiket var:

 ".NET String to byte array".ToCharArray() 

Bu bizə istənilən məlumat növünü vermir, ancaq Mehrdad Response, bu Char arrayini BlockCopy istifadə edərək bayt arrayına necə çevirəcəyini göstərir. Lakin, iki dəfə simli kopyalayır! Və kodlaşdırma kodunu çox açıq şəkildə istifadə edir: data type System.Char .

Stringin saxlandığı faktiki baytları əldə etmək üçün yeganə yol göstərici istifadə etməkdir. fixed bəyanat dəyərlərin ünvanını götürməyə imkan verir. C # xüsusiyyətindən:

Bir növ düstur ifadəsi üçün [for] ... başlanğıc simli ilk simvolun ünvanını hesablayır.

Bunu etmək üçün, derleyici RuntimeHelpers.OffsetToStringData istifadə edərək, bir dize obyektinin digər hissələrini keçirən kodu yazır. Beləliklə, xam bytes almaq, sadəcə bir simli bir göstərici yaratmaq və lazımlı sayı bayt kopyalayın.

 // using System.Runtime.InteropServices unsafe byte[] GetRawBytes(String s) { if (s == null) return null; var codeunitCount = s.Length;  var byteCount = codeunitCount * 2; var bytes = new byte[byteCount]; fixed(void* pRaw = s) { Marshal.Copy((IntPtr)pRaw, bytes, 0, byteCount); } return bytes; } 

@CodesInChaos qeyd etdiyi kimi, nəticə maşın dəqiqliyindən asılıdır. Ancaq sualın müəllifi bununla maraqlanmır.

79
02 дек. Cavab Tom Blodget tərəfindən verilir 02 Dekabr. 2013-12-02 07:43 '13 at 07:43 2013-12-02 07:43

Sizin sualınızın ilk hissəsi (baytların alınması) artıq başqaları tərəfindən cavablandırılmışdır: System.Text.Encoding ad boşluğuna baxın.

Növbəti sualınızı nəzərdən keçirəcəyəm: niyə kodlaşdırma seçmək lazımdır? Niyə bu simli sinifdən özünü ala bilmirsiniz?

Cavab iki hissədən ibarətdir.

Hər şeydən əvvəl, string sinifində istifadə olunan baytlar vacibdir və bu vəziyyətdə olduğunuzda, ehtimal ki, bir səhv daxil olursunuz.

Proqramınız tamamilə .Net dünyada, şəbəkə üzərindən məlumatlar göndərsəniz belə, strings üçün bayt dizilerini almaqdan narahat olmayın. Bunun əvəzinə, məlumat köçürməsindən narahat olmaq üçün Net Serializasiya istifadə edin. Artıq faktiki baytlar barədə narahat olmayın: Serializasiya formatı sizin üçündir.

Digər tərəfdən, əgər bu baytları bir yerə göndərə bilsəniz, təmin edə bilməyəcəyiniz məlumatların veriləcəyi. NET serialized stream? Bu vəziyyətdə, şübhəsiz ki, kodlaşdırma mövzusunda narahat olmaq lazımdır, çünki açıq-aydın bu xarici sistemə diqqət yetirir. Beləliklə, simli istifadə edilən daxili baytlar əhəmiyyətli deyil: daxilində istifadə edilən eyni kodlaşdırma istifadə etsə belə, bu kodlamanı qəbul edən tərəfdə açıq şəkildə göstərə bilməsi üçün bir kodlama seçməlisiniz.

Hesab edirəm ki, bu halda, bir dize xaricində baytların yaradılması ilə bəzi işlərin saxlaya biləcəyi fikri ilə yaddaşda saxlanılan datanın dəyişənində saxlanılan faktiki baytları istifadə edə bilərsiniz. Buna baxmayaraq, hesab edirəm ki, çıxışınızın digər sonunda başa düşülməsinə və kodlaşdırma ilə aydın olmalı olduğunuza əmin olmaq üçün sadəcə vacib deyil. Bundan əlavə, əgər həqiqətən daxili baytlarınızı birləşdirmək istəyirsinizsə, sadəcə Unicode kodlamasını seçə və bu qənaət qənaətini əldə edə bilərsiniz.

Hansı məni ikinci hissəyə aparır ... Unicode kodlamasını seçirəm Base baytlarını istifadə etmək üçün. Bu kodlamanı seçməlisiniz, çünki yeni Unicode-Plus göründüyü zaman, proqramınızı pozmadan bu yeni, daha yaxşı kodlama modelini istifadə etmək üçün .Net runtime pulsuz olmalıdır. Ancaq, indiki (və gələcəkdə) Unicode kodlamasını seçmək istədiyinizi verir.

Sizin simninizin telə yenidən yazılması lazım olduğunu anlamaq vacibdir və bu, müvafiq kodlamanı istifadə etsəniz belə, ən azı bit naxışının bəzi tərcüməsini nəzərdə tutur. Kompüter Big və Little Endian, şəbəkə byte sifariş, qablaşdırma, sessiya məlumatları və s.

39
23 янв. Joel Coehoorn tərəfindən verilmiş cavab Yanvar 23 2009-01-23 18:54 '09 at 18:54 'da 2009-01-23 18:54

Yalnız Mehrdradın səsli cavabının işlədiyini nümayiş etdirmək üçün onun yanaşması hətta bir çoxları mənim cavabımı düzəldiblər, lakin hər birinin bərabər günahkardır, məsələn, System.Text.Encoding.UTF8.GetBytes , System.Text.Encoding.Unicode.GetBytes , bu kodlama metodları köhnə d800 qəhrəmanları d800 saxlaya d800 , amma sadəcə köhnə d800 simvollarını d800 ilə əvəz fffd ):

 using System; class Program { static void Main(string[] args) { string t = "爱虫"; string s = "Test\ud800Test"; byte[] dumpToBytes = GetBytes(s); string getItBack = GetString(dumpToBytes); foreach (char item in getItBack) { Console.WriteLine("{0} {1}", item, ((ushort)item).ToString("x")); } } static byte[] GetBytes(string str) { byte[] bytes = new byte[str.Length * sizeof(char)]; System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length); return bytes; } static string GetString(byte[] bytes) { char[] chars = new char[bytes.Length / sizeof(char)]; System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length); return new string(chars); } } 

Çıxış:

 T 54 e 65 s 73 t 74 ? d800 T 54 e 65 s 73 t 74 

System.Text.Encoding.UTF8.GetBytes və ya System.Text.Encoding.Unicode.GetBytes ilə cəhd edin, onlar köhnə surrogate simvollarını fffd

Hər zaman bu mövzuda bir hərəkət var, mən hələ də serializer haqqında düşünürəm (Microsoft-dan və ya üçüncü tərəfin tərkibindən), bu da sətirləri saxlaya bilir, hətta əgər bu əlavə olmayan surrogate simvolları olsa da; Zaman zaman bu səhifəni Google edirəm: serbestleşmemiş surrogate. NET karakterinin seriallaşdırılması . Bu, məni yuxuya çevirməz, amma bəzən mənim cavabımda yanlış olduğunu düşünürsə, zaman zaman bir az zəhmət çəkir, amma onların cavabları bərpa edilməyən surrogate simvollarına gəldikdə bərabərdir.

Cəhənnəm, Microsoft yalnız BinaryFormatterBinaryFormatter istifadə etməlidir

谢谢!

38
30 апр. Cavab Maykl Buen tərəfindən 30 Apreldə verildi 2012-04-30 15:50 '12 at 15:50 2012-04-30 15:50

Bunu çox az kod cəhd edin:

 System.Text.Encoding.UTF8.GetBytes("TEST String"); 
36
26 июля '11 в 1:52 2011-07-26 01:52 cavab Nathan tərəfindən 26 iyul 'da11: 00' da verildi. 2011-07-26 01:52

Bəli, bütün cavabları oxumuşdum və onlar kodlaşdırma və ya serializasiya haqqında söhbət etdilər.

Dizayn, məsələn, SQL Server- dan gəldiyi zaman pisdir, burada parol yığımı kimi bayt dizisindən tikilmişdir. Ondan bir şey atarsa, bu, saxta hash saxlayacaq və biz onu XML-də saxlamaq istəyiriksə, onu pozmamaq istəyirik (çünki XML yazıçısı tapdığı heç bir uyğunsuzluq surətini istisna edir).

Buna görə də, Base64- in bayt dizilerini bu cür hallarda istifadə edirəm, ancaq İnternetdə C # -də bunun üçün bir həll var və bunun bir səhvi var və bu yalnız bir yoldur, mən səhvəni düzəldib, qeyd prosedurunu yerinə yetirdim. İşdə, gələcək Googlers:

 public static byte[] StringToBytes(string str) { byte[] data = new byte[str.Length * 2]; for (int i = 0; i < str.Length; ++i) { char ch = str[i]; data[i * 2] = (byte)(ch  0xFF); data[i * 2 + 1] = (byte)((ch  0xFF00) >> 8); } return data; } public static string StringFromBytes(byte[] arr) { char[] ch = new char[arr.Length / 2]; for (int i = 0; i < ch.Length; ++i) { ch[i] = (char)((int)arr[i * 2] + (((int)arr[i * 2 + 1]) << 8)); } return new String(ch); } 
22
10 марта '11 в 11:57 2011-03-10 11:57 cavab 10 mart 2011- ci il saat 11: 57-da Gman tərəfindən verilmişdir

Həmçinin kodlaşdırmanın nəzərə alınması lazım olduğunu da izah edin. Yalnız simli saxlanılan baytları əldə edə bilərəmmi? Niyə bu asılılığı kodlaşdırmağa?

Çünki "string bytes" kimi bir şey yoxdur.

Bir string (və ya daha ümumi mətn) simvollardan ibarətdir: məktublar, nömrələr və digər simvollar. Bütün bunlar. Kompüterlər, ancaq simvol haqqında heç bir şey bilmir; onlar baytları idarə edə bilərlər. Buna görə, bir kompüter istifadə edərək mətni saxlamaq və ya ötürmək istəyirsinizsə, simvolları baytlara çevirmək lazımdır. Bunu necə edirsiniz? Burada kodlaşdırma səhnəyə çıxdı.

Kodlama, mantıksal simvolları fiziki baytlara çevirmək üçün bir razılıqdan başqa bir şey deyil. Ən sadə və ən məşhur şifrələmə ASCII və ingilis dilində yazarsanız, lazım olan hər şey. Digər dillər üçün, Unicode hər hansı bir zamanda ən təhlükəsiz seçimdir, çünki daha tam kodlaşdırma lazımdır.

Beləliklə, bir sözlə, "kodları istifadə etmədən bir stringin baytlarını almaq" cəhdi "heç bir dil istifadə etmədən mətn yazma" kimi mümkün deyil.

Yeri gəlmişkən, mən sizə məsləhət verirəm (və hər kəs bunun üçün) bu kiçik bir müdrikliyi oxuyur: Mütləq Minimum Hər bir proqram tərtibçisi mütləq, Unicode və xarakter dəstləri haqqında müsbət biliklər lazımdır (heç bir bəhanə!)

20
16 июля '09 в 14:45 2009-07-16 14:45 Cavab Konamiman tərəfindən 16 iyul 16: 09-da saat 14.45-də verilir

string dizisini byte üçün çevirmək üçün C #:

 public static byte[] StrToByteArray(string str) { System.Text.UTF8Encoding encoding=new System.Text.UTF8Encoding(); return encoding.GetBytes(str); } 
19
05 июня '13 в 13:52 2013-06-05 13:52 Cavab Shyam sundar shah tərəfindən verilir 05 İyun 2013 13:52 2013-06-05 13:52
 byte[] strToByteArray(string str) { System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); return enc.GetBytes(str); } 
15
23 янв. gkrogers tərəfindən verilmiş cavab Yanvar 23 2009-01-23 16:43 '09 da 16:43 'da 2009-01-23 16:43

Diziler ve bayt dizisi arasında dönüştürmek üçün aşağıdakı kodu istifadə edə bilərsiniz.

 string s = "Hello World"; // String to Byte[] byte[] byte1 = System.Text.Encoding.Default.GetBytes(s); // OR byte[] byte2 = System.Text.ASCIIEncoding.Default.GetBytes(s); // Byte[] to string string str = System.Text.Encoding.UTF8.GetString(byte1); 
15
09 сент. Cavab Jarvis Stark tərəfindən Sep 09 2014-09-09 14:30 '14 14:30 'da 2014-09-09 14:30

Mən əmin deyiləm, amma simli onun məlumatlarını saxta bir sıra kimi saxlayır, çünki bytes ilə effektiv deyil. Xüsusilə Charinin tərifi "Unicode xarakterini təmsil edir" deməkdir.

Bu nümunəni götür:

 String str = "asdf éß"; String str2 = "asdf gh"; EncodingInfo[] info = Encoding.GetEncodings(); foreach (EncodingInfo enc in info) { System.Console.WriteLine(enc.Name + " - " + enc.GetEncoding().GetByteCount(str) + enc.GetEncoding().GetByteCount(str2)); } 

Unicode cavabının hər iki halda 14 bayt olduğuna diqqət yetirin, UTF-8 cavab isə yalnız 9 üçün bayt və ikinci üçün isə yalnız 7 ədəddir.

Belə ki, yalnız string tərəfindən istifadə olunan baytları istifadə etmək istəyirsinizsə, yalnız Encoding.Unicode istifadə edin, ancaq yaddaş miqdarı ilə səmərəsiz olacaq.

11
23 янв. Cavab Ed Marty Jan 23 tərəfindən verilir 2009-01-23 17:34 '09 da 17:34 'da 2009-01-23 17:34

Əsas problem simli glifin 32 bit (karakter kodu üçün 16 bit), lakin baytın yalnız 8 bitə bərabərdir. Yalnız ASCII simvolları olan dizgələrlə özünüzü məhdudlaşdırmadan fərdi uyğunlaşma yoxdur. System.Text.Encoding bir simli bir byte [] ilə uyğunlaşmanın bir çox yoluna malikdir, məlumatı itirməkdən qaçınmağa imkan verən və bir bayt [] geri simli ilə uyğunlaşması üçün lazım olan zaman istifadə üçün asan olanı seçməlisiniz.

Utf8 məşhur kodlaşdırma, kompakt və itirmək deyil.

10
23 янв. Hans Passant tərəfindən verilmiş cavab Jan 23 2009-01-23 17:15 '09 saat 05:15 'da 2009-01-23 17:15

C # 7.2-də çıxarılan Span<T> 'in çıxışı ilə, simli yaddaşda idarə olunan bir bayt array daxilində saxlanılan qanonik metod:

 byte[] bytes = "rubbish_\u9999_string".AsSpan().AsBytes().ToArray(); 

Geri çevrilmə çətin ola bilər, çünki bu, həqiqətən, məlumatları bir şəkildə şərh edir, ancaq tamamlanma naminə:

 string s; unsafe { fixed (char* f =  char>().DangerousGetPinnableReference()) { s = new string(f); } } 

NonPortableCastDangerousGetPinnableReference adları ehtimal etməməli olan NonPortableCast arqumentinə sahib olmalıdır.

Span<T> ilə işləmək üçün System.Memory NuGet paketini yükləməlisiniz .

Buna baxmayaraq, faktiki qaynaq məsələsi və sonrakı şərhlər əsas yaddaşın "təfsir edilən" deyildir (hansı ki, yazılırsa, dəyişməz və Stream sinif, məlumatlar haqqında əsaslandırmaların əvəzinə üslub olaraq istifadə edilməlidir.

8
10 янв. Cavab John Rasch tərəfindən 10 Yanvar verildi 2018-01-10 23:21 '18 saat 11.21 'da 2018-01-10 23:21

İstifadə edin:

  string text = "string"; byte[] array = System.Text.Encoding.UTF8.GetBytes(text); 

Nəticə:

 [0] = 115 [1] = 116 [2] = 114 [3] = 105 [4] = 110 [5] = 103 
7
22 окт. cavab mashet 22 oct verildi . 2013-10-22 15:55 '13 saat 15:55 'də 2013-10-22 15:55

Ən sürətli şəkildə

 public static byte[] GetBytes(string text) { return System.Text.ASCIIEncoding.UTF8.GetBytes(text); } 

Makotosan olaraq CHANGE olaraq şərh etdilər, indi bu ən yaxşı şəkildə:

 Encoding.UTF8.GetBytes(text) 
7
22 марта '10 в 11:40 2010-03-22 11:40 Cavab 22 Mart 'da 11: 30-da sunrising günüdür. 2010-03-22 11:40

OP sorusuna ən yaxın yanaşma Tom Blodget, əslində obyektə daxil olur və baytları çıxarır. String obyektinin həyata keçirilməsindən asılıdır, çünki daha yaxın danışıram.

 "Can't I simply get what bytes the string has been stored in?" 

Əlbəttə ki, məsələdə əsas səhv olduğu yerdə. String maraqlı bir məlumat strukturuna sahib ola bilən bir obyektdir. Zaten bilirik ki, bu, başarısız olan surrogates depolamanıza imkan verir. Uzunluğu saxlaya bilər. Tezliklə hesablamağa imkan verən "cütlənmiş" suratların hər birinə göstərici ola bilər. Və s Bu əlavə baytların hamısı karakter məlumatlarının bir hissəsidir.

То, что вы хотите, это каждый символ байтов в массиве. И именно здесь происходит "кодирование". По умолчанию вы получите UTF-16LE. Если вы сами не заботитесь о самих байтах, за исключением поездки туда и обратно, вы можете выбрать любую кодировку, включая "по умолчанию", и преобразовать ее позже (при условии, что те же параметры, что и кодировка по умолчанию, кодовые точки, исправления ошибок, разрешенные вещи, такие как непарные суррогаты и т.д.

Но зачем оставлять "кодировку" до магии? Почему бы не указать кодировку, чтобы вы знали, какие байты вы получите?

 "Why is there a dependency on character encodings?" 

Кодирование (в этом контексте) просто означает байты, которые представляют вашу строку. Не байты строкового объекта. Вам нужны байты, в которые была сохранена строка, - вот где вопрос был задан наивно. Вам нужны байты строки в смежном массиве, которые представляют строку, а не все другие двоичные данные, которые могут содержать строковый объект.

Это означает, что сохранение строки не имеет значения. Вы хотите, чтобы строка "закодирована" в байты в массиве байтов.

Мне нравится ответ Tom Bloget, потому что он взял вас к направлению "байтов строкового объекта". Это зависит от реализации, и, поскольку он заглядывает внутрь, может быть трудно восстановить копию строки.

Ответ Mehrdad неверен, поскольку он вводит в заблуждение на концептуальном уровне. У вас все еще есть список байтов, закодированных. Его особое решение позволяет сохранить непарные суррогаты - это зависит от реализации. Его конкретное решение не создавало бы строковых байтов точно, если GetBytes по умолчанию возвратил строку в UTF-8.


Я изменил свое мнение об этом (решение Mehrdad) - это не получает байты строки; скорее, он получает байты массива символов, которые были созданы из строки. Независимо от кодирования, тип данных char в С# является фиксированным размером. Это позволяет создать массив байтов с последовательной длиной, и он позволяет воспроизводить массив символов на основе размера массива байтов. Поэтому, если кодировка была UTF-8, но каждый char составлял 6 байтов для размещения наибольшего значения utf8, он все равно работал бы. Так что действительно - кодирование персонажа не имеет значения.

Но использовалось преобразование - каждый символ помещался в поле фиксированного размера (тип символа С#). Однако какое это представление не имеет значения, что технически является ответом на ОП. Итак - если вы все равно собираетесь конвертировать... Почему бы не "закодировать"?

5
ответ дан Gerard ONeill 18 авг. '15 в 20:04 2015-08-18 20:04

Вы можете использовать следующий код для преобразования string в byte array в .NET

 string s_unicode = "abcéabc"; byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(s_unicode); 
5
ответ дан Shyam sundar shah 02 сент. '13 в 14:21 2013-09-02 14:21

Как преобразовать строку в byte [] в .NET (С#) без указания конкретной кодировки вручную?

Строка в .NET представляет текст как последовательность кодовых единиц UTF-16, поэтому байты кодируются в памяти уже в UTF-16.

Mehrdad Ответ

Вы можете использовать ответ Mehrdad , но на самом деле он использует кодировку, потому что символы UTF-16. Он вызывает ToCharArray, который, глядя на источник, создает char[] и напрямую копирует в него память. Затем он копирует данные в байтовый массив, который также выделяется. Таким образом, он скрывает два байта и выделяет массив символов, который не используется после вызова.

Том Блоджетт Ответ

Ответ Tom Blodget на 20-30% быстрее, чем Mehrdad, поскольку он пропускает промежуточный этап выделения массива char и копирования в него байтов, но требует компиляции с параметром /unsafe . Если вы абсолютно не хотите использовать кодирование, я думаю, что это путь. Если вы поместите свой логин шифрования в fixed блок, вам даже не нужно выделять отдельный массив байтов и копировать в него байты.

Кроме того, почему кодирование должно быть принято во внимание? Разве я не могу просто получить, в каких байтах хранится строка? Почему существует зависимость от кодировки символов?

Потому что это правильный способ сделать это. string - это абстракция.

Использование кодировки может создать проблемы, если у вас есть "строки" с недопустимыми символами, но этого не должно происходить. Если вы вводите данные в строку с недопустимыми символами, вы делаете это неправильно. Вы, вероятно, должны использовать байтовый массив или кодировку Base64 для начала.

Если вы используете System.Text.Encoding.Unicode , ваш код будет более устойчивым. Вам не нужно беспокоиться о порядке работы системы, в которой будет выполняться ваш код. Вам не нужно беспокоиться, если в следующей версии CLR будет использоваться другая внутренняя кодировка символов.

Я думаю, вопрос не в том, почему вы хотите беспокоиться о кодировке, а в том, почему вы хотите игнорировать ее и использовать что-то еще. Кодирование предназначено для представления абстракции строки в последовательности байтов. System.Text.Encoding.Unicode предоставит вам немного порядковый порядок кодирования байтов и будет выполнять то же самое в каждой системе, сейчас и в будущем.

5
ответ дан Jason Goemaat 02 июля '18 в 23:51 2018-07-02 23:51

Вот моя небезопасная реализация преобразования String в Byte[] :

 public static unsafe Byte[] GetBytes(String s) { Int32 length = s.Length * sizeof(Char); Byte[] bytes = new Byte[length]; fixed (Char* pInput = s) fixed (Byte* pBytes = bytes) { Byte* source = (Byte*)pInput; Byte* destination = pBytes; if (length >= 16) { do { *((Int64*)destination) = *((Int64*)source); *((Int64*)(destination + 8)) = *((Int64*)(source + 8)); source += 16; destination += 16; } while ((length -= 16) >= 16); } if (length > 0) { if ((length  8) != 0) { *((Int64*)destination) = *((Int64*)source); source += 8; destination += 8; } if ((length  4) != 0) { *((Int32*)destination) = *((Int32*)source); source += 4; destination += 4; } if ((length  2) != 0) { *((Int16*)destination) = *((Int16*)source); source += 2; destination += 2; } if ((length  1) != 0) { ++source; ++destination; destination[0] = source[0]; } } } return bytes; } 

Это намного быстрее, чем принятый anwser, даже если он не такой элегантный, как есть. Вот мои тесты секундомера более 10000000 итераций:

 [Second String: Length 20] Buffer.BlockCopy: 746ms Unsafe: 557ms [Second String: Length 50] Buffer.BlockCopy: 861ms Unsafe: 753ms [Third String: Length 100] Buffer.BlockCopy: 1250ms Unsafe: 1063ms 

Чтобы использовать его, вы должны отметить "Разрешить небезопасный код" в своих свойствах построения проекта. В соответствии с .NET Framework 3.5 этот метод также можно использовать как расширение строки:

 public static unsafe class StringExtensions { public static Byte[] ToByteArray(this String s) { // Method Code } } 
3
ответ дан Tommaso Belluzzo 15 янв. '13 в 14:43 2013-01-15 14:43

Два способа:

 public static byte[] StrToByteArray(this string s) { List<byte> value = new List<byte>(); foreach (char c in s.ToCharArray()) value.Add(c.ToByte()); return value.ToArray(); } 

 public static byte[] StrToByteArray(this string s) { s = s.Replace(" ", string.Empty); byte[] buffer = new byte[s.Length / 2]; for (int i = 0; i < s.Length; i += 2) buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16); return buffer; } 

Я предпочитаю использовать нижнюю часть чаще, чем верхнюю, не сравнивая их по скорости.

2
ответ дан harmonik 20 февр. '09 в 0:03 2009-02-20 00:03

простой код с LINQ

 string s = "abc" byte[] b = s.Select(e => (byte)e).ToArray(); 

EDIT: как указано ниже, это не очень хорошо.

но вы все равно можете использовать его для понимания LINQ с более подходящим кодированием:

 string s = "abc" byte[] b = s.Cast<byte>().ToArray(); 
2
ответ дан Avlin 11 окт. '12 в 12:45 2012-10-11 12:45

Просто используйте это:

 byte[] myByte= System.Text.ASCIIEncoding.Default.GetBytes(myString); 
2
ответ дан alireza amini 30 июня '15 в 17:39 2015-06-30 17:39

Если вам действительно нужна копия базовых байтов строки, вы можете использовать такую ​​функцию, как следующая. Однако вы не должны читать, чтобы узнать, почему.

 [DllImport( "msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] private static extern unsafe void* UnsafeMemoryCopy( void* destination, void* source, uint count); public static byte[] GetUnderlyingBytes(string source) { var length = source.Length * sizeof(char); var result = new byte[length]; unsafe { fixed (char* firstSourceChar = source) fixed (byte* firstDestination = result) { var firstSource = (byte*)firstSourceChar; UnsafeMemoryCopy( firstDestination, firstSource, (uint)length); } } return result; } 

Эта функция быстро доставит вам копию байтов, лежащих в основе вашей строки. Вы получите эти байты любым способом, который они кодируют в вашей системе. Эта кодировка почти наверняка является UTF-16LE, но это деталь реализации, которую вам не нужно заботиться.

Чтобы просто позвонить, безопаснее, проще и надежнее ,

 System.Text.Encoding.Unicode.GetBytes() 

По всей вероятности, это даст тот же результат, проще набрать, и байты всегда будут округлены с вызовом

 System.Text.Encoding.Unicode.GetString() 
2
ответ дан Jodrell 25 нояб. '14 в 13:29 2014-11-25 13:29
 bytes[] buffer = UnicodeEncoding.UTF8.GetBytes(string something); //for converting to UTF then get its bytes bytes[] buffer = ASCIIEncoding.ASCII.GetBytes(string something); //for converting to ascii then get its bytes 
2
ответ дан user1120193 02 янв. '12 в 14:07 2012-01-02 14:07

Это зависит от того, что вы хотите байтов FOR

Это потому, что, поскольку Тайлер так метко сказал , "Строки не являются чистыми данными, у них также есть information ." В этом случае информация представляет собой кодировку, которая была принята при создании строки.

Предполагая, что у вас есть двоичные данные (а не текст), хранящиеся в строке

Это основано на комментариях OP по его собственному вопросу, и это правильный вопрос, если я понимаю подсказки OP в прецеденте.

Сохранение двоичных данных в строках, вероятно, является неправильным подходом из-за предполагаемого кодирования, упомянутого выше! Независимо от того, какая программа или библиотека хранит эти двоичные данные в string (вместо массива byte[] , который был бы более уместным), он уже проиграл битву до ее начала. Если они отправляют вам байты в запросе/ответе REST или что-либо, что должно передавать строки, Base64 будет правильным подходом.

Если у вас есть текстовая строка с неизвестной кодировкой

Все остальные неверно ответили на этот неправильный вопрос.

Если строка выглядит хорошо как-есть, просто выберите кодировку (желательно, начиная с UTF), используйте соответствующую функцию System.Text.Encoding.???.GetBytes() и сообщите, кто бы вы ни отправили байты, в которые вы выбрали кодировку.

1
ответ дан NH. 08 нояб. '17 в 21:21 2017-11-08 21:21

Строка может быть преобразована в массив байтов несколькими способами, из-за следующего факта:.NET поддерживает Unicode, а Unicode стандартизирует несколько разностных кодировок, называемых UTF. Они имеют различную длину байтового представления, но эквивалентны в этом смысле, что при кодировании строки он может быть закодирован обратно в строку, но если строка кодируется одним UTF и декодируется в предположении о разном UTF, если его можно навинтить вверх.

Кроме того,.NET поддерживает кодировки, отличные от Unicode, но они недействительны в общем случае (будут действительны только в том случае, если ограниченный подмножество кодовой точки Unicode используется в реальной строке, такой как ASCII). Внутренне .NET поддерживает UTF-16, но для представления потока обычно используется UTF-8. Это также стандартно-де-факто для Интернета.

Неудивительно, что сериализация строки в массив байтов и десериализация поддерживается классом System.Text.Encoding , который является абстрактным классом; его производные классы поддерживают конкретные кодировки: ASCIIEncoding и четыре UTF ( System.Text.UnicodeEncoding поддерживает UTF-16)

Ref эта ссылка.

Для сериализации массива байтов с помощью System.Text.Encoding.GetBytes . Для обратной операции используйте System.Text.Encoding.GetChars . Эта функция возвращает массив символов, поэтому для получения строки используйте конструктор строк System.String(char[]) .
Ссылка на эту страницу.

Məsələn:

 string myString = //... some string System.Text.Encoding encoding = System.Text.Encoding.UTF8; //or some other, but prefer some UTF is Unicode is used byte[] bytes = encoding.GetBytes(myString); //next lines are written in response to a follow-up questions: myString = new string(encoding.GetChars(bytes)); byte[] bytes = encoding.GetBytes(myString); myString = new string(encoding.GetChars(bytes)); byte[] bytes = encoding.GetBytes(myString); //how many times shall I repeat it to show there is a round-trip? :-) 
1
ответ дан Vijay Singh Rana 11 июня '14 в 14:29 2014-06-11 14:29
  • 1
  • 2

Другие вопросы по меткам или Задайте вопрос