Java と Perl で FTP

FTP サーバと通信したいとき、JavaPerl だったらどっちが早いんだろう。

Perl の場合

標準モジュールの Net::FTP を使う。
Net::FTP のマニュアルで冒頭に書いてあるサンプルをほぼコピペだけど、例えばこんな感じ。

#!/usr/bin/perl

use strict;
use warnings;
use Getopt::Long;
use Net::FTP;

my $host = 'localhost';
my $user = 'anonymous';
my $pass;
my $dir;
my $file;

GetOptions('h=s' => \$host,
           'u=s' => \$user,
           'p=s' => \$pass,
           'd=s' => \$dir,
           'f=s' => \$file)
  or die "usage: $0 -h host -u user -p password -d dir -f file";

my $ftp = Net::FTP->new($host, Debug => 0)
  or die "Cannot connect to some.host.name: $@";

$ftp->login($user, $pass)
  or die "Cannot login ", $ftp->message;

$ftp->cwd($dir)
  or die "Cannot change working directory ", $ftp->message;

$ftp->get($file)
  or die "get failed ", $ftp->message;

$ftp->quit;

引数の解析には、こちらも標準モジュールの Getopt::Long を使った。
空行こみで、33 行になった。

Java の場合

標準 API でも FTP でファイルをダウンロードしたりはできるんだけど、今回は、Apache Commons Net を使った。

package lab;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.commons.net.ftp.FTPClient;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;

public class FtpGet {
	@Option(name = "-h")
	private String host = "localhost";

	@Option(name = "-u")
	private String user = "anonymous";

	@Option(name = "-p")
	private String pass;

	@Option(name = "-d")
	private String dir;

	@Option(name = "-f")
	private String file;

	public static void main(String[] args) {
		FtpGet get = new FtpGet();
		CmdLineParser p = new CmdLineParser(get);
		try {
			p.parseArgument(args);

			get.invoke();

		} catch (CmdLineException e) {
			System.err.println(e.getMessage());
			p.printSingleLineUsage(System.err);
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void invoke() throws IOException {
		FTPClient ftp = new FTPClient();
		ftp.connect(host);
		
		if (!ftp.login(user, pass)) {
			throw new RuntimeException(ftp.getReplyString());
		}
		
		if (!ftp.changeWorkingDirectory(dir)) {
			throw new RuntimeException(ftp.getReplyString());
		}

		try (OutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
			if (!ftp.retrieveFile(file, out)) {
				throw new RuntimeException(ftp.getReplyString());
			}
		}
		
		ftp.disconnect();
	}
}

引数の解析には args4j を使った。
空行こみで、66 行になった。

比べてみて

起動してから終わるまでを time コマンドで計測してみたが、どっちも同じくらいだった。
Java って VM だから起動が重いんでしょ」とか「Perl ってインタプリタだから遅いんでしょ」とか差が出るかと思ったけど、このくらいのタスクだとどっちでも変わらないようだ。
Perl の方が行数が少ないとか、今回は計ってないけどたぶんメモリ消費が少ないとかはあるかもしれない。あと、起動するときは Perl の方が簡単だった。Java だとクラスパスを通さないといけないので。
ただまぁ、今回僕がしたいことを考えると、どっちでも楽な方でいいんじゃないの、というレベルっぽい。ということで、Java で書こうっと。