2013-01-06 13 views
10

W tej funkcji konwersjiKonwersja ciąg byte [] tworzy zerowy charakter

public 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; 
} 

byte[] test = GetBytes("abc"); 

Powstały tablica zawiera zero znaków

test = [97, 0, 98, 0, 99, 0] 

A kiedy konwertować byte [] z powrotem do łańcucha, wynik jest

string test = "a b c " 

jaki sposób możemy zrobić to tak, aby nie tworzyć tych zer

+1

Te zera wydawały się celowo celowe, gdy skopiowano znaki do tablicy bajtów. Jakiego rodzaju kodowania * * chcesz? ASCII? UTF-8? – harold

+0

możliwy duplikat [Pobierz plik pobierz z bajtu \ [\]] (http://stackoverflow.com/questions/14158804/return-file-download-from-byte) – Esailija

+2

ToCharArray, jak sama nazwa wskazuje, zwraca char [] . Znak char ma 16 bitów, czyli 2 bajty. Otrzymasz dodatkowy bajt o wartości 0, nawet dla prostego tekstu ASCII. – Chris

Odpowiedz

6

Najpierw przyjrzyjmy co twój kod robi źle. char jest 16-bitowy (2 bajty) w środowisku .NET. Co oznacza, że ​​podczas pisania sizeof(char), zwraca 2. str.Length to 1, więc Twój kod będzie byte[] bytes = new byte[2] jest taki sam byte[2]. Tak więc, gdy używasz metody Buffer.BlockCopy(), faktycznie kopiujesz 2 bajtów z tablicy źródłowej do tablicy docelowej. Co oznacza, że ​​twoja metoda GetBytes() zwraca bytes[0] = 32 i bytes[1] = 0, jeśli Twój ciąg znaków to " ".

Spróbuj użyć zamiast tego Encoding.ASCII.GetBytes().

Kiedy nadpisane w klasie pochodnej, koduje wszystkie znaki w określony ciąg na ciąg bajtów.

const string input = "Soner Gonul"; 

byte[] array = Encoding.ASCII.GetBytes(input); 

foreach (byte element in array) 
{ 
    Console.WriteLine("{0} = {1}", element, (char)element); 
} 

wyjściowa:

83 = S 
111 = o 
110 = n 
101 = e 
114 = r 
32 = 
71 = G 
111 = o 
110 = n 
117 = u 
108 = l 
0

Spróbuj wyraźnie określić Encoding. Można użyć kolejnego kodu przekonwertować ciąg bajtów z określonego kodowania

byte[] bytes = System.Text.Encoding.ASCII.GetBytes("abc"); 

jeśli wydrukować zawartość bajtów, dostaniesz { 97, 98, 99 } która nie zawiera zera, tak jak w przykładzie Twojego w domyślnym kodowaniem przykład za pomocą 16 bitów na symbol. Może to być obserwatorem, drukując wyniki

System.Text.Encoding.Unicode.GetBytes("abc"); // { 97, 0, 98, 0, 99, 0 } 

Następnie podczas konwertowania go z powrotem, należy wybrać odpowiednie kodowanie:

string str = System.Text.Encoding.ASCII.GetString(bytes); 
Console.WriteLine (str); 

Drukuje "abc" jak można oczekiwany

+1

Lub użyj kodowania Unicode, aby przekonwertować z powrotem z tego, co dostał z GetBytes: 'string str = System.Text.Encoding.Unicode.GetString (bytes);' To powinno również działać z non-Ascii. Nadal powinieneś zawsze określać kodowanie idące w jedną stronę: 'byte [] bytes = System.Text.Encoding.Unicode.GetBytes (" abc ");' Zauważ, że domyślne UnicodeEncoding jest małym endianem, jeśli planujesz robić sieci i przełączać się endianness lub praca z innymi językami niż C#. – Sardtok

+0

@Sardtok dziękuje, zaktualizowałem asnwer –

0

(97,0) jest reprezentacją Unicode A. Unicode reprezentuje każdy znak w dwóch bajtach. Więc nie możesz usunąć zer. Ale możesz zmienić kodowanie na ASCII. Spróbuj następujących po Konwertowanie ciąg na bajt [].

byte[] array = Encoding.ASCII.GetBytes(input); 
0

Aby usunąć zamieszanie związane z twoją odpowiedzią, typ znaku w języku C# zajmuje 2 bajty. Tak więc string.toCharArray() zwraca tablicę, w której każdy element zajmuje 2 bajty pamięci. Podczas kopiowania do tablicy bajtowej, gdzie każdy element zajmuje 1 bajt pamięci, następuje utrata danych. Stąd zera pojawiają się w wyniku.
Zgodnie z sugestią, Encoding.ASCII.GetBytes jest bezpieczniejszym rozwiązaniem.

+0

Nie ma utraty danych, skutecznie działa tak samo jak 'Encoding.Unicode.GetBytes', który koduje jako Little Endian UTF16. – Esailija

1

w rzeczywistości .net (przynajmniej do 4,0) automatycznie zmienia rozmiar char po odcinkach z BinaryWriter

UTF-8 znaków mają zmienną długość (nie może być 1 bajt) znaków ASCII ma 1 bajt

'e' = 2 bajty

'e' = 1 bajt

należy pamiętać przy użyciu

BinaryReader.ReadChars(stream) 

W przypadku słowa "½valds" = 7 bajtów będzie się różnić od "evalds" = 6 bajtów

+0

"Łańcuchy UTF-8 mają 2 bajty" ... Co? UTF-8 to kodowanie o zmiennej długości. –

+0

Dziękuję za wyjaśnienia Zmontowałem odpowiedź –