Java

2008/03/28

ファイル入出力(Java)

Javaでのファイル入出力についてメモ

1.ファイルを読み込む

// ファイルを読み込むためのクラス
import java.io.FileReader;
// バッファリングと行番号取得で使用
import java.io.LineNumberReader;
// 入出力が失敗したときに生成される例外クラス
import java.io.IOException;

public class FileReadOnly
{
    public static void main(String[ ] args)
    {
       FileReader in = null;
       LineNumberReader lnr = null;

       try{
          //---ファイルを読み込む
          in = new FileReader("./test.txt");
          //---バッファリングのために利用
          lnr = new LineNumberReader(in);
          String line;

          //---1行ずつ表示
          while((line = lnr.readLine()) != null){
             System.out.println(line);
          }
       }catch(IOException e){
          e.printStackTrace();
       }finally{
          try{
             //---ファイルを閉じる
             lnr.close();
          }catch(Exception e){
          }
      }
    }
}

2.ファイルをコピーする

import java.io.FileReader;
import java.io.LineNumberReader;
import java.io.IOException;
// 出力に必要なクラス
import java.io.FileWriter;
import java.io.BufferedWriter;

public class ReadandWrite
{
    public static void main(String[] args)
    {
       FileReader in = null;
       LineNumberReader lnr = null;
       FileWriter out = null;
       BufferedWriter bw = null;

       try{
           in = new FileReader("./test.txt");
           lnr = new LineNumberReader(in);

           out = new FileWriter("./copy.txt");
           bw = new BufferedWriter(out);

           String line;
           while((line = lnr.readLine()) != null){
              //---1行ごとに書き込み
              bw.write(line);
              //---改行コードを挿入(互換性を考慮)
              bw.newLine();
           }
           //---ファイルに書き込む
           bw.flush();
        }catch(IOException e){
           e.printStackTrace();
        }finally{
           try{
               lnr.close();
           }catch(Exception e){
           }
           try{
               bw.close();
           }catch(Exception e){
           }
        }
    }
}

ファイルを閉じる操作は必ずfinally節で行うべきらしい。finally節の処理はtry節の処理を実行しているときにエラーが発生しても必ず実行されるからだそうだ。

| | コメント (0) | トラックバック (0)

2008/03/11

拡張for文

Javaには「拡張for文」というものがあったので、メモ。

class ForIn{
  public static void main(String[ ] args){
   double[ ] array = {1.0, 2.0, 3.0, 4.0, 5.0};
   double sum = 0;
   for(double i : array)
    sum += i;
  }
}

このfor文は配列の走査(配列要素を順に1つずつなぞっていくこと)を簡潔に記述することができます。このfor文で、”double i”となっていて?となるかもしれませんが、この”i”はインデックスを表すものではなく、「現在着目している要素」を表しているのでdouble型になっているのです。

もちろん多次元配列にも適用することができ、例えば2次元配列double array[ ][ ]があるとすると、

for(double[ ] i : array){
  for(double j : i){
  }
}

このように記述します。

| | コメント (0) | トラックバック (1)

2008/03/09

Javaの基礎を整理するか

Javaの基礎を整理してみようかと。

| | コメント (0) | トラックバック (0)

2008/03/04

乱数を発生させる[Java]

Javaで乱数を生成するにはRandomクラスを用います。(Mathクラスにも乱数を生成するライブラリがある)

例えば0~99の整数値を(10個)生成するプログラムは次のようにします。

import java.util.Random;

class RandMake
{
  public static void main(String[ ] args)
  {
   Random rand = new Random();
   int num;

   for(int i=0 ; i<10 ; i++){
     num = rand.nextInt(100);
     System.out.println(num);
   }
  }
}

このプログラムでは乱数の種を与えていませんが、種を与える場合はインスタンス作成時にRandom rand = new Random(seed);とします。また、nextInt(n)メソッドは0~n-1の範囲の乱数が生成されますが、他には

  • nextBoolean()  boolean型  trueまたはfalse
  • nextInt()         int型         -2147483648~+2147483647
  • nextLong()      long型       -9223372036854775808~+9223372036854775807
  • nextDouble()    double型    0.0以上1.0未満
  • nextFloat()      float型       0.0以上1.0未満

以上のメソッドがRandomクラスに用意されています。

| | コメント (0) | トラックバック (0)

2008/03/03

Javaでキーボードから入力する方法

Javaのコンソールプログラムでキーボードから入力(ここでは整数値)を入力するときって、

import java.util.Scanner;

class Input{
public static void main(String[ ] args){
  Scanner stdIn = new Scanner(System.in);
  System.out.print("Input:");
  int num = stdIn.nextInt();

とする方法と、

import java.io.*;

class Input{
public static void main(String[ ] args){
  System.out.print("Input:");
  BufferedReader br =
   new BufferedReader(
    new InputStreamReader(System.in));
  String str = br.readLine();
  int num = Integer.parseInt(str);

とする方法が(私が知る限りは)あると思いますが、この2つの方法のどちらのほうがスタンダードなんでしょうか?というか、どんな違いがあるのでしょうか?私はScannerクラスを用いる方が短くて楽ですが。

| | コメント (0) | トラックバック (0)

2008/02/29

時間割作成プログラムをGUI化する。

かな~り前に作った「時間割作成プログラム」をJava SwingでGUIプログラム化したいと思います。

  • 起動すると空の時間割りが表示される
  • マウスで目的の時間をクリックして授業名を入力
  • 作成した時間割は.iniファイルとして保存し、次に起動したとき読み込む

こんな感じで。

とりあえず、JTable使って作ってみたのがこれです。(まだ見かけだけで何の機能の無い)

Schedule_maker

JTableはデフォルトで編集可能になっているので、2つ目はクリアかな。(それっぽくするのに少し手を加えなくてはならないですが)

| | コメント (0) | トラックバック (0)

2008/02/25

忘れちゃいけないキャスト

私がよくつまづくキャストについて。

例えば15!を計算するときに次のように記述したとします。

double ans = 0;
ans = 15*14*13*.......*2*1;

階乗計算としては全く問題がないように見えますが、これには大きな間違いがあります。実際にコンパイルして実行すると15!の答えである1307674368000は出力されません。(JavaでもCでも2.00.....E09、つまり2.00....×10の9乗と出力されるはず)

なぜなら、右辺に書かれた数値リテラルをint型として捉え左から順に計算しているためにint型の最大値を超過、すなわちオーバーフローを起こしています。さらに、JavaやCではオーバーフローを起こしてもエラーや例外が発生しません。(コンパイラオプションに-Wallなどを加えておけば警告をだしてくれます)

これを防ぐには次のようにしっかりキャストしておく必要があります。

double ans = 0;
ans = (double)15*14*13*.......*2*1;

(Javaでは(double)15ではなく15dとすることもできます。)

もちろん、

double ans2 = 1;
for(i=15 ; i>=1 ; i--)
ans2 *= i;

とすれば正しく階乗計算をすることができます。

| | コメント (0) | トラックバック (0)

2008/02/11

public static void main(String[ ] args)

Javaのmainメソッド public static void main(String[ ] args) についてのメモです。

C言語のmain関数に相当するものです。ちなみに、修飾子「public」と「static」はどちらが先に来ても問題ありませんが、public staticと書くのが一般的です。

mainメソッドは引数を一つだけとり、それはString型の要素の配列です。(String[ ] argsのこと)この引数はコマンドライン引数と呼ばれます。この引数の名前は何でもいいのですが、"args"とか"argv"と書かれることが多いようです。(このargsやargvのargはArgument=引数だと思いますが、"s"とか"v"って何?)

コマンドライン引数は配列ですが、Javaでの配列の宣言はC言語と少し違います。C言語では

int array[10];

と宣言しますが、Javaでは

int[ ] array;
array = new int[10];

と宣言します。C言語のように int array[ ]; と宣言することもできますが、推奨されていません。(高橋麻奈 著 「やさしいJava」では非推奨の宣言をしている)

| | コメント (0) | トラックバック (0)

2008/01/24

自作GUIを操作

無理やりSwing!」から始まったSwingプログラミングが所期の目的を果たすことができました。(火曜日にはGUIフロントエンドが完成していましたが、肝心の数値計算プログラムの完成が遅れていました。理由:昨日のアレ

このプログラムが完成したことにより、

プログラムを実行して、パラメータを入力。
計算が終わったらファイルAをBにコピーしてから再びプログラムを実行してパラメータを入力。
また計算が終わったらファイルAを・・・

という億劫な作業を直感的に操作できるようになりました。おまけに、自分で作ったGUIプログラムを使うことで数値計算も楽しさが倍増です。

Md_calculator_client

このプログラムは思いつきで急造したので、「パラメータを入力して実行」、「特定のファイルをコピー」、「入力欄をクリア」と最小限の機能しか実装していません。使用したコンポーネントも以前に挙げたもののみです。

簡単に言うと、このプログラムはexec()で呼び出す外部プログラムをボタンで選択しているだけですが、この方法は「ボタン」と「外部プログラム呼び出しメソッド」を増やすだけで機能を増加できるので、今後は出力されたデータをGnuplotでグラフ化したり、グラフを画像データ化する機能を追加したいと思っています。(Javaを理解しているとは言えないので、Javaをもっと理解し、コードが安全か危険かを判断できるようにしたいとも思う)

/*========================
  GUI FrontEnd For MDcalc
  Input Form
  Using Java Swing
  ========================*/

import javax.swing.*;
import java.io.*;
import java.awt.event.*;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.BorderLayout;

//---Run MDcalc---
class MDcalculator
{
    //---Calc---
    public String calc(int nstep, int istart,
		     int ivs, int nvs, int temp)
    {
	String result;
	try{
	    Runtime rt = Runtime.getRuntime();
	    Process p  = rt.exec("./MDcalc "+nstep+" "+istart+
				 " "+ivs+" "+nvs+" "+temp);
	    InputStream is = p.getInputStream();
	    InputStreamReader isr = new InputStreamReader(is);
	    BufferedReader br = new BufferedReader(isr);
	    result = br.readLine();
	}catch(IOException ex){
	    ex.printStackTrace();
	    result = "error";
	}
	return result;
    }

    //---Copy---
    public void copy()
    {
	String re2;
	try{
	    Runtime rt2 = Runtime.getRuntime();
	    Process p2  = rt2.exec("cp restart.out restart.in");
	}catch(IOException ex){
	    ex.printStackTrace();
	}
    }
}

//---Main Class---
public class InputForm extends JFrame implements ActionListener
{
    //---InputForm Parts---
    JTextField form1;
    JComboBox  form2;
    JComboBox  form3;
    JTextField form4;
    JTextField form5;
    JLabel     caution;

    public static void main(String[] args)
    {
	InputForm frame = new InputForm();
	frame.setTitle("MD Calculator Client");
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.setSize(350, 400);
	frame.setLocationRelativeTo(null);
	frame.setVisible(true);
    }

    InputForm()
    {
	//---Base---
	JPanel base = new JPanel();

	//---Input nstep---
	JPanel panel1 = new JPanel();
	panel1.setPreferredSize(new Dimension(350, 50));
	panel1.setLayout(new FlowLayout());
	form1 = new JTextField(10);
	form1.setHorizontalAlignment(JLabel.RIGHT);
	panel1.add(new JLabel("NSTEP:"));
	panel1.add(form1);

	//---Input istart---
	JPanel panel2 = new JPanel();
	panel2.setPreferredSize(new Dimension(350, 50));
	panel2.setLayout(new FlowLayout());
	String[] f2_ini = {"ON", "OFF"};
	form2 = new JComboBox(f2_ini);
	panel2.add(new JLabel("Read restart.in:"));
	panel2.add(form2);

	//---Input ivs---
	JPanel panel3 = new JPanel();
	panel3.setPreferredSize(new Dimension(350, 50));
	panel3.setLayout(new FlowLayout());
	String[] f3_ini = {"ON", "OFF"};
	form3 = new JComboBox(f3_ini);
	panel3.add(new JLabel("Velocity Scale:"));
	panel3.add(form3);

	//---Input nvs---
	JPanel panel4 = new JPanel();
	panel4.setPreferredSize(new Dimension(350, 50));
	panel4.setLayout(new FlowLayout());
	form4 = new JTextField(10);
	form4.setHorizontalAlignment(JLabel.RIGHT);
	panel4.add(new JLabel("Scale:"));
	panel4.add(form4);
	panel4.add(new JLabel("every times"));

	//---Input temp---
	JPanel panel5 = new JPanel();
	panel5.setPreferredSize(new Dimension(350, 50));
	panel5.setLayout(new FlowLayout());
	form5 = new JTextField(10);
	form5.setHorizontalAlignment(JLabel.RIGHT);
	panel5.add(new JLabel("TARGET TEMP[K]:"));
	panel5.add(form5);

	//---Run Button---
	JPanel panel6 = new JPanel();
	panel6.setPreferredSize(new Dimension(350, 50));
	panel6.setLayout(new FlowLayout(FlowLayout.RIGHT));
	JButton run_btn = new JButton("Run");
	run_btn.addActionListener(this);
	run_btn.setActionCommand("run");
	JButton reset_btn = new JButton("Reset");
	reset_btn.addActionListener(this);
	reset_btn.setActionCommand("reset");
	JButton copy_btn = new JButton("Copy");
	copy_btn.addActionListener(this);
	copy_btn.setActionCommand("copy");
	caution = new JLabel("");
	panel6.add(caution);
	panel6.add(run_btn);
	panel6.add(copy_btn);
	panel6.add(reset_btn);

	//---Put Form Panel on Base---
	base.add(panel1);
	base.add(panel2);
	base.add(panel3);
	base.add(panel4);
	base.add(panel5);

	//---Set Panels on Frame---
	getContentPane().add(base, BorderLayout.CENTER);
	getContentPane().add(panel6, BorderLayout.PAGE_END);
    }

    //---Action Event Method---
    public void actionPerformed(ActionEvent e)
    {
	MDcalculator mdc = new MDcalculator();
	String f1str, f4str, f5str, end_str, act_cmd;
	int f1, f2=0, f3=0, f4, f5;
	int f2index, f3index;

	act_cmd = e.getActionCommand();
	if(act_cmd.equals("run")){
	    //---form1---
	    f1str = form1.getText();
	    f1 = Integer.parseInt(f1str);
	    //---form2---
	    f2index = form2.getSelectedIndex();
	    if(f2index == -1){
		caution.setText("Error!");
	    }else{
		if(f2index == 0) f2 = 1;
		else if(f2index == 1) f2 = 0;
	    }
	    //---form3---
	    f3index = form3.getSelectedIndex();
	    if(f3index == -1){
		caution.setText("Error!");
	    }else{
		if(f3index == 0) f3 = 1;
		else if(f3index == 1) f3 = 0;
	    }
	    //---form4---
	    f4str = form4.getText();
	    f4 = Integer.parseInt(f4str);
	    //---form5---
	    f5str = form5.getText();
	    f5 = Integer.parseInt(f5str);

	    //---Run MDcalc---
	    caution.setText("Start!");
	    end_str = mdc.calc(f1, f2, f3, f4, f5);
	    caution.setText(end_str);
	}else if(act_cmd.equals("reset")){
	    form1.setText("");
	    form4.setText("");
	    form5.setText("");
	    caution.setText("Reset!");
	}else if(act_cmd.equals("copy")){
	    mdc.copy();
	    caution.setText("Copy!");
	}
    }
}

| | コメント (0) | トラックバック (0)

2008/01/22

Javaプログラム内から外部プログラムを呼び出す

無理やりSwing!」で、私は数値計算プログラムごとJavaで書き直そうとしていましたが、スケジュール的にきつくなってきたので、数値計算プログラムはC言語のままで、パラメータ入力だけをJava Swingにやらせることにしました。

外部プログラムをJavaプログラムから起動するには「Runtimeクラス」か、「JNI(Java Native Interface)」 という選択肢があるようです。

Runtimeクラスのexec()で外部プロセスを起動する方法のほうがJNIをつかうよりも簡単にできそうです。(JNIのほうがパフォーマンスが良いようですが)

C言語プログラムにはscanf()ではなく、コマンドライン引数で値を渡すように改造すればいいだけです。

今回はJavaからC言語プログラムを呼び出すことにしましたが、もっとJavaを勉強して、いつかはJavaで書き直したいです。(グラフの描画も含めて)

| | コメント (0) | トラックバック (0)