1 /// <summary> 2 /// 本類提供了對byte數據的常用操作函數 3 /// </summary> 4 public class ByteUtil 5 { 6 private static char[] HEX_CHARS = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 7 private static byte[] BITS = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; 8 9 10 /// <summary> 11 /// 將字節數組轉換為HEX形式的字符串, 使用指定的間隔符 12 /// </summary> 13 public static string ByteToHex(byte[] buf, string separator) 14 { 15 System.Text.StringBuilder sb = new System.Text.StringBuilder(); 16 for(int i = 0;i < buf.Length;i++) 17 { 18 if (i > 0) 19 { 20 sb.Append(separator); 21 } 22 sb.Append(HEX_CHARS[buf[i] >> 4]).Append(HEX_CHARS[buf[i] & 0x0F]); 23 } 24 return sb.ToString(); 25 } 26 27 28 29 30 /// <summary> 31 /// 將字節數組轉換為HEX形式的字符串, 使用指定的間隔符 32 /// </summary> 33 public static string ByteToHex(byte[] buf, char c) 34 { 35 System.Text.StringBuilder sb = new System.Text.StringBuilder(); 36 for(int i = 0;i < buf.Length;i++) 37 { 38 if (i > 0) 39 { 40 sb.Append(c); 41 } 42 sb.Append(HEX_CHARS[buf[i] >> 4]).Append(HEX_CHARS[buf[i] & 0x0F]); 43 } 44 return sb.ToString(); 45 } 46 47 48 /// <summary> 49 /// 判斷字節數組前幾位是否符合一定規則 50 /// </summary> 51 /// <param name="data">需要判斷的字節數組</param> 52 /// <param name="pattern">匹配規則</param> 53 /// <returns>如果匹配返回true</returns> 54 public static bool IsMatch(byte[] data, params byte[] pattern) 55 { 56 if (data == null || data.Length < pattern.Length) 57 return false; 58 59 60 for(int i = 0;i < pattern.Length;i++) 61 { 62 if (data[i] != pattern[i]) 63 return false; 64 } 65 return true; 66 } 67 68 69 /// <summary> 70 /// 判斷指定字節是否為列舉的某個值 71 /// </summary> 72 /// <param name="value">需要判斷的值</param> 73 /// <param name="choice">可能值</param> 74 /// <returns>如果與任一個可能值相等則返回true</returns> 75 public static bool IsMatch(byte value, params byte[] choice) 76 { 77 if (choice == null || choice.Length == 0) 78 return false; 79 80 81 foreach(byte item in choice) 82 { 83 if (item == value) 84 return true; 85 } 86 return false; 87 } 88 89 90 91 92 /// <summary> 93 /// 將字節數組轉換為HEX形式的字符串, 沒有間隔符 94 /// </summary> 95 public static string ByteToHex(byte[] buf) 96 { 97 return ByteToHex(buf, string.Empty); 98 } 99 100 101 102 103 /// <summary> 104 /// 將字節數組轉換為HEX形式的字符串 105 /// 轉換後的字符串長度為字節數組長度的兩倍 106 /// 如: 1, 2 轉換為 0102 107 /// </summary> 108 public static string ByteToHex(byte b) 109 { 110 return string.Empty + HEX_CHARS[b >> 4] + HEX_CHARS[b & 0x0F]; 111 } 112 113 114 115 116 /// <summary> 117 /// 將字節流信息轉換為HEX字符串 118 /// </summary> 119 public static string DumpBytes(byte[] bytes) 120 { 121 return DumpBytes(bytes, 0, bytes.Length); 122 } 123 124 125 /// <summary> 126 /// 將字節流信息轉換為HEX字符串 127 /// </summary> 128 public static string DumpBytes(byte[] bytes, int offset, int len) 129 { 130 StringBuilder buf = new StringBuilder(); 131 for(int i = 0;i < len;i++) 132 { 133 if (i == 0 || i % 16 == 0) 134 buf.AppendLine(); 135 136 buf.Append(ByteToHex(bytes[i + offset])); 137 buf.Append(' '); 138 } 139 buf.AppendLine(); 140 return buf.ToString(); 141 } 142 143 144 145 146 /// <summary> 147 /// 計算字節塊的模256校驗和 148 /// </summary> 149 public static byte SumBytes(byte[] bytes, int offset, int len) 150 { 151 int sum = 0; 152 for(int i = 0;i < len;i++) 153 { 154 sum += bytes[i + offset]; 155 if (sum >= 256) 156 { 157 sum = sum % 256; 158 } 159 } 160 return (byte)sum; 161 } 162 163 164 /// <summary> 165 /// 計算字節塊的模256雙字節校驗和(低位在前) 166 /// </summary> 167 public static byte[] Sum2Bytes(byte[] bytes, int offset, int len) 168 { 169 int sum = 0; 170 for(int i = 0;i < len;i++) 171 sum += bytes[i + offset]; 172 return new byte[] { (byte)(sum % 256), (byte)(sum / 256) }; 173 } 174 175 176 /// <summary> 177 /// 計算字節塊的異或校驗和 178 /// </summary> 179 public static byte XorSumBytes(byte[] bytes, int offset, int len) 180 { 181 byte sum = bytes[0 + offset]; 182 for(int i = 1;i < len;i++) 183 { 184 sum = (byte)(sum ^ bytes[i + offset]); 185 } 186 return sum; 187 } 188 189 190 191 192 /// <summary> 193 /// 計算字節塊的異或校驗和 194 /// </summary> 195 public static byte XorSumBytes(byte[] bytes) 196 { 197 return XorSumBytes(bytes, 0, bytes.Length); 198 } 199 200 201 202 203 /// <summary> 204 /// 比較兩個字節塊是否相等。相等返回true否則false 205 /// </summary> 206 public static bool CompareBytes(byte[] bytes1, int offset1, byte[] bytes2, int offset2, int len) 207 { 208 for(int i = 0;i < len;i++) 209 { 210 if (bytes1[i + offset1] != bytes2[i + offset2]) 211 { 212 return false; 213 } 214 } 215 return true; 216 } 217 218 219 /// <summary> 220 /// 將兩個字符的hex轉換為byte 221 /// </summary> 222 public static byte HexToByte(char[] hex, int offset) 223 { 224 byte result = 0; 225 for(int i = 0;i < 2;i++) 226 { 227 char c = hex[i + offset]; 228 byte b = 0; 229 switch (c) 230 { 231 case '0': 232 case '1': 233 case '2': 234 case '3': 235 case '4': 236 case '5': 237 case '6': 238 case '7': 239 case '8': 240 case '9': 241 b = (byte)(c - '0'); 242 break; 243 case 'A': 244 case 'B': 245 case 'C': 246 case 'D': 247 case 'E': 248 case 'F': 249 b = (byte)(10 + c - 'A'); 250 break; 251 case 'a': 252 case 'b': 253 case 'c': 254 case 'd': 255 case 'e': 256 case 'f': 257 b = (byte)(10 + c - 'a'); 258 break; 259 } 260 if (i == 0) 261 { 262 b = (byte)(b * 16); 263 } 264 result += b; 265 } 266 267 268 return result; 269 } 270 271 272 /// <summary> 273 /// 將兩個字符的hex轉換為byte 274 /// </summary> 275 public static byte HexToByte(byte[] hex, int offset) 276 { 277 char[] chars = {(char)hex[offset], (char)hex[offset + 1]}; 278 return HexToByte(chars, 0); 279 } 280 281 282 /// <summary> 283 /// 轉換16進制字符串為字節數組 284 /// <param name="hex">有分隔或無分隔的16進制字符串,如“AB CD EF 12 34...”或“ABCDEF1234...”</param> 285 /// <param name="dot">任意分隔字符,但不能是16進制字符</param> 286 /// <returns>字節數組</returns> 287 /// </summary> 288 public static byte[] HexToByte(string hex, params char[] dot) { 289 char[] ca = new char[2]; 290 List<byte> list = new List<byte>(); 291 for (int i = 0, n = 0; i < hex.Length; i++) { 292 if (Array.IndexOf<char>(dot, hex[i]) >= 0) { 293 continue; 294 } 295 296 297 switch (++n) { 298 case 1: 299 ca[0] = hex[i]; 300 break; 301 302 303 case 2: 304 ca[1] = hex[i]; 305 list.Add(ByteUtil.HexToByte(ca, 0)); 306 n = 0; 307 break; 308 } 309 } 310 311 312 return list.ToArray(); 313 } 314 315 316 /// <summary> 317 /// 將uint變量分解為四個字節。高位在前。 318 /// </summary> 319 public static void UintToBytes(uint i, byte[] bytes, int offset) 320 { 321 bytes[offset] = (byte)((i & 0xFF000000) >> 24); 322 bytes[offset + 1] = (byte)((i & 0x00FF0000) >> 16); 323 bytes[offset + 2] = (byte)((i & 0x0000FF00) >> 8); 324 bytes[offset + 3] = (byte)(i & 0x000000FF); 325 } 326 327 328 /// <summary> 329 /// 將uint變量分解為四個字節。高位在前。 330 /// </summary> 331 public static byte[] UintToBytes(uint i) 332 { 333 byte[] bytes = new byte[4]; 334 bytes[0] = (byte)((i & 0xFF000000) >> 24); 335 bytes[1] = (byte)((i & 0x00FF0000) >> 16); 336 bytes[2] = (byte)((i & 0x0000FF00) >> 8); 337 bytes[3] = (byte)(i & 0x000000FF); 338 return bytes; 339 } 340 341 342 /// <summary> 343 /// 將int變量分解為四個字節。高位在前。 344 /// </summary> 345 public static byte[] IntToBytes(int i) 346 { 347 byte[] data = BitConverter.GetBytes(i); 348 Array.Reverse(data); 349 return data; 350 351 352 //byte[] bytes = new byte[4]; 353 //bytes[0] = (byte)((i & 0xFF000000) >> 24); 354 //bytes[1] = (byte)((i & 0x00FF0000) >> 16); 355 //bytes[2] = (byte)((i & 0x0000FF00) >> 8); 356 //bytes[3] = (byte)(i & 0x000000FF); 357 //return bytes; 358 } 359 360 361 /// <summary> 362 /// 將四個字節合成為一個int 363 /// </summary> 364 public static uint BytesToUint(byte[] bytes, int offset) 365 { 366 uint a = ((uint)bytes[offset]) << 24; 367 uint b = ((uint)bytes[offset + 1]) << 16; 368 uint c = ((uint)bytes[offset + 2]) << 8; 369 uint d = bytes[offset + 3]; 370 return a + b + c + d; 371 } 372 373 374 /// <summary> 375 /// 將ulong變量分解為八個字節。高位在前。 376 /// </summary> 377 public static byte[] UlongToBytes(ulong i) 378 { 379 byte[] bytes = new byte[8]; 380 bytes[0] = (byte)((i & 0xFF00000000000000) >> 56); 381 bytes[1] = (byte)((i & 0x00FF000000000000) >> 48); 382 bytes[2] = (byte)((i & 0x0000FF0000000000) >> 40); 383 bytes[3] = (byte)((i & 0x000000FF00000000) >> 32); 384 bytes[4] = (byte)((i & 0x00000000FF000000) >> 24); 385 bytes[5] = (byte)((i & 0x0000000000FF0000) >> 16); 386 bytes[6] = (byte)((i & 0x000000000000FF00) >> 8); 387 bytes[7] = (byte)(i & 0x00000000000000FF); 388 return bytes; 389 } 390 391 392 /// <summary> 393 /// 將八個字節合成為一個ulong 394 /// </summary> 395 public static ulong BytesToUlong(byte[] bytes, int offset) 396 { 397 ulong a = ((ulong)bytes[offset]) << 56; 398 ulong b = ((ulong)bytes[offset + 1]) << 48; 399 ulong c = ((ulong)bytes[offset + 2]) << 40; 400 ulong d = ((ulong)bytes[offset + 3]) << 32; 401 ulong e = ((ulong)bytes[offset + 4]) << 24; 402 ulong f = ((ulong)bytes[offset + 5]) << 16; 403 ulong g = ((ulong)bytes[offset + 6]) << 8; 404 ulong h = bytes[offset + 7]; 405 return a + b + c + d + e + f + g + h; 406 } 407 408 409 410 411 /// <summary> 412 /// 設置某個字節的指定位 413 /// </summary> 414 /// <param name="b">需要設置的字節</param> 415 /// <param name="pos">1-8, 1表示最低位, 8表示最高位</param> 416 /// <param name="on">true表示設置1, false表示設置0</param> 417 public static void ByteSetBit(ref byte b, int pos, bool on) 418 { 419 int temp = BITS[pos - 1]; 420 421 422 if (!on) 423 { 424 //取反 425 temp = temp ^ 0xFF; 426 } 427 428 429 b = (byte)(on?(b | temp):(b & temp)); 430 } 431 432 433 /// <summary> 434 /// 判斷某個byte的某個位是否為1 435 /// </summary> 436 /// <param name="pos">第幾位,大於等於1</param> 437 public static bool ByteGetBit(byte b, int pos) 438 { 439 int temp = BITS[pos - 1]; 440 return (b & temp) != 0; 441 } 442 443 444 445 446 /// <summary> 447 /// 設置雙比特值 448 /// </summary> 449 /// <param name="b">需要設置的字節</param> 450 /// <param name="low">低位, 1-7</param> 451 /// <param name="val">值,0-3</param> 452 /// <returns></returns> 453 public static void ByteSetBitPair(ref byte b, int low, int val) 454 { 455 if (low < 1 || low > 7) 456 { 457 throw new ArgumentException(string.Format("無效的low值:{0}", low)); 458 } 459 460 461 switch(val) 462 { 463 case 0: 464 { 465 ByteUtil.ByteSetBit(ref b, low, false); 466 ByteUtil.ByteSetBit(ref b, low + 1, false); 467 break; 468 } 469 case 1: 470 { 471 ByteUtil.ByteSetBit(ref b, low, true); 472 ByteUtil.ByteSetBit(ref b, low + 1, false); 473 break; 474 } 475 case 2: 476 { 477 ByteUtil.ByteSetBit(ref b, low, false); 478 ByteUtil.ByteSetBit(ref b, low + 1, true); 479 break; 480 } 481 case 3: 482 { 483 ByteUtil.ByteSetBit(ref b, low, true); 484 ByteUtil.ByteSetBit(ref b, low + 1, true); 485 break; 486 } 487 default: 488 { 489 throw new ArgumentException(string.Format("無效的val值:{0}", val)); 490 } 491 } 492 } 493 494 495 496 497 /// <summary> 498 /// 讀取雙比特值 499 /// </summary> 500 /// <param name="b">需要讀取的字節</param> 501 /// <param name="low">低位, 0-6</param> 502 /// <returns>0-3</returns> 503 public static byte ByteGetBitPair(byte b, int low) 504 { 505 if (low < 0 || low > 7) 506 { 507 throw new ArgumentException(string.Format("無效的low值:{0}", low)); 508 } 509 510 511 int x = 0; 512 x += ByteUtil.ByteGetBit(b, low)?1:0; 513 x += ByteUtil.ByteGetBit(b, low + 1)?2:0; 514 515 516 return (byte)x; 517 } 518 519 520 /// <summary> 521 /// 將short轉換為兩個字節 522 /// </summary> 523 /// <param name="s"></param> 524 /// <returns></returns> 525 public static byte[] ShortToByte(short s) 526 { 527 return UshortToByte((ushort)s); 528 } 529 530 531 /// <summary> 532 /// 將ushort轉換為兩個字節 533 /// </summary> 534 public static byte[] UshortToByte(ushort u) 535 { 536 return new byte[]{ 537 (byte)(u >> 8), 538 (byte)(u & 0x00FF) 539 }; 540 } 541 542 543 /// <summary> 544 /// 將兩個字節轉換為一個short 545 /// </summary> 546 public static short BytesToShort(byte[] data, int offset) 547 { 548 short a = data[offset], b = data[offset + 1]; 549 return (short)((a << 8) + b); 550 } 551 552 553 /// <summary> 554 /// 將兩個字節轉換為一個short 555 /// </summary> 556 public static ushort BytesToUshort(byte[] data, int offset) 557 { 558 ushort a = data[offset], b = data[offset + 1]; 559 return (ushort)((a << 8) + b); 560 } 561 562 /// <summary> 563 /// 將四個字節轉換為int 564 /// </summary> 565 /// <param name="data"></param> 566 /// <param name="offset"></param> 567 /// <returns></returns> 568 public static int BytesToInt(byte[] data, int offset) 569 { 570 return (data[offset] << 24) + (data[offset + 1] << 16) + (data[offset + 2] << 8) + data[offset + 3]; 571 } 572 573 574 /// <summary> 575 /// 將guid字符串轉換為等價的16維字節數組 576 /// </summary> 577 public static byte[] GuidToBytes(string s) 578 { 579 byte[] guid = new byte[16]; 580 char[] hex = s.Replace("-", string.Empty).Replace(" ", string.Empty).ToCharArray(); 581 for (int i = 0; i < 32; i += 2) 582 { 583 guid[i / 2] = ByteUtil.HexToByte(hex, i); 584 } 585 return guid; 586 } 587 588 589 /// <summary> 590 /// CRC16校驗表 591 /// </summary> 592 static ushort[] wCRCTalbeAbs = {0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400}; 593 594 595 /// <summary> 596 /// 計數字節塊的CRC16校驗值 597 /// </summary> 598 public static int CRC16Bytes(byte[] bytes, int offset, int len) 599 { 600 int wCRC = 0xFFFF; 601 byte chChar; 602 603 604 for (int i = offset; i < len; i++) 605 { 606 chChar = bytes[i]; 607 wCRC = wCRCTalbeAbs[(chChar ^ wCRC) & 15] ^ (wCRC >> 4); 608 wCRC = wCRCTalbeAbs[((chChar >> 4) ^ wCRC) & 15] ^ (wCRC >> 4); 609 } 610 611 612 return wCRC; 613 } 614 615 616 /// <summary> 617 /// 字節格式化,將字節轉換為字節、KB、MB、GB顯示 618 /// </summary> 619 /// <param name="bytes">字節數</param> 620 /// <returns>格式化後的字符串</returns> 621 public static string ByteFormater(long bytes) 622 { 623 const long KB = 1024; 624 const long MB = 1024 * 1024; 625 const long GB = 1024 * 1024 * 1024; 626 627 628 if (bytes >= GB) 629 { 630 double result = bytes * 1.0 / GB; 631 return result.ToString("#,##0.0") + "GB"; 632 } 633 if (bytes >= MB) 634 { 635 double result = bytes * 1.0 / MB; 636 return result.ToString("#,##0.0") + "MB"; 637 } 638 if (bytes >= KB) 639 { 640 double result = bytes * 1.0 / KB; 641 return result.ToString("#,##0.0") + "KB"; 642 } 643 return bytes.ToString("#,##0") + "字節"; 644 } 645 }