byte to HexString (byte 16진수 문자열 변환)

byte to HexString


byte를 HexString으로 변환 하는 방법을 구글에서 찾아보면 아래 소스를 볼 수 있다.


1
Integer.toString(((byteData & 0xff)+0x10016).substring(1);
cs


 Integer.toString(int값,  16) 메소드를 통해서 정수값을 16진수로 변환하는 것은 소스코드를 보고도 명확히 알 수 있다. 그런데 왜 byteData에 &0xff 비트연산을 해주고, 0x100을 더해주는지에 대한 설명은 아무리 찾아봐도 없다. 그래서 같은 고민을 가지고 계신 분들을 위하여 &0xff와 +0x100에 대한 의문을 풀어보고자 한다.



byte&0xff


byte형은 8비트의 공간을 차지한다. int는 32비트의 공간을 차지한다. 비트연산자 &을 수행하는 경우 비트수가 넓은 곳에 맞춰서 낮은 비트를 가진 자료형을 확장한다. 즉 byteData&0xff를 수행하는 경우 byte는 32비트의 int형으로 강제 형변환이 된다. 이 때 byteData의 가장 앞에 비트가 0인 경우는 0으로 채운다. 하지만 1인 경우는 비트 확장시 모든 비트를 1로 채운다. 이 경우에 원본 값과는 전혀 다른 값이 되어버리기 때문에 &0xFF와 비트 연산을 수행하여 주는 것이다. 즉 앞에 불필요하게 (정확히는 컴퓨터구조의 음수표현 때문에) 의도치 않게 채워진 1을 전부 0으로 바꿔주기 위해서 수행한다.


byte의 첫번 째 비트가 0인 경우


1
2
3
4
5
int i = 1// 00000000 00000000 00000000 00000001
System.out.println(Integer.toBinaryString(i)); // 00000000 00000000 00000000 00000001     
        
byte b = (byte)i; // 00000001
System.out.println(Integer.toBinaryString(b)); // 00000000 00000000 00000000 00000001
cs


4번 line에서 int를 byte로 형변환 하는 경우 뒤에 마지막 8비트만 저장되고 앞에는 버려진다. 그래서 byte b = 00000001이 된다.

이때 5번 line에서 int로 다시 형변환 되어도 원래 숫자가 0으로 채워져서 처음 int i와 동일 한 결과가 나온다.


byte의 첫번 째 비트가 1인 경우


1
2
3
4
5
int i = 150// 00000000 00000000 00000000 10010110
System.out.println(Integer.toBinaryString(i)); // 00000000 00000000 00000000 10010110     
        
byte b = (byte)i; // 10010110
System.out.println(Integer.toBinaryString(b)); // 11111111 11111111 11111111 10010110
cs


byte의 첫번째 비트가 1인 경우는 5번 line에서 출력시 int로 변환 되면서 2의 보수법 처리 때문에 모든 비트가 1로 채워지는 것을 볼 수 있다. 

즉, 최초에 150의 값과는 전혀 다른 값으로 변형되기 때문에 문제가 발생하게 된다.


&0xff


1
2
3
4
5
int i = 150// 00000000 00000000 00000000 10010110
System.out.println(Integer.toBinaryString(i)); // 00000000 00000000 00000000 10010110     
        
byte b = (byte)i; // 10010110
System.out.println(Integer.toBinaryString(b&0xff)); // 00000000 00000000 00000000 10010110
cs

 0xff              

  00000000 0000000 0000000 11111111

 (int)150

  00000000 0000000 0000000 10010110 

 (byte)150

  10010110
 (int)(byte)150   11111111 11111111 11111111 10010110 

 (byte)150 & 0xff

  00000000 0000000 0000000 10010110 


두 값을 비트 연산 &를 하는경우 각 비트 자리가 모두 1이여야 1의 결과가 나오기 때문에 00000000 0000000 0000000 10010110 이 출력되어 정상적으로 처리 되는 것을 알 수 있다. 물론 byte의 앞에 위치한 비트들이 0으로 채워지는 경우도 0&0 = 0 이기 때문에 위와 같이 &0xff를 해주면 1인 경우와 0인 경우 모두 문제 없이 초기에 int형 데이터로 복원이 가능하다.


 

(byte&0xff)+0x100


제는 +0x100을 해주는 이유에 대해서 알아보자. 결론부터 말하면 0x100을 해주어도 안해주어도 값 자체는 동일하게 나온다. 대신에 0x100을 Integer.toString(n, 16) 메소드의 결과값을 강제로 3자리로 만들어 준다. 


1
2
3
4
5
int i = 1;
System.out.println( Integer.toString((byte)i & 0xff16) ); // 16 진수 "1"이 출력
        
int j = 200;
System.out.println( Integer.toString((byte)j & 0xff16) ); // 16 진수 "c8"이 출력
cs


위에 예제처럼 별다른 조작 없이 &0xff만 수행하는 경우 2진수 1~16까지의 16진수 변환 결과는 아래와 같다.

1  -> 1

2  -> 2

3  -> 3

4  -> 4

5  -> 5

6  -> 6

7  -> 7

8  -> 8

9  -> 9

10 -> a

11 -> b

12 -> c

13 -> d

14 -> e

15 -> f

16 -> 10


+0x100


즉, 2진수 16이상의 숫자는 모두 2라의 String으로 리턴, 2진수 16미만의 숫자는 1자리의 String으로 리턴되기 때문에 추후에 String데이터를 저장할 때 다른 문제가 생기는 것을 방지하기 위해서 강제로 +0x100을 더하여 아래와 같이 변형하여 주는 것이다.


1
2
3
4
5
int i = 1;
System.out.println( Integer.toString(((byte)i & 0xff)+0x10016) ); // 16 진수 "101"이 출력
        
int j = 200;
System.out.println( Integer.toString(((byte)j & 0xff)+0x10016) ); // 16 진수 "1c8"이 출력
cs

1  -> 101

2  -> 102

3  -> 103

4  -> 104

5  -> 105

6  -> 106

7  -> 107

8  -> 108

9  -> 109

10 -> 10a

11 -> 10b

12 -> 10c

13 -> 10d

14 -> 10e

15 -> 10f

16 -> 110


+0x100 ).substring(1)

0x100을 더하여 주어 강제로 3자리의 String으로 변경 하였다. 이제 불필요하게 붙은 제일 앞에 1만 제거해주면 된다.

1
2
3
4
5
int i = 1;
System.out.println( Integer.toString(((byte)i & 0xff)+0x10016).substring(1) ); // 16 진수 "01"
        
int j = 200;
System.out.println( Integer.toString(((byte)j & 0xff)+0x10016).substring(1) ); // 16 진수 "c8"
cs


위처럼 처리 결과에 substring(1)을 하여주면 


1  -> 101 -> 01

2  -> 102 -> 02

3  -> 103 -> 03

4  -> 104 -> 04

5  -> 105 -> 05

6  -> 106 -> 06

7  -> 107 -> 07

8  -> 108 -> 08

9  -> 109 -> 09

10 -> 10a -> 0a

11 -> 10b -> 0b

12 -> 10c -> 0c

13 -> 10d -> 0d

14 -> 10e -> 0e

15 -> 10f -> 0f

16 -> 110 -> 10


으로 2자리에 맞게 16진수가 정상적으로 변경되어 출력되는 것을 확인 할 수 있다.





정리


각 케이스 별로 출력결과를 정리 한 아래 표를 참고하여 이해하면 이해하기 쉽다.


2진수

16진수

Integer.toString(((byte)i & 0xff), 16)

16진수

Integer.toString(((byte)i & 0xff)+0x100, 16).substring(1)

0

0

00

1

1

01

2

2

02

3

3

03

4

4

04

5

5

05

6

6

06

7

7

07

8

8

08

9

9

09

10

a

0a

11

b

0b

12

c

0c

13

d

0d

14

e

0e

15

f

0f

16

10

10

17

11

11

18

12

12

19

13

13

20

14

14

21

15

15

22

16

16

23

17

17

24

18

18

25

19

19

26

1a

1a

27

1b

1b

28

1c

1c

29

1d

1d

30

1e

1e

31

1f

1f

32

20

20

33

21

21

34

22

22

35

23

23

36

24

24

37

25

25

38

26

26

39

27

27

40

28

28

41

29

29

42

2a

2a

43

2b

2b

44

2c

2c

45

2d

2d

46

2e

2e

47

2f

2f

48

30

30

49

31

31

50

32

32

51

33

33

52

34

34

53

35

35

54

36

36

55

37

37

56

38

38

57

39

39

58

3a

3a

59

3b

3b

60

3c

3c

61

3d

3d

62

3e

3e

63

3f

3f

64

40

40

65

41

41

66

42

42

67

43

43

68

44

44

69

45

45

70

46

46

71

47

47

72

48

48

73

49

49

74

4a

4a

75

4b

4b

76

4c

4c

77

4d

4d

78

4e

4e

79

4f

4f

80

50

50

81

51

51

82

52

52

83

53

53

84

54

54

85

55

55

86

56

56

87

57

57

88

58

58

89

59

59

90

5a

5a

91

5b

5b

92

5c

5c

93

5d

5d

94

5e

5e

95

5f

5f

96

60

60

97

61

61

98

62

62

99

63

63

100

64

64

101

65

65

102

66

66

103

67

67

104

68

68

105

69

69

106

6a

6a

107

6b

6b

108

6c

6c

109

6d

6d

110

6e

6e

111

6f

6f

112

70

70

113

71

71

114

72

72

115

73

73

116

74

74

117

75

75

118

76

76

119

77

77

120

78

78

121

79

79

122

7a

7a

123

7b

7b

124

7c

7c

125

7d

7d

126

7e

7e

127

7f

7f

128

80

80

129

81

81

130

82

82

131

83

83

132

84

84

133

85

85

134

86

86

135

87

87

136

88

88

137

89

89

138

8a

8a

139

8b

8b

140

8c

8c

141

8d

8d

142

8e

8e

143

8f

8f

144

90

90

145

91

91

146

92

92

147

93

93

148

94

94

149

95

95

150

96

96

151

97

97

152

98

98

153

99

99

154

9a

9a

155

9b

9b

156

9c

9c

157

9d

9d

158

9e

9e

159

9f

9f

160

a0

a0

161

a1

a1

162

a2

a2

163

a3

a3

164

a4

a4

165

a5

a5

166

a6

a6

167

a7

a7

168

a8

a8

169

a9

a9

170

aa

aa

171

ab

ab

172

ac

ac

173

ad

ad

174

ae

ae

175

af

af

176

b0

b0

177

b1

b1

178

b2

b2

179

b3

b3

180

b4

b4

181

b5

b5

182

b6

b6

183

b7

b7

184

b8

b8

185

b9

b9

186

ba

ba

187

bb

bb

188

bc

bc

189

bd

bd

190

be

be

191

bf

bf

192

c0

c0

193

c1

c1

194

c2

c2

195

c3

c3

196

c4

c4

197

c5

c5

198

c6

c6

199

c7

c7

200

c8

c8

201

c9

c9

202

ca

ca

203

cb

cb

204

cc

cc

205

cd

cd

206

ce

ce

207

cf

cf

208

d0

d0

209

d1

d1

210

d2

d2

211

d3

d3

212

d4

d4

213

d5

d5

214

d6

d6

215

d7

d7

216

d8

d8

217

d9

d9

218

da

da

219

db

db

220

dc

dc

221

dd

dd

222

de

de

223

df

df

224

e0

e0

225

e1

e1

226

e2

e2

227

e3

e3

228

e4

e4

229

e5

e5

230

e6

e6

231

e7

e7

232

e8

e8

233

e9

e9

234

ea

ea

235

eb

eb

236

ec

ec

237

ed

ed

238

ee

ee

239

ef

ef

240

f0

f0

241

f1

f1

242

f2

f2

243

f3

f3

244

f4

f4

245

f5

f5

246

f6

f6

247

f7

f7

248

f8

f8

249

f9

f9

250

fa

fa

251

fb

fb

252

fc

fc

253

fd

fd

254

fe

fe

255

ff

ff


이 글을 공유하기

댓글

Email by JB FACTORY