Base64やHEXなどについて。呪文とかそういうんじゃないですよ

花粉症と風邪のダブルパンチな今日このごろ、ダブルパンチは、ポテトチップスのコンソメ味だけにしてもらいたいですね、どうもボクです。

職場の方に、Base64やHEXという概念について教えていただいたので、忘れないうちにメモメモ。

それでは、レッツトライ~。 

 

Base64って?

まずは、Base64から。みんな大好き、Wikipedia先生は、

Base64は、データを64種類の印字可能な英数字のみを用いて、それ以外の文字を扱うことの出来ない通信環境にてマルチバイト文字バイナリデータを扱うためのエンコード方式である。MIMEによって規定されていて、7ビットのデータしか扱うことの出来ない電子メールにて広く利用されている。

具体的には、AZaz09 までの62文字と、記号2つ (+/)、さらにパディング(余った部分を詰める)のための記号として = が用いられる。この変換によって、データ量は4/3(約133%)になるまた、MIMEの基準では76文字ごとに改行コードが入るため、この分の2バイトを計算に入れるとデータ量は約137%となる

Base64 - Wikipedia

と、仰ていますかね。

Base64エンコードすると、4/3 倍にデータ量が増えるって話みたいですね。つまり、仮に、800 byteのデータをBase64エンコードした場合、800 × 1.33 = 1064 byteになると。800 byteのデータをBase64でデコードした場合は、800 / 1.33 = 601.503759398 byte になるんだと。

主な使い道の代表例としては、

電子メールでは、SMTPなどの制約により、7ビット文字列以外をやり取りすることは出来ない。そのため、添付ファイルなどのバイナリ形式のデータを送信する際に標準的に利用されている。

Base64 - Wikipedia

なんかが挙げられていますかね。

 

yokonoji.work

⇧  上記サイト様によりますと、サイトを 表示するときに、http通信をする際に、画像データをBase64エンコードしてテキストデータとすることで、画像読み込みのhttp通信をなくすことができるので表示速度が速くなるそうな。

ただし、Base64エンコードは、データ量が 4/3 倍になるので、大きいサイズの画像には不向きのようです。

そして、みんな大好きJSONで画像データ(バイナリデータ)なんかを送りたいんじゃぁという時も、

qiita.com

⇧  上記サイト様によりますと、Base64エンコードでいけるそうです。逆に言うと、JSONでバイナリ形式のデータを送るには、Base64エンコードを使っていく必要があるということですかね。

qiita.com

⇧  Base64以外にも選択肢はあるようですが、やはりBase64がオススメだそうです。

 

HEXって?

16進数のことらしいです。読み方としては、 

yomikata.org

⇧  「ヘクス」が人気らしいですが、「ヘキサ」が一般的らしいです。

Wikiepediaさんによりますと、

十六進法(じゅうろくしんほう、 hexadecimal)とは、16を底(てい)とし、底およびそのを基準にして数を表す方法である。

十六進法 - Wikipedia

ということらしいです。

 

qiita.com

⇧  上記サイト様によりますと、256進数とかも存在するそうな...気が遠くなりそう...

 

当然、HEXエンコードや、HEXデコードってことも行う機会が訪れるであろうと。

kiririmode.hatenablog.jp

 ⇧  上記サイト様を参考にさせていただくと、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

Base64 - Wikipedia

「A」は、16進数で「41」と表記されることから、単純に考えるならば、HEXエンコードで、1byteから2byteになってるということで2倍されてるということですかね。逆に、16進数の「41」をHEXデコードすれば、「A」になり、1/2倍になるということかと。

ちなみに、

www.mrl.co.jp

⇧ 「文字列(ASCIIコード)」と「16進数(16進コード)」の関係は、上記サイト様を参照してますが、16進コードって何ぞ?な疑問が出てきてしまったと...

 

というわけで、16進数表記と2進数表記の違いを見てみる

じゃあ、実際に、どうなるか試してみます。

qiita.com

qiita.com

okwave.jp

⇧  上記サイト様を参考にさせていただきました。

 

Eclipseを起動し、適当なクラスを作成し、

f:id:ts0818:20190227221621p:plain

で、ソースコードはこんな感じ。

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 + " ");
		}
	}
}

で、実行してみると、

f:id:ts0818:20190227221932p:plain

f:id:ts0818:20190227222004p:plain

16進数表記は、2進数表記に比べてbyte数が半分になってますね。

文字列の進数表記とbyte数の関係性がいまいちピンとこない、そんなモヤモヤを抱えたまま、今回はこのへんで。

2019年2月28日(木)追記:↓  ここから

なんか、16進数表記文字列は、

www.tutorialspoint.com

⇧  元のStringの長さを半分にしてから、byte[] に変換しないと、正しいバイト数が得られないらしい...。

2019年2月28日(木)追記:↑  ここからまで