2017-11-07 34 views
1

bitarrayをユニコード文字列に変換する必要があります(文字列型の場合はvb.netのデフォルトエンコーディング)。ChrW関数を使用せずにbitarrayを文字列に変換する

たとえば、000000000100000100000000010000100000000001000011が3 x 16ビットのユニコード文字のビットストリング表現であるとします。 B = 66およびC = 67(codePointsはこれらのビットの整数への変換をもたらした)。

これらのビットは、ビット配列で格納されます。 ChrW組み込み関数を使用せずにビット配列を文字列に変換する方法はありますか?

エンコーディングの際に既にビットが順序付けされているので、私はこれを必要とします。そのため、パフォーマンスを向上させるためにダブル変換を避けようとします。

+0

は、あなたがループして行うことができ、何かで、 SubString。バイナリ文字列を整数に変換する最良の方法がわからない。しかし、その整数の文字を取得するためにChrWを使用すると、行く方法です。 – dwilliss

+0

あなたのビット列は実際にはビッグエンディアンのUnicodeです。 VB.NETのデフォルトはリトルエンディアンのUnicodeだと思います。私は 'BitArray'の代わりに' Byte'配列を使い、 'String'との変換に' System.Text.Encoding'を使う方が良いと思います。 – SSS

+0

@dviliss - 私は 'ChrW'を使用したいと言っています遅い –

答えて

1

使用Byte()System.Text.Encoding ...

'BIN: 00000000 01000001 00000000 01000010 00000000 01000011 
'HEX: 0 0 4 1 0 0 4 2 0 0 4 3 
Dim s1 As String = "ABC" 
Console.WriteLine("Original string:" & s1) 
Dim b1 As Byte() = System.Text.Encoding.BigEndianUnicode.GetBytes(s1) 
Console.WriteLine("Big-endian UTF-16 (Hex):" & BitConverter.ToString(b1)) 
b1(1) = b1(1) Or CByte(&H4) 'change byte 1 from 01000001 to 01000101 
Dim s2 As String = System.Text.Encoding.BigEndianUnicode.GetString(b1) 
Console.WriteLine("Modified string:" & s2) 
Console.ReadKey() 
+0

'BitConverter.IsLittleEndian'はあなたの現在のアーキテクチャが大きいか小さいエンディアンかを教えてくれます – SSS

+0

とてもいいです!ありがとうございました。今度は私のコードでいくつかの修正を行い、速度をテストするよりもそうです。それはビットを読むことについてだけであるので、速くなければなりません。私はbyte()への変換があまりにも高価ではないことを願っています。 –

+0

'b1(1)= CByte(b1(1)Or&H4)'を 'b1(1)= b1(1)またはCByte(&H4)'に変更しました。 'Integer'から' Byte'への型変換を避けます。 – SSS

1

、これは実際にChrW()を使用するよりも速くなるだろう、それはどちらか、おそらくきれいな解決策ではない場合、私は知りません;)が、私はここにどのように私ですそれをしなかった:

あなたは、私はこれらの手順をした聞いて何を行うには:

  1. .NETは、左からそれらを解釈するので(ビット配列をリバース右から左にではなく右に)

  2. ビットのバイト配列を作成します。配列のサイズは、8ビット(8ビット= 1バイト)を最も近い整数に切り上げたビット数(Math.Ceiling()を参照)でなければなりません。

  3. Encoding.Unicodeを使用して、バイト配列を文字列にデコードします。

  4. 文字列を文字の配列に変換し、逆に変換し、新しい文字配列を文字列に変換し直します。

私は、関数の中で一緒にこれを入れている:

Public Function BitArrayToString(ByVal Bits As BitArray) As String 
    'Reverse the bits (I didn't have access to a compiler tha supports Linq, please don't hate). 
    Dim ReversedValues As Boolean() = New Boolean(Bits.Count - 1) {} 
    For x As Integer = 0 To Bits.Count - 1 
     ReversedValues((ReversedValues.Length - 1) - x) = Bits(x) 
    Next 

    'Put the reversed bits into a new bit array. 
    Dim ReversedBits As New BitArray(ReversedValues) 

    'Declare a byte array to 1/8th of the bit array's size, rounded up to the nearest integer. 
    Dim Bytes As Byte() = New Byte(Math.Ceiling(ReversedBits.Length/8) - 1) {} 
    ReversedBits.CopyTo(Bytes, 0) 

    'Decode the byte array into a string. 
    Dim Result As String = System.Text.Encoding.Unicode.GetString(Bytes) 

    'Get the string as a char array and reverse it. 
    Dim Chars As Char() = Result.ToCharArray() 
    Array.Reverse(Chars) 

    'Return the resulting string from our reversed chars. 
    Return New String(Chars) 
End Function 

オンラインテスト:最大16本の文字のストリングに文字列を破るhttps://ideone.com/SUTWlJ

+0

素敵な仕事、ありがとう。しかし、 'Math.Ceiling'はChrWよりも高価です。これは実際に遅い関数ではありません。単純にビットを読むよりも遅いですが、確かに 'Math'演算よりも遅くはありません。 –

+0

@ソーリンGFS:これは本当に必要なものですか? 'ChrW()'や 'Math.Ceiling()'が実際に違いを生むように、あなたが本当に重要なことを実際に開発していると信じています。どのような操作をしなくても、どうやってこれをやろうとしていますか? 'Math.Ceiling()'と 'ChrW()'は**非常に**高速で、_ ** less ** _ _ 0,3マイクロ秒** _より実行されます。この例で見られるように、同時に実行して測定するには、同時に0.4〜0.6マイクロ秒しかかかりません:https://ideone.com/cgBiKi –

+0

'Math.Ceiling()'と ' ChrW() '。単一の数学/ルックアップの評価は、通常はそれほど時間がかかりませんが、それは高価な_ **ルーピング** _です。 - ところで、あなたが私の例で見る最初の測定は、それらの行の編集だけです。これはいつも一度だけです。 –

関連する問題