乱数の生成

JDKにおいて、乱数を生成するクラスは二つあります。 一つはjava.util.Randomクラス、もう一つはjava.lang.Mathクラスです。 実際に使用してその動作を見てみます。

import java.util.*;

public class LearningJava
{
    public static void main( String[] args )
    {
        // Randomクラスのインスタンスを作成
        Random rnd = new Random();

        for ( int i = 0; i < 10; i++ )
        {
            // java.util.Random.nextDouble()メソッドよる乱数の生成
            double rnd1 = rnd.nextDouble();

            // java.lang.Math.random()メソッドによる乱数の発生
            double rnd2 = Math.random();

            System.out.println( i + ": " + rnd1 + " / " + rnd2 );
        }
    }
}
実行結果
0: 0.23880118630901193 / 0.23880118630901193
1: 0.8288732683486508 / 0.8288732683486508
2: 0.2536719518198898 / 0.2536719518198898
3: 0.28133619860453163 / 0.28133619860453163
4: 0.6749980030344941 / 0.6749980030344941
5: 0.2979008821787835 / 0.2979008821787835
6: 0.8306057445520595 / 0.8306057445520595
7: 0.4125203165488647 / 0.4125203165488647
8: 0.9516971247762693 / 0.9516971247762693
9: 0.5739107989773766 / 0.5739107989773766

このように、二つの違うクラス・メソッドを用いているにもかかわらず、同じ数値が得られます。 というのも、Mathクラスでは内部的にRandomクラスのインスタンスを生成し、それを用いているためです。 さらに、Randomクラスのインスタンスに対して同じシード値を与えられている場合、同じ乱数が生じます。 そのためこのような結果になります。

Mathクラスには0以上1未満のdouble値を返すrandom()メソッドしかありませんが、Randomクラスには様々なメソッドがあります。

Mathクラス

JDKのMathクラスのメンバのほとんどは、.NET FrameworkのMathクラスと大差ありません。 一部ですが、その使用例が次のコードです。

public class LearningJava
{
    public static void main( String[] args )
    {
        System.out.println( "Sin(π/2) = " + Math.sin( Math.PI / 2.0 ) );
        System.out.println( "Cos(π/4) = " + Math.cos( Math.PI / 4.0 ) );
        System.out.println( "Tan(π/6) = " + Math.tan( Math.PI / 6.0 ) );

        System.out.println( "Atan(1/√3)  = " + Math.atan( 1.0 / Math.sqrt(3.0) ) );
        System.out.println( "Atan2(1/√3) = " + Math.atan2( 1.0, Math.sqrt(3.0) ) );

        System.out.println( "π/2[rad] = " + Math.toDegrees( Math.PI / 2.0 ) + "[deg]");
        System.out.println( "45[deg] = " + Math.toRadians( 45.0 ) + "[rad]" );
    }
}
実行結果
Sin(π/2) = 1.0
Cos(π/4) = 0.7071067811865476
Tan(π/6) = 0.5773502691896257
Atan(1/√3)  = 0.5235987755982989
Atan2(1/√3) = 0.5235987755982989
π/2[rad] = 90.0[deg]
45[deg] = 0.7853981633974483[rad]

.NET FrameworkのMathクラスにないメソッドとして、toDegrees()メソッド及びtoRadians()メソッドがあります。 このメソッドは、度数で表された角度をラジアンに変換したり、その逆を行うためのメソッドです。

Fileクラス

java.io.Fileクラスは、.NET FrameworkにおけるFileクラス、Pathクラス、Directoryクラスの機能が一つになった様なクラスです。

import java.io.*;

public class LearningJava
{
    public static void main( String[] args )
    {
        // Fileクラスのインスタンスを作成
        File f = new File("E:\\Java Program\\test.txt");

        System.out.println( f.getName() + " existence: " + f.exists() );

        // ファイルを生成
        try
        {
            f.createNewFile();
            System.out.println( f.getName() + " was created." );
        }
        catch ( Exception ex )
        {
            System.out.println( ex.getMessage() );
            System.out.println( "File creation failed." );
            return;
        }

        System.out.println( f.getName() + " existence: " + f.exists() );
        System.out.println( "Path: " + f.getPath() );
        System.out.println( "Parent: " + f.getParent() );
        System.out.println( "Is directory: " + f.isDirectory() );
        System.out.println( "Is file: " + f.isFile() );

        // ファイルを削除
        f.delete();

        System.out.println( f.getName() + " was deleted." );
        System.out.println( f.getName() + " existence: " + f.exists() );
    }
}
実行結果
test.txt existence: false
test.txt was created.
test.txt existence: true
Path: E:\Java Program\test.txt
Parent: E:\Java Program
Is directory: false
Is file: true
test.txt was deleted.
test.txt existence: false

このように、ファイルの生成・削除や、ファイル属性、絶対パスの取得など、様々な操作が行えます。 ここではパスにファイル名を指定したのでファイルに対する操作になりますが、ディレクトリ名を指定すればディレクトリに対して操作を行えます。

FileWriterクラスとFileReaderクラス

java.io.FileWriterクラスとjava.io.FileReaderクラスはファイルへの簡単な書き込み・読み込みを行うためのクラスです。

import java.io.*;

public class LearningJava
{
    public static void main( String[] args )
    {
        // Fileクラスのインスタンスを作成
        File f = new File("E:\\Java Program\\test.txt");

        // ファイルを生成
        try
        {
            if ( !f.exists() ) f.createNewFile();
        }
        catch ( IOException ex )
        {
            System.out.println( "ファイルの作成に失敗。 " + ex.getMessage() );
            return;
        }

        // FileWriterのインスタンスを作成
        FileWriter writer;

        try
        {
            writer = new FileWriter( f );
        }
        catch ( IOException ex )
        {
            System.out.println( "FileWriterインスタンスの作成に失敗。 " + ex.getMessage() );
            return;
        }

        // 現在のエンコーディング名を取得
        System.out.println( "Encoder: " + writer.getEncoding() );

        // 書き込み
        try
        {
            writer.write( "FileWriterのテスト。\r\n" );
            writer.write( "うまく書き込めてるかな?\r\n" );
            writer.close();
        }
        catch ( IOException ex )
        {
            System.out.println( "書き込みに失敗。 " + ex.getMessage() );
            return;
        }

        // FileReaderのインスタンスを作成
        FileReader reader;

        try
        {
            reader = new FileReader( f );
        }
        catch ( IOException ex )
        {
            System.out.println( "FileReaderインスタンスの作成に失敗。 " + ex.getMessage() );
            return;
        }

        // 読み込み
        char[] buff = new char[0x100];

        try
        {
            reader.read( buff );
            reader.close();
        }
        catch ( IOException ex )
        {
            System.out.println( "読み込みに失敗。 " + ex.getMessage() );
            return;
        }

        // 出力
        String str = new String( buff );
        str = str.substring( 0, str.indexOf(0) );
        
        System.out.println( str );
    }
}
出力されたファイルの内容 (E:\Java Program\test.txt)
FileWriterのテスト。
うまく書き込めてるかな?
実行結果)
Encoder: MS932
FileWriterのテスト。
うまく書き込めてるかな?

読み込み時のバッファサイズ0x100は適当な数値です。 しかし、length()メソッドなどでファイルのサイズを取得してから決定した方がいいのかもしれません。 ちなみに、使用されているエンコーディング名は「MS932」と出力されていますが、これはSHIFT-JISを表すものと思われます。

また、78〜79行目においてchar配列のバッファを文字列化する際に、バッファの余った部分には0で満たされているので、その部分までを有効なデータとして切り出しています。

BufferedWriterクラスとBufferedReaderクラス

java.io.BufferedWriterクラスとjava.io.BufferedReaderクラスはFileWriter・ FileReader同様、ファイルへの書き込み・読み込みを行うためのクラスですが、FileWriter・FileReaderとは異なり書き込み・読み込み時にバッファリングされます。

import java.io.*;

public class LearningJava
{
    public static void main( String[] args )
    {
        // Fileクラスのインスタンスを作成
        File f = new File("E:\\Java Program\\test.txt");

        // ファイルを生成
        try
        {
            if ( !f.exists() ) f.createNewFile();
        }
        catch ( IOException ex )
        {
            System.out.println( "ファイルの作成に失敗。 " + ex.getMessage() );
            return;
        }

        // BufferedWriterのインスタンスを作成
        BufferedWriter writer;

        try
        {
            // FileWriterをラップ
            writer = new BufferedWriter( new FileWriter( f ) );
        }
        catch ( IOException ex )
        {
            System.out.println( "BufferedWriterインスタンスの作成に失敗。 " + ex.getMessage() );
            return;
        }

        // 書き込み
        try
        {
            writer.write( "BufferedWriterのテスト。" ); writer.newLine();
            writer.write( "きっと書き込めてるよね?" ); writer.newLine();
            writer.close();
        }
        catch ( IOException ex )
        {
            System.out.println( "書き込みに失敗。 " + ex.getMessage() );
            return;
        }

        // BufferedReaderのインスタンスを作成
        BufferedReader reader;

        try
        {
            // FileReaderをラップ
            reader = new BufferedReader( new FileReader( f ) );
        }
        catch ( IOException ex )
        {
            System.out.println( "BufferedReaderインスタンスの作成に失敗。 " + ex.getMessage() );
            return;
        }

        // 読み込み
        try
        {
            String str;

            while ( ( str = reader.readLine() ) != null )
            {
                System.out.println( str );
            }

            reader.close();
        }
        catch ( IOException ex )
        {
            System.out.println( "読み込みに失敗。 " + ex.getMessage() );
            return;
        }

    }
}
出力されたファイルの内容 (E:\Java Program\test.txt
BufferedWriterのテスト。
きっと書き込めてるよね?
実行結果
BufferedWriterのテスト。
きっと書き込めてるよね?

この例ではBufferedWriter及びBufferedReaderをインスタンス化する時に、FileWriterまたはFileReaderのインスタンスを作成し、それをラップします。 出力に際して、改行コードを出力するためにはnewLine()メソッドを呼び出す必要があります。

BufferedReaderでは一行単位の読込が行えます。 このときファイルの終端に達するとreadLine()メソッドはnullを返します。 67〜70行目ではnullが返されるまで読み取りを繰り返し、表示しています。

PrintWriterクラス

PrintWriterクラスでは、書き出したいデータを適切な表現にフォーマットして出力します。

import java.io.*;

public class LearningJava
{
    public static void main( String[] args )
    {
        // Fileクラスのインスタンスを作成
        File f = new File("E:\\Java Program\\test.txt");

        // ファイルを生成
        try
        {
            if ( !f.exists() ) f.createNewFile();
        }
        catch ( IOException ex )
        {
            System.out.println( "ファイルの作成に失敗。 " + ex.getMessage() );
            return;
        }

        // PrintWriterクラスのインスタンスを作成
        PrintWriter writer;

        try
        {
            writer = new PrintWriter( new FileWriter( f ) );
        }
        catch ( IOException ex )
        {
            System.out.println( "PrintWriterインスタンスの作成に失敗。 " + ex.getMessage() );
            return;
        }

        writer.println( "PrintWriterのテスト。" );

        writer.println( "数値の書き込み" );
        writer.println( 1234567890 );
        writer.println( 3.14159265 );
        writer.println( true );

        writer.println( "オブジェクトの書き込み" );
        writer.println( f );
        writer.println( writer );

        writer.close();

    }
}
出力されたファイルの内容 (E:\Java Program\test.txt)
PrintWriterのテスト。
数値の書き込み
1234567890
3.14159265
true
オブジェクトの書き込み
E:\Java Program\test.txt
java.io.PrintWriter@965fb

この例でもBufferedWriter同様、インスタンス化する際にFileWriterのインスタンスを作成して、それをラップしています。 また、書き込みに際しては、改行文字を同時に出力するprintln()メソッドを使用しています。 改行文字を出力しないprint()メソッドも存在します。

出力結果を見てわかるとおり、文字列や数値だけでなく、オブジェクトも適切に出力されています。 オブジェクトの値として出力されたこれらの文字列は、ObjectクラスからオーバーライドしたtoString()メソッドによって得られるものです。