花粉症と風邪のダブルパンチな今日このごろ、ダブルパンチは、ポテトチップスのコンソメ味だけにしてもらいたいですね、どうもボクです。
職場の方に、Base64やHEXという概念について教えていただいたので、忘れないうちにメモメモ。
それでは、レッツトライ~。
Base64って?
まずは、Base64から。みんな大好き、Wikipedia先生は、
Base64は、データを64種類の印字可能な英数字のみを用いて、それ以外の文字を扱うことの出来ない通信環境にてマルチバイト文字やバイナリデータを扱うためのエンコード方式である。MIMEによって規定されていて、7ビットのデータしか扱うことの出来ない電子メールにて広く利用されている。
具体的には、A
–Z
, a
–z
, 0
–9
までの62文字と、記号2つ (+
, /
)、さらにパディング(余った部分を詰める)のための記号として =
が用いられる。この変換によって、データ量は4/3(約133%)になる。また、MIMEの基準では76文字ごとに改行コードが入るため、この分の2バイトを計算に入れるとデータ量は約137%となる。
と、仰ていますかね。
Base64でエンコードすると、4/3 倍にデータ量が増えるって話みたいですね。つまり、仮に、800 byteのデータをBase64でエンコードした場合、800 × 1.33 = 1064 byteになると。800 byteのデータをBase64でデコードした場合は、800 / 1.33 = 601.503759398 byte になるんだと。
主な使い道の代表例としては、
なんかが挙げられていますかね。
⇧ 上記サイト様によりますと、サイトを 表示するときに、http通信をする際に、画像データをBase64エンコードしてテキストデータとすることで、画像読み込みのhttp通信をなくすことができるので表示速度が速くなるそうな。
ただし、Base64エンコードは、データ量が 4/3 倍になるので、大きいサイズの画像には不向きのようです。
そして、みんな大好きJSONで画像データ(バイナリデータ)なんかを送りたいんじゃぁという時も、
⇧ 上記サイト様によりますと、Base64でエンコードでいけるそうです。逆に言うと、JSONでバイナリ形式のデータを送るには、Base64のエンコードを使っていく必要があるということですかね。
⇧ Base64以外にも選択肢はあるようですが、やはりBase64がオススメだそうです。
HEXって?
16進数のことらしいです。読み方としては、
⇧ 「ヘクス」が人気らしいですが、「ヘキサ」が一般的らしいです。
Wikiepediaさんによりますと、
ということらしいです。
⇧ 上記サイト様によりますと、256進数とかも存在するそうな...気が遠くなりそう...
当然、HEXエンコードや、HEXデコードってことも行う機会が訪れるであろうと。
⇧ 上記サイト様を参考にさせていただくと、HEXエンコードするということは、16進数文字列表記にすることで、HEXデコードするとうことは、16進数表記にしたものを元の表記に戻してあげることであると。
それを踏まえて、WikipediaさんのBase64の部分を見てみると、
元データ
- 文字列: "ABCDEFG"
- 16進表現: 41, 42, 43, 44, 45, 46, 47
- 2進表現: 0100 0001, 0100 0010, 0100 0011, 0100 0100, 0100 0101, 0100 0110, 0100 0111
「A」は、16進数で「41」と表記されることから、単純に考えるならば、HEXエンコードで、1byteから2byteになってるということで2倍されてるということですかね。逆に、16進数の「41」をHEXデコードすれば、「A」になり、1/2倍になるということかと。
ちなみに、
⇧ 「文字列(ASCIIコード)」と「16進数(16進コード)」の関係は、上記サイト様を参照してますが、16進コードって何ぞ?な疑問が出てきてしまったと...
というわけで、16進数表記と2進数表記の違いを見てみる
じゃあ、実際に、どうなるか試してみます。
⇧ 上記サイト様を参考にさせていただきました。
Eclipseを起動し、適当なクラスを作成し、
で、ソースコードはこんな感じ。
public class HexTest { public static void main(String[] args) { // 16進数文字は、0-9,a-f,A-Fで構成されている String hexStr = "0a"; // 16進数表記文字列 System.out.print("16進数文字列表記のバイト数 "); System.out.println(hexStr.getBytes().length + "byte"); for (byte b: hexStr.getBytes()) { System.out.print(b + " "); } System.out.println(); int bin = Integer.parseInt(hexStr, 16); String binStr = Integer.toBinaryString(bin); // 2進数表記文字列 System.out.print(" 2進数文字列表記のバイト数 "); System.out.println(binStr.getBytes().length + "byte"); for (byte b: binStr.getBytes()) { System.out.print(b + " "); } } }
で、実行してみると、
16進数表記は、2進数表記に比べてbyte数が半分になってますね。
文字列の進数表記とbyte数の関係性がいまいちピンとこない、そんなモヤモヤを抱えたまま、今回はこのへんで。
2019年2月28日(木)追記:↓ ここから
なんか、16進数表記文字列は、
⇧ 元のStringの長さを半分にしてから、byte[] に変換しないと、正しいバイト数が得られないらしい...。
2019年2月28日(木)追記:↑ ここからまで