2010-08-08 13 views

Odpowiedz

29

W przypadku, gdy nie ma tego LINQ fetysz, tak powszechne ostatnio, można spróbować w normalny sposób

string input .... 
int numOfBytes = input.Length/8; 
byte[] bytes = new byte[numOfBytes]; 
for(int i = 0; i < numOfBytes; ++i) 
{ 
    bytes[i] = Convert.ToByte(input.Substring(8 * i, 8), 2); 
} 
File.WriteAllBytes(fileName, bytes); 

LINQ jest wielki, ale nie muszą być pewne ograniczenia.

+0

O wiele bardziej zrozumiały – jwsample

+1

Zakłada się, że długość ciągu jest wielokrotnością 8 ... Ale masz rację, prawdopodobnie łatwiej jest to zrozumieć. Chyba jestem całkowicie uzależniony od LINQ;) –

+2

Hmm. Twierdzę, że LINQ jest bardziej zrozumiały. Opisuje zwięźle, co się dzieje bez opisywania (hałaśliwych) kroków, aby osiągnąć ten cel. Ma znacznie wyższy stosunek zawartości do szumu. – spender

9

Można zacząć od podziału ciąg do sekwencji łańcuchów 8-znakowy, a następnie przekonwertować te ciągi bajtów, i ostatecznie zapisać bajtów do pliku

string input = "01110100011001010111001101110100"; 
var bytesAsStrings = 
    input.Select((c, i) => new { Char = c, Index = i }) 
     .GroupBy(x => x.Index/8) 
     .Select(g => new string(g.Select(x => x.Char).ToArray())); 
byte[] bytes = bytesAsStrings.Select(s => Convert.ToByte(s, 2)).ToArray(); 
File.WriteAllBytes(fileName, bytes); 

EDIT: oto inny sposób podzielić ciąg na kawałki 8-znakowych, może nieco prostsze:

int nBytes = (int)Math.Ceiling(input.Length/8m); 
var bytesAsStrings = 
    Enumerable.Range(0, nBytes) 
       .Select(i => input.Substring(8 * i, Math.Min(8, input.Length - 8 * i))); 

Jeśli wiesz, że długość łańcucha jest wielokrotnością 8, można zrobić to jeszcze prostsze:

int nBytes = input.Length/8; 
var bytesAsStrings = 
    Enumerable.Range(0, nBytes) 
       .Select(i => input.Substring(8 * i, 8)); 
+0

Po prostu wpadłem na to pytanie. Miły problem z zabawkami ... dobry na rozmowę. Myślałem, że dam mu szansę, zanim przeczytam odpowiedzi. Dopasowałem twoje drugie podejście praktycznie do terminu. Ja też jestem uzależniony od LINQ! +1 – spender

0

Inne odpowiedzi zostały omówione, ale dla zabawy napisałem coś przeciwnego. Idąc z łańcucha ASCII do reprezentacji binarnej:

private static string StringToAsciiBin(string s) 
    { 
     string output = ""; 
     foreach (char c in s.ToCharArray()) 
     { 
      for (int i = 128; i >= 1; i /=2) 
      { 
       if (((int)c & i) > 0) 
       { 
        output += "1"; 
       } 
       else 
       { 
        output += "0"; 
       } 
      } 
     } 
     return output; 
    } 
+2

Chciałbyś przejść od tablicy bajtów do reprezentacji binarnej. Char to 16-bitowy typ danych, więc możesz odciąć osiem pierwszych bitów każdego kodu postaci. Nie używaj + = do zbudowania napisu, skaluje się to bardzo źle, zamiast tego użyj StringBuilder. – Guffa

3

Trochę późno, ale tutaj jest moje 2 centy:

var binaryStr = "01110100011001010111001101110100"; 

var byteArray = Enumerable.Range(0, int.MaxValue/8) 
          .Select(i => i*8) 
          .TakeWhile(i => i < binaryStr.Length) 
          .Select(i => binaryStr.Substring(i, 8)) 
          .Select(s => Convert.ToByte(s, 2)) 
          .ToArray(); 
File.WriteAllBytes("C:\temp\test.txt", byteArray); 
0

Właściwie odpowiedź przez @Maciej nie jest poprawna. Ponieważ @ Phate01 zauważył, że numOfBytes jest poprawny tylko dla długości wejściowej, która jest mocą 8. Drugą rzeczą jest to, że tablica bajtów powinna być wypełniona od n do 0 indeks nie w odwrotny sposób. Oto przykładowy kod:

var bits = "000011110000001000"; 
var numOfBytes = (int)Math.Ceiling(bits.Length/8m); 
var bytes = new byte[numOfBytes]; 
var chunkSize = 8; 

for (int i = 1; i <= numOfBytes; i++) 
{ 
    var startIndex = bits.Length - 8 * i; 
    if (startIndex < 0) 
    { 
     chunkSize = 8 + startIndex; 
     startIndex = 0; 
    } 
    bytes[numOfBytes - i] = Convert.ToByte(bits.Substring(startIndex, chunkSize), 2); 
} 

To może być poprawiona, aby pozbyć się if statetment ale w tej formie jest to bardziej zrozumiałe.

Powiązane problemy