Javaからgnuplotを使う

Javaからコマンドを与えgnuplotにチャートを描かせてJava側でそれを表示する。
コマンドとチャートデータの授受は標準入出力を使用する。
チャートデータはPNG形式を利用する。
ついでに、標準エラーから得られる-オプション付きgnuplotからのメッセージも表示する。

import java.awt.BorderLayout;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;

public class GnuplotUser implements Runnable {
    private static final String GNUPLOT = "A:\\usr\\local\\bin\\gnuplot.exe";

    public static void main(String[] args) throws IOException {
        Process p = new ProcessBuilder(GNUPLOT, "-").start();
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(p.getOutputStream())));
        BufferedInputStream in = new BufferedInputStream(p.getInputStream());
        BufferedReader err = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        StringWriter log = new StringWriter();
        out.println("set terminal png");    // output png to stdout
        out.println("plot sin(x)");         // plot
        out.println("set output");          // flush gnuplot output
        out.close();                        // flush and close stdout
        ImageIcon icon = new ImageIcon(ImageIO.read(in));   // create icon from stdin
        in.close();                                         // close stdin
        while (true) {                      // create log from stderr
            int c = err.read();
            if (c == -1) break;
            log.append((char)c);
        }
        err.close();
        try {
            p.waitFor();
        } catch (InterruptedException e) {
        }
        SwingUtilities.invokeLater(new GnuplotUser(icon, log.toString()));
    }

    private ImageIcon icon;
    private String message;

    private GnuplotUser(ImageIcon icon, String message) {
        this.icon = icon;
        this.message = message;
    }

    public void run() {
        JFrame f = new JFrame("sin(x)");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new JLabel(icon), BorderLayout.CENTER);
        f.add(new JScrollPane(new JTextArea(message, 4, 40)), BorderLayout.SOUTH);
        f.pack();
        f.setVisible(true);
    }
}