Python 標準出力→Java受け取り

先日書いた中の Python 標準出力→Java受け取りは、
Javaからプロセス起動で実行するPython と文字列の受け渡し - Oboe吹きプログラマの黙示録
リストを長い正規表現で解析する方法でこれでは、ちょっと効率が悪そうで
汚いコードである。
b' ' などとPython に出力させるのでなく、いっそのこと
Base64 エンコードさせたリストを出力させて Java で読み込んだ方が
スマートで安全だ。

Python 側、util ディレクトリに配置する stdio.py は次のようにする。

# -*- coding: UTF-8 -*-
from base64 import b64encode
class StdIO:
    # 標準入力
    # escape=True  : inputした文字をUnicode文字列に変換してリストにする
    #                標準入力=Unicode入力を想定(Javaプロセス標準出力から受信する場合はTrueにする)
    # escape=False : inputした文字を変換なしでリストにする。
    #                標準入力=通常
    def input(self, escape=True):
        inlist = []
        try:
            if escape:
                while True:
                    inp = input('')
                    if inp == '': break
                    inlist.append(inp.encode().decode('unicode-escape'))
            else:
                while True:
                    inp = input('')
                    if inp == '': break
                    inlist.append(inp)
        except EOFError:
            pass
        return inlist
    # リストを標準出力
    #   escape=True  : リスト要素をunicode-escape にエンコードして出力
    #   code : 出力する文字コード、デフォルト 'utf-8'  ユニコード指定は、'unicode-escape'
    def printList(self, list, base64=False, code='utf-8'):
        outlist = []
        if base64==True:
            for e in list:
                data = e.encode(code)
                outlist.append(b64encode(data).decode())
        else:
            for e in list:
                data = e.encode(code)
                outlist.append(data)
        print(outlist)

Java が呼び出す Python のコード
sample.py

# -*- coding: UTF-8 -*-

from util.stdio import StdIO

stdio = StdIO()
list = stdio.input()
# Java に返すリストは、Base64 エンコードする
stdio.printList(list, True)

Javaのコード

import org.yipuran.csv4j.CSVParser;
import org.yipuran.function.ThrowableConsumer;
import org.yipuran.util.process.ScriptExecutor;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

Python から受け取った文字列を以下3通りの方法で解析する。
・StringTokenizer での抽出
・org.yipuran.csv4j.CSVParser での抽出・・・1行のCSVとして解析させる方法
Google gson での抽出・・・JSONのリストとして解析させる方法

StringTokenizer または 1行CSVとして解析する方法は、誰でもすぐに思いつくが、
JSONのリストとして解析させる方法は、なかなか思いつかないであろう。

List<String> list = Arrays.asList("A", "B'B", "C\"", "'\"", "あいうえ1234");

try(ByteArrayOutputStream out = new ByteArrayOutputStream()){
   ScriptExecutor.runStream(()->"python sample.py"
   , ()->list.stream().map(e->Unicodes.encode(e) + "\n").collect(Collectors.toList())
   , ThrowableConsumer.of(i->i.transferTo(out))
   , (t, e)->{
      System.out.println("stderr : " + t );
      e.printStackTrace();
   });
   String response = out.toString();

   System.out.println(response);
   // 解析
   System.out.println("====== StringTokenizer による抽出 =========");

   List<String> list1 
   = Collections.list(new StringTokenizer(response.replaceAll("[\r\n]", ""), ","))
   .stream()
   .map(e->e.toString().replaceFirst("^(\\['| {0,1}')", "").replaceFirst("'\\]{0,1}$", ""))
   .map(e->new String(Base64.getDecoder().decode(e), StandardCharsets.UTF_8))
   .collect(Collectors.toList());

   list1.stream()
   .forEach(e->{
      System.out.println("[" + e+ "]");
   });

   System.out.println("====== org.yipuran.csv4j.CSVParser による抽出 =========");

   List<String> list2 
   = new CSVParser().tokenize(response.replaceAll("[\r\n\\[\\]]", ""))
   .stream()
   .map(e->e.replaceAll("'", ""))
   .map(e->new String(Base64.getDecoder().decode(e), StandardCharsets.UTF_8))
   .collect(Collectors.toList());

   list2.stream()
   .forEach(e->{
      System.out.println("[" + e+ "]");
   });

   System.out.println("====== Google gson による抽出 =========");

   List<String> list3 = new GsonBuilder().serializeNulls().create()
   .fromJson(response, new TypeToken<List<String>>(){}.getType());
   List<String> list4 = list3.stream()
   .map(e->new String(Base64.getDecoder().decode(e), StandardCharsets.UTF_8))
   .collect(Collectors.toList());

   list4.stream()
   .forEach(e->{
      System.out.println("[" + e+ "]");
   });
}catch(IOException ex){
   ex.printStackTrace();
}finally{
}

実行結果は、、、

['QQ==', 'QidC', 'QyI=', 'JyI=', '44GC44GE44GG44GIMTIzNA==']

====== StringTokenizer による抽出 =========
[A]
[B'B]
[C"]
['"]
[あいうえ1234]
====== org.yipuran.csv4j.CSVParser による抽出 =========
[A]
[B'B]
[C"]
['"]
[あいうえ1234]
====== Google gson による抽出 =========
[A]
[B'B]
[C"]
['"]
[あいうえ1234]