Home Full Site
byte와 16진수 문자열 간의 변환

byte 혹은 byte 배열을 16진 문자열로 변경하거나 반대로 16진수 문자열을 byte나 byte 배열로 변경해야 할 경우가 있다. 아래는 각각의 경우에 대한 변환 방법이다.

하나의 byte를 16진수(Hex) 문자열로 변경하는 것은 byte의 ToString("X2") 메서드를 사용하여 간단히 변환할 수 있다 (아래 예제 1번).

복수의 byte들 즉 바이트 배열을 16진수 문자열로 변경하기 위해서는 바이트 하나 하나를 16진수 문자열로 변환한 후 이를 모두 결합시키면 되는데, 아래 예제 2번과 같이 Array.ConvertAll() 메서드과 String.Concat() 를 쓰면 간단하게 전체 변환을 수행할 수 있다. 또 다른 방식으로는 BitConverter.ToString() 메서드를 사용할 수 있는데, 이 메서드는 바이트배열을 A1-B2-C3-11-2F 와 같이 "-" 로 연결된 16진수 문자열을 변환해 준다. 여기서 "-" 이 필요 없는 경우에는 아래 예제 3번과 같이 Replace()를 써서 이를 제거한다.

하나의 16진수 문자열을 한 byte로 변환하는 방법은 Convert.ToByte()를 쓰거나 byte.Parse() 메서드를 사용할 수 있다. (아래 예제 3번).

여러 16진수 문자열을 byte[] 배열로 변환하기 위해서는 아래 예제 4번과 같이 16진수 문자열을 2 문자씩 떼어내어 이를 바이트로 변환하고 바이트배열에 순차적으로 할당한다. 아래 예제는 for 루프를 사용하여 Hex 문자를 바이트로 변환하여 해당 배열요소에 할당하는 예이다.


예제

// (1) 한 byte 를 Hex 문자로 변환하는 방법
byte b1 = 0xFE;
string hex1 = b1.ToString("X2");

// (2) byte[] 을 Hex 문자열로 변환하는 방법
byte[] bytes = new byte[] { 0xA1, 0xB2, 0xC3, 0x11, 0x2F };
string h = string.Concat(Array.ConvertAll(bytes, byt => byt.ToString("X2")));
// 혹은
// h = BitConverter.ToString(bytes).Replace("-", "");


// (3) 한 Hex 문자를 byte 로 변환하는 방법
byte b2 = Convert.ToByte("3F", 16);
// 혹은
// b2 = byte.Parse("3F", NumberStyles.HexNumber);

// (4) 여러 Hex 문자열을 byte[] 로 변환하는 방법
string hexString = "A1B2C3";
byte[] xbytes = new byte[hexString.Length / 2];
for (int i = 0; i < xbytes.Length; i++)
{
    xbytes[i] = Convert.ToByte(hexString.Substring(i*2, 2), 16);
}



byte와 비트 문자열 간의 변환

바이트를 0과 1로된 비트 문자열로 변환하거나 반대로 비트 문자열을 바이트로 변환하는 방법을 소개한다.

하나의 byte를 2진수 비트 문자열로 변경하는 것은 Convert.ToString() 메서드를 사용하여 변환할 수 있다. 단, 아래 예제 1번에서 처럼 0x11 인 경우 Convert.ToString() 메서드는 유효숫자 "10001" 만을 리턴하기 때문에, 8비트 모두를 넣기 위해 PadLeft() 메서드를 써서 전체 자리가 8자리이고 빈 자리에 문자 "0"을 넣으라고 지정해 주어야 한다.

만약 byte가 아니고 4 바이트 크기의 int 인 경우 동일한게 Convert.ToString() 메서드를 사용하여 변환하고, 아래 예제 2번과 같이 PadLeft()의 전체 자릿수를 32로 지정한다.

위와 반대로 2진수 비트 문자열을 byte 로 변환하기 위해서는 Convert.ToByte() 를 사용한다 (아래 예제 3번). 또한, 32비트 비트 문자열을 int로 변환하기 위해서는 Convert.ToInt32()을 사용한다 (아래 예제 4번).


예제

// (1) byte를 비트문자열로 변환
byte a = 0x11;
string s = Convert.ToString(a, 2).PadLeft(8, '0'); // 00010001

// (2) int를 비트문자열로 변환
int j = 0x01020304;
s = Convert.ToString(j, 2).PadLeft(32, '0');

// (3) 비트 문자열을 1 바이트로 변환
string bitStr = "01110000";
byte b = Convert.ToByte(bitStr, 2); // 112 = 0x70

// (4) 비트 문자열을 int 로 변환
string bstr = "00000001000000100000001100000100";
int i = Convert.ToInt32(bstr, 2);  // 16909060 = 0x01020304      



byte의 비트 연산

C# 비트 연산자(bitwise operator)는 AND (&), OR (|), XOR (^), NOT (~), Left Shift (<<), Right Shift (>>) 가 있으며, byte 간 비트 연산도 이러한 비트 연산자를 사용하는데, 바이트 간 비트 연산 수행후 결과를 다시 byte 에 담기 위해서는 비트 연산 결과를 byte로 캐스팅 해 주어야 한다. (주: 비트 연산 후 결과를 int로 리턴하기 때문에, 이를 다시 byte에 담기 위해서는 (byte)로 캐스팅해야 한다)

아래 예제는 2개의 바이트 간에 다섯가지 비트 연산을 수행한 예이다.


예제

byte x = 0xF1;
byte y = 0x1F;

byte a = (byte)(x & y);  // 0x11
byte o = (byte)(x | y);  // 0xFF
byte c = (byte)(x ^ y);  // 0xEE
byte d = (byte) ~x;      // 0x0E

byte e = (byte)(x << 2); // 0xC4
byte f = (byte)(y >> 2); // 0x07



BitArray 클래스를 활용한 비트 처리

C# 데이타 타입의 가장 작은 단위는 byte로서 한 바이트는 8 비트를 가지고 있다. 바이트 내의 각 비트 단위로 처리하기 위해서는 일반적으로 Shift 와 비트 연산자를 사용하여 비트별 값들을 읽거나 쓰게 된다. 이러한 불편함을 해소시키기 위해 .NET Framework에서 BitArray 클래스를 제공하고 있다.

BitArray 클래스는 특정 비트를 읽거나 쓰기에 편리한 기능을 제공하고 있으며, 개발자가 지정한 (임의의) 숫자의 비트들을 핸들링할 수 있도록 필요한 공간들을 내부에서 자동으로 처리해 준다.

BitArray 생성자에서 비트수를 파라미터로 지정하면, 해당 비트수만큼의 비트들을 사용할 수 있는 객체를 생성해 준다. 즉, new BitArray(8) 은 8비트를 갖는 객체를 생성한다. 비트인덱스는 첫번째 비트가 0, 두번째 비트가 1, ... 등과 같이 붙여진다. BitArray 생성자는 또한 bool[] 배열 혹은 byte[] 배열을 받아들여 비트들을 초기화할 수 있다.

비트를 읽을 때는 Get(비트인덱스) 메서드를 사용하고, 쓸 때는 Set(비트인덱스, true/false) 메서드를 사용한다. 즉, 3번째 비트를 1로 하기 위해서는 Set(2, true) 와 같이 사용하며, 다시 3번째 비트를 읽을 때는 Get(2) 를 사용한다. BitArray 클래스는 또한 Indexer 를 지원하고 있는데, 이를 사용하면 Get과 Set 기능을 인덱서를 통해 쉽게 사용할 수 있다.

그리고 BitArray는 비트 연산을 쉽게 하기 위해 And(), Or(), Xor(), Not() 같은 Bitwise 연산 메서드들을 제공하고 있다.


예제

void TestBitArray()
{
    // 8개의 비트를 갖는 BitArray 객체 생성
    BitArray ba1 = new BitArray(8);

    // ## 비트 쓰기 ##
    ba1.Set(0, true);
    ba1.Set(1, true);

    PrintBits(ba1);  // 11000000

    BitArray ba2 = new BitArray(8);
    ba2[1] = true;
    ba2[2] = true;
    ba2[3] = true;
    PrintBits(ba2);  // 01110000

    // ## 비트 읽기 ##
    bool b1 = ba1.Get(0); // true
    bool b2 = ba2[4];     // false


    // ## BitArray 비트 연산 ##
    // OR (ba1 | ba2) 결과를 ba1 에
    ba1.Or(ba2);  
    PrintBits(ba1);  // 11110000

    // AND (ba1 & ba2) 결과를 ba1 에
    ba1.And(ba2);
    PrintBits(ba1);  // 01110000

    ba1.Xor(ba2);
    ba1.Not();


    // ## 기타 BitArray 생성 방법 ##
    // bool[] 로 생성
    var bools = new bool[] { true, true, false, false };
    BitArray ba3 = new BitArray(bools);

    // byte[] 로 생성
    var bytes = new byte[] { 0xFF, 0x11 };
    BitArray ba4 = new BitArray(bytes);          
}

void PrintBits(BitArray ba)
{
    for (int i = 0; i < ba.Count; i++)
    {
        Console.Write(ba[i] ? "1" : "0");
    }
    Console.WriteLine();
}



© csharpstudy.com