手元にある各言語で、base64エンコード/デコードをしてみたメモ。
要件は以下の通り。
- 標準入力は以下の通り構成される
- 入力として与えられる「base64エンコードされた文字列」をbase64デコードしても、得られるのはASCII文字(空白文字を含む)のみからなる文字列とする
- 入力される各行の長さは不明とする(つまり上限設定なし)
- 入力の不正チェックは不要(上記仕様に従った入力が必ず与えられるとしてよい)
- 標準出力には以下を出力する
環境
手元にあるものということで、環境は以下のものに限定する。
- CentOS 7
なお、以下の言語は自前実装しなきゃならなくて辛いので割愛。
入力
od -c
した結果で示す。
0000000 a b c d e f g h i j k l m n o p 0000020 q r s t u v w x y z A B C D E F 0000040 G H I J K L M N O P Q R S T U V 0000060 W X Y Z 0 1 2 3 4 5 6 7 8 9 \n Y 0000100 W J j Z G V m Z 2 h p a m t s b 0000120 W 5 v c H F y c 3 R 1 d n d 4 e 0000140 X p B Q k N E R U Z H S E l K S 0000160 0 x N T k 9 Q U V J T V F V W V 0000200 1 h Z W j A x M j M 0 N T Y 3 O 0000220 D k = \n Y W J j Z G V m Z 2 h p 0000240 a m t s b W 5 v c H F y c 3 R 1 0000260 d n d 4 e X p B Q k N E R U Z H 0000300 S E l K S 0 x N T k 9 Q U V J T 0000320 V F V W V 1 h Z W j A x M j M 0 0000340 \r \n N T Y 3 O D k = \r \n 0000354
人間に分かりやすく示すと大体以下のような感じ。
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODk= YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0 NTY3ODk=
ただし3行目以降の各行は「CR LF」で終わっていることに注意。
出力
これもod -c
した結果で示すと以下のような感じ。
0000000 Y W J j Z G V m Z 2 h p a m t s 0000020 b W 5 v c H F y c 3 R 1 d n d 4 0000040 e X p B Q k N E R U Z H S E l K 0000060 S 0 x N T k 9 Q U V J T V F V W 0000100 V 1 h Z W j A x M j M 0 \r \n N T 0000120 Y 3 O D k = \r \n Y W J j Z G V m 0000140 Z 2 h p a m t s b W 5 v c H F y 0000160 c 3 R 1 d n d 4 e X p B Q k N E 0000200 R U Z H S E l K S 0 x N T k 9 Q 0000220 U V J T V F V W V 1 h Z W j A x 0000240 M j M 0 N T Y 3 O D k = \n a b c 0000260 d e f g h i j k l m n o p q r s 0000300 t u v w x y z A B C D E F G H I 0000320 J K L M N O P Q R S T U V W X Y 0000340 Z 0 1 2 3 4 5 6 7 8 9 \n a b c d 0000360 e f g h i j k l m n o p q r s t 0000400 u v w x y z A B C D E F G H I J 0000420 K L M N O P Q R S T U V W X Y Z 0000440 0 1 2 3 4 5 6 7 8 9 \n 0000453
人間に分かりやすく示すと大体以下のような感じ。
YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0 NTY3ODk= YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODk= abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
ただし、上の例でいうところの1~2行目の末尾は「CR LF」で終わっていることに注意。
Java
import java.io.IOException; import java.io.PrintStream; import java.util.Base64; import java.util.Scanner; public class Main { public static void main(String[] args) { // 今回はASCII文字しかない前提なので手抜きでScannerを使っている try (Scanner sc = new Scanner(System.in); PrintStream out = new PrintStream(System.out) ) { String line1 = sc.nextLine(); // MIME format(encode) Base64.Encoder mimeEncoder = Base64.getMimeEncoder(/*76, "\n".getBytes()*/); out.write(mimeEncoder.encode(line1.getBytes())); out.print("\r\n"); // MimeEncoderでは最後の行にCR LFを付加しないので、その分を補う // no wrap format(encode) Base64.Encoder encoder = Base64.getEncoder(); out.write(encoder.encode(line1.getBytes())); out.println(); // no wrap format(decode) String line21 = sc.nextLine(); Base64.Decoder decoder = Base64.getDecoder(); out.write(decoder.decode(line21)); out.println(); // MIME format(decode) Base64.Decoder mimeDecoder = Base64.getMimeDecoder(); StringBuilder sb = new StringBuilder(); while (sc.hasNextLine()) { sb.append(sc.nextLine()); sb.append("\r\n"); // わざとMIME形式を復元してみる } String line22 = sb.toString(); out.write(mimeDecoder.decode(line22)); out.println(); } catch (IOException e) { e.printStackTrace(); } } }
PHP
<?php $lines = file('php://stdin'); // MIME format(encode) $line1 = array_shift($lines); $line1 = preg_replace("/[\r\n]/", "", $line1); print chunk_split(base64_encode($line1)/*, 76, "\n"*/); // no wrap format(encode) print base64_encode($line1) . PHP_EOL; // no wrap format(decode) $line21 = array_shift($lines); $line21 = preg_replace("/[\r\n]/", "", $line21); print base64_decode($line21) . PHP_EOL; // MIME format(decode) $line22 = implode('', $lines); $line22 = preg_replace("/[\r\n]/", "", $line22); print base64_decode($line22) . PHP_EOL;
Python 2
import sys import base64 line1 = sys.stdin.readline() line1 = line1[0:len(line1) - 1] # remove LF res1 = base64.b64encode(line1) # MIME format(encode) for i in range(0, len(res1), 76): print res1[i:i + 76] + "\r" # no wrap format(encode) print res1 # no wrap format(decode) line21 = sys.stdin.readline() print base64.b64decode(line21) # MIME format(decode) line22 = '' while True: tmp = sys.stdin.readline() if tmp == '': break line22 = line22 + tmp print base64.b64decode(line22)
Python 3
import sys import base64 line1 = sys.stdin.buffer.readline() line1 = line1[0:len(line1) - 1] # remove LF res1 = base64.b64encode(line1) # MIME format(encode) for i in range(0, len(res1), 76): print(res1[i:i + 76].decode() + "\r") # no wrap format(encode) print(res1.decode()) # no wrap format(decode) line21 = sys.stdin.buffer.readline() print(base64.b64decode(line21).decode()) # MIME format(decode) line22 = b'' while True: tmp = sys.stdin.buffer.readline() if tmp == b'': break line22 = line22 + tmp print(base64.b64decode(line22).decode())
Ruby
require 'base64' line1 = STDIN.gets line1 = line1[0, line1.length() - 1] res1 = Base64.strict_encode64(line1) # MIME format(encode) i = 0 while i < res1.length() print res1[i, 76],"\r\n" i += 76 end # no wrap format(encode) print res1,"\n" # no wrap format(decode) line21 = STDIN.gets line21 = line21[0, line21.length() - 1] print Base64.strict_decode64(line21),"\n" # MIME format(decode) line22 = "" while tmp = STDIN.gets line22 = line22 + tmp end print Base64.decode64(line22),"\n"
Perl
use MIME::Base64; my $line1 = readline(STDIN); chomp($line1); # MIME format(encode) print encode_base64($line1, "\r\n"); # no wrap format(encode) print encode_base64($line1, ""),"\n"; # no wrap format(decode) my $line21 = readline(STDIN); chomp($line21); print decode_base64($line21),"\n"; # MIME format(decode) my $line22 = ""; while (my $tmp = readline(STDIN)) { $line22 = $line22 . $tmp; } print decode_base64($line22),"\n";
Go
package main import ( "bufio" "fmt" "io" "os" "encoding/base64" ) func ReadLine(reader *bufio.Reader) (bytes []byte, err error) { prefix := false buf := make([]byte, 0, 1024) line := make([]byte, 0, 1) for { line, prefix, err = reader.ReadLine() if err == io.EOF { return } buf = append(buf, line...) if prefix { continue } bytes = buf return } } func main() { stdin := bufio.NewReader(os.Stdin) line1, err := ReadLine(stdin) if err == io.EOF { panic(err) } len1 := base64.StdEncoding.EncodedLen(len(line1)) res1 := make([]byte, len1); base64.StdEncoding.Encode(res1, line1) // MIME format(encode) for i := 0; i < len(res1); i += 76 { end := i + 76 if end > len(res1) { end = len(res1) } fmt.Println(string(res1[i:end]) + "\r") } // no wrap format(encode) fmt.Println(string(res1)) // no wrap format(decode) line21, err := ReadLine(stdin) if err == io.EOF { panic(err) } // base64.StdEncoding.DecodedLenが返す値はあくまで最大値なので、 // パディングがあったりすると、それよりも短くなることがあるので、 // Decodeしたときの返り値で実際の長さを取得して切り詰めてやる必要がある。 len21 := base64.StdEncoding.DecodedLen(len(line21)) res21 := make([]byte, len21) resLen21, _ := base64.StdEncoding.Decode(res21, line21) fmt.Println(string(res21[0:resLen21])) // MIME format(decode) line22 := make([]byte, 0) for { tmp, err := ReadLine(stdin) if err == io.EOF { break } line22 = append(line22, tmp...) } len22 := base64.StdEncoding.DecodedLen(len(line22)) res22 := make([]byte, len22) resLen22, _ := base64.StdEncoding.Decode(res22, line22) fmt.Println(string(res22[0:resLen22])) }
bash
#! /bin/bash IFS= read -r line1 # MIME format(encode) # base64コマンドは"\n"を付加するので、sedで"\r\n"に変えてやる echo -n "${line1}" | base64 | sed -e 's/$/\r/' # no wrap format(encode) echo -n "${line1}" | base64 -w 0 echo # no wrap format(decode) IFS= read -r line21 echo -n "${line21}" | base64 -d echo # MIME format(decode) while IFS=$'\r' read -r tmp ; do line22="${line22}${tmp}" done echo -n "${line22}" | base64 -d echo
man base64