トップ回答者
16ビット単位でリトルエンディアンにしたい

質問
-
いつもお世話になります。
VisualC#2010、WindowsXPでの動作について質問があります。E0 FF 06 00 00 00 02 00 22 01 E1 FF
というようなbyte[]配列(bs)を
FFE0 0006 0000 0002 0122 FFE1
のようなリトルエンディアンの文字列にしたいです。
if (BitConverter.IsLittleEndian) {
Array.Reverse(bs);
string littleendiantext = BitConverter.ToString(bs);
}
とすると、FF-E1-01-22-00-02-00-00-00-06-FF-E0
のように、配列全体を逆転してしまいます。
どのようにしたらよいでしょう。
あと、区切りを16ビットずつにしたいです。
あわせてご示唆ください。
回答
-
var bytes = new byte[] { 0xE0, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x22, 0x01, 0xE1, 0xFF };
var list = bytes.Where((v,i)=>i%2==1)
.Zip( bytes.Where((v,i)=>i%2==0),
(b2,b1)=>b2.ToString("x2")+b1.ToString("x2"));こういうのもありだと思います。2つの集合に分割しといてZipでくっつける。
文字列かするならこれをさらにConsole.Write(string.Join(" ",list.ToArray()));
でしょうか。
- 回答としてマーク d-kot 2010年11月18日 12:41
すべての返信
-
var bytes = new byte[] { 0xE0, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x22, 0x01, 0xE1, 0xFF };
var list = bytes.Where((v,i)=>i%2==1)
.Zip( bytes.Where((v,i)=>i%2==0),
(b2,b1)=>b2.ToString("x2")+b1.ToString("x2"));こういうのもありだと思います。2つの集合に分割しといてZipでくっつける。
文字列かするならこれをさらにConsole.Write(string.Join(" ",list.ToArray()));
でしょうか。
- 回答としてマーク d-kot 2010年11月18日 12:41
-
Enumerable.Zip()を使うということは.NET 4ですが、だとしたらstring.Join()のためにToArray()する必要はありませんよ。
2つずつのペアを作るアプローチだと
var i = 0;
Console.WriteLine(string.Join(" ", bs.GroupBy(_ => i++ / 2).Select(g => string.Format("{1:X2}{0:X2}", g.Cast<object>().ToArray()))));なるほど。どちらにしても単にバイト順を入れ替えたいのか、エンディアンを意識して入れ替えたいのかはっきりしないことには、ですが。それとArray.Reserve()を持ち出す人にLinqが通用するかも気になるところ。
-
佐祐理さん、説明がわけわからずすみません。
E0 FF 06 00 00 00 02 00 22 01 E1 FF
を
FFE0 0006 0000 0002 0122 FFE1
としたい、ということだけです。Array.Reserve()を持ち出す人にLinqが通用するかも気になるところ。
と、いろいろご心配いただいておりますが、
Linqは好きです。
初心者にはむしろ、Linqのほうが、すっきり書けて理解しやすいように思います。
わからなければ何度でもききますので、ご心配無用で、最良のコードを、コードで教えていただければと。ちなみに自分では、
int lowhigh = 1;
string buffer = "";
foreach(byte b in bs) {
string sixteen = int.Parse(b.ToString()).ToString("X").ToLower();
if (sixteen.Length == 1) sixteen = "0" + sixteen;
if (lowhigh%2 == 1) buffer = sixteen;
else log += "0x" + sixteen + buffer + " ";
lowhigh++;
}
のようにして実現できていました。
質問したときから、0xを追加してffe0のように小文字化してみました。 -
-
string.Format()に渡すフォーマット文字列は複合書式設定 に説明がありますが、
{index[,alignment][:formatString]}
と3つのフィールドに分かれます。このformatStringにはいろいろ指定できて標準の数値書式指定文字列 で説明されています。
"0x"を付け加えたいのなら0x{0:x4}のように書式設定の外に書くまでです。
なお、渋木宏明さん・竹原貴司さんが使われているToString()メソッドではformatString部分を指定します。(その分、表現力が弱いです。) -
補足説明ありがとうございました。
.Select(v => "0x" + v.ToString("x4"))
で、動作することを確認できました。.Select( i => string.Format( "0x{1:x2}{0:x2}",
でも同様の結果を得ました。
string.Join( " ", Enumerable.Range( 0, bs.Length / 2 )
.Select( i => "0x" + bs[i*2+1] .ToString("x2") + bs[i*2+0].ToString("x2"))) ;
と書けるのも確認しました。 -
素直にMemoryStream から BinaryReader で読めばいいですよ。
class Program
{
static void Main(string[] args)
{
var array = new byte[] { 0xE0, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x22, 0x01, 0xE1, 0xFF };
var memStream = new MemoryStream(array);
BinaryReader binaryReader = new BinaryReader(memStream);
for (int i = 0; i < memStream.Length; i += 2)
{
Console.Write("{0:X04} ", binaryReader.ReadInt16());
}
Console.ReadLine();
}
}
Kazuhiko Kikuchi