2012年4月16日月曜日

javaからjavacコマンドとjavaコマンドを実行

タイトルにかかれてある通りjavaからjavacコマンドとjavaコマンドを実行してみようと思います。

javaからjavacコマンドのような外部コマンドを実行するには、ProcessBuilderクラスを使用します。
今回linux環境で自分のホームフォルダ直下にHello.javaファイルが格納されており、
それをjavaからコンパイル・実行し、結果を出力してみます。
※Hello.javaは"hello"を出力する単純なソースです。


import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class CommandExec {
 public static void main(String[] args) {
  ProcessBuilder pb1 = new ProcessBuilder("javac", "Hello.java");
  pb1.directory(new File(System.getProperty("user.home")));

  try {
   Process process = pb1.start();
   int exit = process.waitFor();
   if (exit != 0) {
    System.out.println("javacコマンド失敗");
    return;
   }

   pb1.command("java", "Hello");
   process = pb1.start();
   exit = process.waitFor();
   if (exit != 0) {
    System.out.println("javaコマンド失敗");
    return;
   }

   InputStream inputStream = process.getInputStream();
   InputStreamReader inputStreamReader = new InputStreamReader(
     inputStream);
   BufferedReader bufferedReader = new BufferedReader(
     inputStreamReader);
   String line = bufferedReader.readLine();

   while (line != null) {
    System.out.println(line);
    line = bufferedReader.readLine();
   }

  } catch (IOException e) {
   e.printStackTrace();
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }
}

2012年4月8日日曜日

Java7 globbing patternでファイル一覧取得

久々の更新です。Java7で新規追加されたjava.nio.file.Filesパッケージ
内のクラスを使ってプログタイトルに書かれてあるとおりglobbing patternで指定したディレクトリのファイル一覧を取得してみます。
※globbing pattern・・・・・正規表現のような表現

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class FileGlobbingSample {
 public static void main(String[] args) {
  Path path = Paths.get(System.getProperty("user.home"));
  
  try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path, "*.java")) {
   for (Path p : directoryStream) {
    System.out.println(p.getFileName());
   }
  } catch (IOException ie) {
   ie.printStackTrace();
  }
 }
}

FilesクラスのnewDirectoryStreamメソッドの第二引数にglobbing patternを記述します。
以下の記述で拡張子が「java」のファイルを取得するように指定しています。
Files.newDirectoryStream(path, "*.java")

2012年2月5日日曜日

オーバーロード・オーバライドされたメソッドを呼び出すルール

javaにはオーバーロードとオーバロードという仕組みがあります。
オーバーロードはメソッド名が同じで引数が違うメソッドです。
それに対してオーバライドは親クラスのメソッド名が同じで引数が同じメソッドのことを言います(ものすごく簡単にいうと)。

どのメソッドを呼び出すかどうか自分自身混乱しそうなので、
どのような呼び出しルールなのか確認用のサンプルを作成しました。

public class Test {
 public static void main(String[] args) {
  Animal[] animal = { new Animal(), new Dog(), new Cat()};
  for (Animal a : animal) {
   new Test().method(a);
  }
  for (Animal a : animal) {
   a.method();
  }
 }
 void method(Animal animal) {
  System.out.println(&quot;overload:animal&quot;);
 }
 void method(Cat cat) {
  System.out.println(&quot;overload:cat&quot;);
 }
 void method(Dog dog) {
  System.out.println(&quot;overload:dog&quot;);
 }
}

class Animal {
 public void method() {
  System.out.println(&quot;override:animal&quot;);
 }
}
class Dog extends Animal {
 @Override
 public void method() {
  System.out.println(&quot;override:dog&quot;);
 }

}
class Cat extends Animal {
 @Override
 public void method() {
  System.out.println(&quot;override:cat&quot;);
 }
}

■実行結果
$ java Test
overload:animal
overload:animal
overload:animal
override:animal
override:dog
override:cat

実行結果から呼び出しルールについて以下のことが確認できます。
オーバロード:変数の型を元に呼び出すメソッドを決定
Animal animal = new Dog()のように実体がDogでも呼び出されるのは引数がAnimalのmethodになります。

オーバライド:変数の実体を元に呼び出すメソッドを決定
Animal animal = new Dog()であれば実体がDogなので呼び出されるのはDogのメソッドになります。

2012年1月29日日曜日

クラスの格納場所を取得する

クラスの格納場所を取得するサンプルを作成しました。

 気をつけるのはgetResourceメソッドに渡す引数の値で、
 クラス名のあとにclass拡張子をつけることと、
 パッケージ名の区切りは「/」にすることの2点です。

public class Test {
 public static void main(String[] args) {
  Class c = new Test2().getClass();
  ClassLoader cl = c.getClassLoader();
  System.out.println(cl.getResource("Test2.class"));
  System.out.println(cl.getResource("java/lang/String.class"));
 }
}

■実行結果
file:/Users/masaaki/java/Test2.class jar:file:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/rt.jar!/java/lang/String.class

2012年1月9日月曜日

scala パターンマッチサンプル

scalaにはパターンマッチというものがあり、javaのswitch文のようなもので
switch文よりも柔軟性があります。ちょっとしたサンプルを作成してみました。
年齢を判定するサンプルです。


object MatchSample { def main(args:Array[String]) :Unit = { val p1 = Profile("田中", 22) val p2 = Profile("佐藤", 33) val p3 = Profile("伊藤", 44) val p4 = Profile("木村", 55) val p5 = Profile("斉藤", 66) val p6 = Profile("岡村", 11) val p7 = Profile("大塚", 77) // val p8 = Profile("江藤", -1) val pList = List(p1, p2, p3, p4, p5, p6, p7) for (profile <- pList) { println(ageJudge(profile)) } } def ageJudge(p:Profile) = p match { case Profile(name:String, age:Int) if age >= 0 && age < 20 => p.name + ":20歳代以下" case Profile(name:String, age:Int) if age >= 20 && age < 30 => p.name + ":20歳代" case Profile(name:String, age:Int) if age >= 30 && age < 40 => p.name + ":30歳代" case Profile(name:String, age:Int) if age >= 40 && age < 50 => p.name + ":40歳代" case Profile(name:String, age:Int) if age >= 50 && age < 60 => p.name + ":50歳代" case Profile(name:String, age:Int) if age >= 60 && age < 70 => p.name + ":60歳代" case Profile(name:String, age:Int) if age >= 70 => p.name + ":70歳以上" case Profile(name:String, age:Int) if age < 0 => throw new IllegalArgumentException("年齢が不正:" + p.age) } } case class Profile(name:String, age:Int)

■実行結果
$ scala MatchSample
田中:20歳代
佐藤:30歳代
伊藤:40歳代
木村:50歳代
斉藤:60歳代
岡村:20歳代以下
大塚:70歳以上

2011年12月11日日曜日

ディレクトリコピーするツールをSwingで作ってみた

最近Swingの勉強をし始めたので、ディレクトリを別のディレクトリにコピー
するツールをSwingで作ってみました。
コピー中に進捗が分かるように、進捗バー(JProgressBar)をつけてみました。
また、ディレクトリをコピーする処理は別スレッドで処理するようにしました。

デザインは少しいけてませんが、それはまたということで。

・初期画面

・コピーボタン押下後

・コピー完了後






import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.Timer;


/**
 * ディレクトリをコピー
 * 処理中は進捗バーを表示
 */
public class DirCopy extends JFrame implements ActionListener {

 JProgressBar progress = new JProgressBar();

 JButton buttonFromCopy = null;
 JButton buttonToCopy = null;
 JButton buttonCopy = null;
 
 int fileSize = 0;
 float currentFileSizePercent = 0;
 
 File fileFrom = null;
 File fileTo = null;
 
 boolean flg1 = false;
 boolean flg2 = false;
 
 Timer time = null;

 
 public static void main(String[] args) {
  DirCopy frame = new DirCopy();
  frame.setBounds(20, 20, 300, 200);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true);
 }
 
 DirCopy() {
  JLabel label = new JLabel("進捗バー");
  label.setAlignmentX(0.5f);
  
  progress.setPreferredSize(new Dimension(10, 100));
  progress.setStringPainted(true);

  buttonFromCopy = new JButton("コピー元");
  buttonFromCopy.addActionListener(this);
  buttonFromCopy.setActionCommand("FromCopy");
  buttonFromCopy.setAlignmentY(0.5f);

  buttonToCopy = new JButton("コピー先");
  buttonToCopy.setActionCommand("ToCopy");
  buttonToCopy.addActionListener(this);
  buttonToCopy.setAlignmentY(0.5f);
  
  buttonCopy = new JButton("コピー");
  buttonCopy.setEnabled(false);
  buttonCopy.setActionCommand("copy");
  buttonCopy.addActionListener(this);

  JButton buttonClose = new JButton("close");
  buttonClose.setAlignmentX(0.5f);
  buttonClose.setActionCommand("close");
  buttonClose.addActionListener(this);

  JPanel panel1 = new JPanel();
  JPanel panel2 = new JPanel();
  JPanel panel3 = new JPanel();
  panel1.setLayout(new BoxLayout(panel1, BoxLayout.Y_AXIS));
  panel2.setLayout(new BoxLayout(panel2, BoxLayout.LINE_AXIS));
  panel3.setLayout(new BoxLayout(panel3, BoxLayout.Y_AXIS));
  panel1.add(label);
  panel1.add(progress);
  panel2.add(buttonFromCopy);
  panel2.add(buttonToCopy);
  panel2.add(buttonCopy);
  panel3.add(buttonClose);

  getContentPane().add(panel1, BorderLayout.PAGE_START);
  getContentPane().add(panel2, BorderLayout.CENTER);
  getContentPane().add(panel3, BorderLayout.PAGE_END);

 }
 
 @Override
 public void actionPerformed(ActionEvent e) {

  if (e.getActionCommand().equals("time")) {
   if (currentFileSizePercent < 100) {
    progress.setValue((int)currentFileSizePercent);
    progress.setString("処理中です");
   } else {
    progress.setValue((int)currentFileSizePercent);
    progress.setString("完了");
    time.stop();
   }
  }
  
  // 閉じるボタン押下
  if (e.getActionCommand().equals("close")) {
   System.exit(0);
  }
  
  // コピー元ボタン押下
  if (e.getActionCommand().equals("FromCopy")) {
   JFileChooser fChooser = new JFileChooser();
   //ディレクトリのみ選択可能
   fChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
   int select = fChooser.showOpenDialog(this);
   if(select == JFileChooser.APPROVE_OPTION) {
    fileFrom = fChooser.getSelectedFile();
    fileSize = (int) getFileSize(fileFrom);
    flg1 = true;
    // コピーボタンを活性化
    if (flg2) buttonCopy.setEnabled(true);
   }
  }
  
  // コピー先ボタン押下
  if (e.getActionCommand().equals("ToCopy")) {
   JFileChooser fChooser = new JFileChooser();
   // ディレクトリのみ選択可能
   fChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
   int select = fChooser.showOpenDialog(this);
   if (select == JFileChooser.APPROVE_OPTION) {
    fileTo = fChooser.getSelectedFile();
    flg2 = true;
    // コピーボタンを活性化
    if (flg1) buttonCopy.setEnabled(true); 
   }
  }
  
  // コピーボタン押下
  if(e.getActionCommand().equals("copy")) {
   File dir = new File(fileTo.getPath() + "/" + fileFrom.getName());
   if(dir.isDirectory() && dir.exists()) {
    dirDelete(dir);
   }
   time = new Timer(1000, this);
   time.setActionCommand("time");
   time.start();
   FileCopy fileCopy = new FileCopy();
   // 別スレッドでファイルコピー
   fileCopy.execute();
  }
 }
 
 
 /**
  * ディレクトリ以下のファイルサイズを取得
  * @param dir ディレクトリ
  * @return ファイルサイズ
  */
 private long getFileSize(File dir) {
  long size = 0;
  File[] fileList = dir.listFiles();
  if(fileList != null) {
   for(File file : fileList) {
    if(file.isFile()) {
     size += file.length();
    } else {
     size += getFileSize(file);
    }
   }
  }
  
  return size;
 }
 
 /**
  * @param dirFrom コピー元のディレクトリ
  * @param dirTo コピー先のディレクトリ
  */
 private void fileCopy(File dirFrom, File dirTo) {  
  File[] fromFile = dirFrom.listFiles();
  dirTo = new File(dirTo.getPath() + "/" + dirFrom.getName());
  dirTo.mkdir();

  if(fromFile != null) {
   for(File f : fromFile) {
    // ファイルの場合
    if (f.isFile()) {
     copy(f, dirTo);
    // ディレクトリの場合
    } else {
     fileCopy(f, dirTo);
    }
   }
  }
 }
 
 /**
  * ファイルをディレクトリにコピーする
  * @param file コピーするファイル
  * @param dir コピーするファイルの格納フォルダ
  */
 private void copy(File file, File dir) {
  File copyFile = new File(dir.getPath() + "/" + file.getName());
  FileChannel channelFrom = null;
  FileChannel channelTo = null;
  
  try {
   copyFile.createNewFile();
   channelFrom = new FileInputStream(file).getChannel();
   channelTo = new FileOutputStream(copyFile).getChannel();
   //ファイルをコピー
   channelFrom.transferTo(0, channelFrom.size(), channelTo);
   float currentFileSize = getFileSize(new File(fileTo.getPath() + "/" + fileFrom.getName()));
   //処理の進捗率をファイルサイズから求める
   currentFileSizePercent = (float) (currentFileSize / fileSize) * 100;
  } catch (IOException e) {
   e.printStackTrace();
  } finally {
   try {
    if (channelFrom != null) { channelFrom.close(); }
    if (channelTo != null) { channelTo.close(); }
    } catch (IOException e) { e.printStackTrace(); }
  }
 }
 
 /**
  * 指定したディレクトリを削除
  * @param file 削除ディレクトリ
  */
 private void dirDelete(File dir) {
  for (File f : dir.listFiles()) {
   if (f.isFile()) {
    f.delete();
   } else {
    dirDelete(f);
    f.delete();
   } 
  }
  dir.delete();
 }
 /**
  * ディレクトリをコピー
  */
 class FileCopy extends SwingWorker<Object, Object> {
  @Override
  public Object doInBackground() {
   fileCopy(fileFrom, fileTo);
   return null;
  }
 }
}

2011年12月7日水曜日

scalaでXMLを操作するサンプル

アテンドのAPIを使ってXML形式で情報を取得し
必要な情報を抽出する処理をscalaで書いてみました。
関数名が「/」の関数があるけど、分かりづらい。。。


import scala.xml._

// XMLを取得
val xml:Elem = XML.load("http://api.atnd.org/events/?keyword=scala")

// ルートノード以下のすべてのノードを取得
for (node:Node <- xml.descendant) {
 // タイトルにscalaが含まれている
 if(node.\("title").text.contains("scala")) {
  println("タイトル:" + node.\("title").text)
  println("場所:" + node.\("place").text)
  println("時間:" + getDate(node.\("started_at").text) +" to " 
  + getDate(node.\("ended_at").text))
  println("URL:" + node.\("event_url").text + "\n")
 }
}

// 日付形式を変換
def getDate(date:String):String = {
 date.replace("-", "/").replace("T", " ").substring(0, 19)
}