跟電腦打交道難免經常需要輸出一個位元組數組。這篇文章就講講怎樣輸出一個位元組數組在.NET下的各種方法:
最快捷方法:
string BitConverter.ToString(byte[])方法。(有重載支援位元組數組的部分輸出)
代碼:
Console.WriteLine(BitConverter.ToString(new byte[] { 1, 3, 54, 123, 199, 200, 215, 255 }));
輸出:
01-03-36-7B-C7-C8-D7-FF
缺點是無法自訂中間的間隔符(或者去掉中間的間隔符)。
如果需要修改(或去掉)間隔符的話,最簡單的方法就是直接替換:
Console.WriteLine(BitConverter.ToString(new byte[] { 1, 13, 54 }).Replace("-", ""));
不過還是自己定義一個比較好:
//自訂輸出字元數組方法
static string GetBytesString(byte[] bytes, int index, int count, string sep)
{
var sb = new StringBuilder();
for (int i = index; i < count - 1; i++)
{
sb.Append(bytes[i].ToString("X2") + sep);
}
sb.Append(bytes[index + count - 1].ToString("X2"));
return sb.ToString();
}
上面這個GetBytesString方法看起來簡單易懂了,當然還有其他方法使它更簡潔,看看下面這個修改後的GetBytesString,用String.Join和LINQ,一句話搞定上面的代碼:
//自訂輸出字元數組方法(更簡潔)
static string GetBytesString(byte[] bytes, int index, int count, string sep)
{
return String.Join(sep, bytes.Skip(index).Take(count).Select(b => b.ToString("X2")));
}
上面提到了LINQ,那麼就用純LINQ來試試解決這個問題,看下面代碼(有點可拍):
//自訂輸出字元數組方法(純LINQ。除了字串串連,格式化,返回字串,這些LINQ不可能做到的)
static string GetBytesString(byte[] bytes, int index, int count, string sep)
{
return new string(bytes.Skip(index).Take(count - 1).Select(b => b.ToString("X2") + sep).SelectMany(i => i.ToCharArray()).Concat(bytes.Skip(index + count - 1).Take(1).SelectMany(b => b.ToString("X2").ToCharArray())).ToArray());
}
上面這些代碼都可以正確輸出結果,比如:
Console.WriteLine(GetBytesString(new byte[] { 34, 5, 1, 13, 54 }, 2, 3, " = "));
輸出:
01 = 0D = 36
最後還可以通過繼承.NET中的IFormatProvider和ICustomFormatter來自訂格式器來提供對位元組數組的輸出,通過格式字串來指定間隔符,最後使用String.Format來定義自訂格式器,格式字串從而將位元組數組輸出,代碼:
/// <summary>
/// 自訂格式器
/// </summary>
class MyFormatter : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatterType)
{
if (formatterType == typeof(ICustomFormatter))
return this;
return null;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
//判斷是位元組數組,並根據格式字串來返回相應結果
if (arg is byte[])
return GetBytesString((byte[])arg, format);
throw new NotSupportedException();
}
static string GetBytesString(byte[] bytes, string sep)
{
return String.Join(sep, bytes.Select(b => b.ToString("X2")));
}
}
public class Program
{
static void Main(string[] args)
{
var bytes = new byte[] { 34, 13, 43, 92, 222 };
//使用String.Format來定義一個格式器(IFormatProvider)
Console.WriteLine(String.Format(new MyFormatter(), "{0: =|= }\n{1:-}\n{2}", bytes, bytes, bytes));
}
}
輸出:
22 =|= 0D =|= 2B =|= 5C =|= DE
22-0D-2B-5C-DE
220D2B5CDE
結果都正確。
上述方法我沒有測試過效能,當然某些方法效能一看就知道不怎麼地(比如那個純LINQ的,用字串替換的可能也會稍慢些)。
不過從中我最大的感觸就是.NET的靈活性真是無處不在啊,細細品味,蠻有趣的。