안녕하세요. 명월입니다.
이 글은 byte 배열 순서 엔디언(endian)에 대한 글입니다.
endian은 간단하게 이야기하면 binary의 데이터를 배열하는 방법이며, 그 뜻은 예로 int 객체를 byte로 변환한다고 하면 그 byte데이터를 나열하는 순서입니다.
사실 제가 이 endian의 뜻을 알기 전까지 단순히 프로그램 언어별로 byte로 변환할 경우 데이터가 다르다. 그래서 그 언어에 맞게 배열을 변환해야 한다고 생각하고 있었습니다.
예를 들면, 예전에 java에서 int형의 데이터를 byte로 변환해서 C#으로 보낼 경우, 인식을 못했기 때문에 C#에 있는 Bitconvert를 모방하여 java에서 변환하는 소스를 만든 적이 있었습니다.
링크 - [Java] BitConverter
지금 생각하면 참 바보같은 일이네요... 단순히 java와 C#이 배열하는 endian이 다를 뿐이었지 이렇게 복잡하게 만들 필요가 없었습니다.
간단하게 endian에 대해 설명을 하면 빅 엔디언(Big-endian), 리틀 엔디언(Little-endian), 미들 엔디언(Middle-endian)이 존재합니다.
빅 엔디언의 경우는 값의 표시가 12 34 56 78 이 있으면 12 34 56 78로 표시가 되는 것이고 리틀 엔디언의 경우는 78 56 34 12로 표시되는 형태였습니다.
미들 엔디언은 빅 엔디언과 리틀 엔디언의 짬뽕이라고 합니다.
각기 빅 엔디언과 리틀 엔디언은 사람의 인식 과정의 편함으로 가독성이 좋냐? 먼저의 값을 내보내서 계산의 빠름이 좋냐의 차이라고 합니다.
제가 보기엔 크게 차이는 없다고 생각되는데.. 어쨋든 이게 언어 별로 byte형으로 변환할 때 채택하는 엔디언이 다르다는게 문제입니다.(통일했으면 하는데.. 프로그램이 많이 발전했어도 아직 이런 문제가 많이 있네요..)
C#은 일단 기본적으로 리틀 엔디언을 사용합니다. 자바의 경우는 빅 엔디언이 기본이네요.
참고로 문자열 UTF-8는 엔디언의 구분이 없다고 합니다.
참고 - http://mwultong.blogspot.com/2006/05/little-endian-big-endian.html
https://brownbears.tistory.com/124
그럼 엔디언의 차이를 디버깅을 통해 알아보겠습니다.
class Program
{
static void Main(string[] args)
{
byte[] data = BitConverter.GetBytes(1000);
foreach (byte b in data)
{
Console.Write(b);
Console.Write("\t");
}
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
C#은 딱 봐도 앞자리부터 수가 채워지는 것 보니 리틀 엔디언 같습니다.
import java.nio.ByteBuffer;
public class Test {
public static void main(String... args) {
ByteBuffer data = ByteBuffer.allocate(4);
data.putInt(1000);
for (byte b : data.array()) {
System.out.print(b < 0 ? b + 256 : b);
System.out.print("\t");
}
}
}
Java의 결과가 뒤에서 부터 채워지는 것 보니 빅 엔디언 같습니다.
그럼 빅 엔디언에서 리틀 엔디언으로 혹은 리틀 엔디언에서 빅 엔디언으로 바꾸는 방법은?
그렇습니다. 그냥 뒤집어 주기만 하면 됩니다.
class Program
{
static void Main(string[] args)
{
byte[] data = BitConverter.GetBytes(1000);
// 빅 엔디언으로
Array.Reverse(data);
foreach (byte b in data)
{
Console.Write(b);
Console.Write("\t");
}
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
자바의 경우는 ByteBuffer에 옵션이 있네요.. 물론 byte 배열을 뒤집어도 상관없습니다.
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class Test {
public static void main(String... args) {
ByteBuffer data = ByteBuffer.allocate(4);
// 리틀 엔디언으로!!
data.order(ByteOrder.LITTLE_ENDIAN);
data.putInt(1000);
for (byte b : data.array()) {
System.out.print(b < 0 ? b + 256 : b);
System.out.print("\t");
}
}
}
제가 예전이 이 차이를 몰라서 아예 int에서 byte로 변환하는 소스를 만들었었습니다. 그게 잘못된 건 아니였는데, 역시 표준을 제대로 모르면 일이 엄청 돌아간다는 걸 또 한번 느낍니다.
이제 서로 다른 언어나 환경에 byte로 데이터를 주고 받거나 저장할 때 이 엔디언을 꼭 확인해야 겠습니다.
여기까지 byte 배열 순서 엔디언(endian) 에 대한 설명이었습니다.
궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.
'Development note > Etc.' 카테고리의 다른 글
[정보 및 잡담] 호스팅이란? (서버 임대) (1) | 2016.03.25 |
---|---|
[정보 및 잡담] 아파치와 파이어 폭스 설치(애드온 Firebug 설치) (0) | 2015.06.30 |
[정보 및 잡담] Html에 대해서 (0) | 2015.06.17 |
[정보 및 잡담] 웹 프로토콜 (2) | 2015.06.17 |
[정보 및 잡담] 네트워크란 (인터넷(Internet), 아이피(IP), 포트(Port)) (0) | 2015.06.05 |
[정보 및 잡담] 프로토콜이란? (0) | 2012.10.14 |
[정보 및 잡담] C, C+, JAVA, C#의 차이 (11) | 2012.09.15 |
[정보 및 잡담] 프로그램 후킹과 해킹의 차이점 (3) | 2012.09.08 |