- トップページ
- 特集PC技術
- Java言語入門 ~C言語を学んだ君へ~
- [第16回]入出力
Java言語入門 ~C言語を学んだ君へ~
[第16回]入出力
Javaでの入出力を行うための基礎を説明します。
目次
[1] 入出力の基礎知識
Javaで入出力を行うにはストリームを使います。
ストリームとは「データの流れ」を表す抽象的な概念です。
ストリームを使用する目的は、異なる物理デバイスでも、簡単に入出力を行うためです。
入出力と言ってもいくつもの種類があります。
例えば、キーボード入力とモニタ出力、ファイルへの入出力などです。
これらに対して、個別に入出力の方法を適用することはとても大変です。
しかし、ストリームという抽象的な概念を使うことで、同じ処理で入出力が可能になります。
文字ストリームとバイトストリーム
ストリームには2つの種類があります。
それは文字ストリームとバイトストリームです。
文字ストリームとは、テキストデータを扱うためのストリームです。
バイトストリームとは、バイナリデータを扱うためのストリームです。
例えば、メモ帳などで作成する文章は、テキストデータであり、
画像、音楽ファイルはバイナリデータになります。
対象となるデータによって、2つのストリームを使い分けて入出力を行います。
入出力パッケージ
Javaには入出力を行うためのクラスがパッケージとして用意してあります。
そのパッケージが「java.io」です。
このパッケージには次のクラス関係があります。
それぞれのストリームに対してのクラスが提供されています。
少し多いですが、この回で使用するクラスは
「InputStreamクラス」
「BufferedReaderクラス」
「BufferedWriterクラス」
「FileReaderクラス」
「FileWriterクラス」
の5つです。なお、上記以外にも入出力クラスはあります。
他のクラスについての説明はAPIを見てください。
[2] コンソール入力
コンソールからの入力方法を説明します。
C言語を学んだ方によっては、少し遅いと思ったことでしょう。
しかし、Javaでは入出力を行うために、「クラス」、「パッケージ」、「例外」など、
多くの知識が必要になります。少し難しいかもしれません。
良くない方法
いきなり「良くない方法」を説明します。良い方法はあとで説明します。
ところで、コンソール出力をする場合は、「System.out.println()」を使います。
この「out」とは、PrintStreamクラスであり、このクラスのメソッドを用いて出力を行います。
この他に、Systemクラスには「in」というオブジェクトを持っています。
これはInputStreamクラスであり、標準でキーボード入力ができます。
つまり、このクラスを使うことで、コンソール入力が行えます。
では、コンソール入力のサンプルプログラムを次に示します。
なお、読み込みにはInputStreamクラスのreadメソッドを使います。
サンプルプログラム1
import java.io.*; // インポート public class Java16_01 { public static void main(String args[]) { try { System.out.print("入力してください:"); int n = System.in.read(); System.out.println("入力したデータ:" + n); } catch (IOException e) { e.printStackTrace(); } } }
実行結果1
実行結果より「何か」の入力はできたと思います。
ただし、正しい文字入力はできていません。
その理由は、InputStreamクラスは1バイトデータしか扱えないからです。
つまり、文字入力はできません。
これを改善するには「ストリームのラッピング」が必要になります。
ストリームのラッピング
ストリームのラッピングとは、ストリームをストリームで覆い(ラッピングを行い)、高性能な入出力ストリームにすることです。
上のプログラムではInputStreamクラスを使ってコンソール入力を行いました。
しかし、このクラスは「低機能」のため、文字入力が正しくできませんでした。
そこで、ラッピングを行って「高性能」にします。
方法はInputStreamクラスをInputStreamReaderクラスでラッピングします。
これによって、文字単位の入力ができるようになります。
さらに、InputStreamReaderクラスをBufferedReaderクラスでラッピングすると、
一行単位の入力ができるようになります。それにはreadLineメソッドを使います。
次のサンプルプログラム2を見てください。
サンプルプログラム2
import java.io.*; public class Java16_02 { public static void main(String args[]) { try { // InputStream→InputStreamReader→BufferedReaderの順にラッピング BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.print("入力してください:"); String s = br.readLine(); System.out.println("入力したデータ:" + s); br.close(); } catch (IOException e) { e.printStackTrace(); } } }
実行結果2
今度は正しくコンソール入力ができます。
少し、ラッピングの方法は難しかったかもしれません。
なお、作成したストリームを使用した後は、close()メソッドで終了してください。
これについては、C言語と同じです。
ところで、このサンプルプログラム2ではBufferedReaderクラスを使いました。
しかし、このクラスを使わなくても、InputStreamReaderクラスのみで文字入力は可能です。
使用した理由は、BufferedReaderクラスを使うことで、文字入力の効率が向上するからです。
そのため、文字列を扱うときは、BufferedReaderを使用した方法が良いでしょう。
[3] ファイル入出力
ファイル入出力について説明します。
ここでは、ファイル入出力の例として、ファイルのコピーを行います。
前準備(ファイルの作成)
まず、ファイル入出力に使うファイルを作成します。
ファイルは入力用と出力用の2種類を作成してください。
そして、ファイル名は「input.txt」と「output.txt」とします。
Eclipseの場合、「ファイル」→「新規」→「ファイル」をクリックします。
そして、プロジェクトを指定し、ファイル名を書きます。
その後、「終了」をクリックすると、ファイルが作成できます。
作成できたら、「input.txt」ファイルに次のように書いてください。
ほぷしぃ
ABCDEFG
12345
以上でファイル作成は終了です。
ファイル入出力の手順
ファイル入出力には
FileReaderクラス
BufferedReaderクラス
FileWriterクラス
BufferedWriterクラス
の4つを使います。
では、ファイル入出力の例として、ファイルをコピーする処理を行います。
input.txtに書いてある内容が、output.txtにコピーされるようにします。
入出力の手順は次の通りです。
1.ファイル入出力ストリームの作成
2.入力ファイルから1行読み込む
3.出力ファイルに、読み込んだ1行を書き込む
4.ファイルの最後まで読み書きの繰り返し
5.ファイル入出力ストリームを閉じる
基本的な流れを書きました。
では、次にサンプルプログラムを示します。
サンプルプログラム
サンプルプログラムです。
注意点として、上記で作成したファイルと同じプロジェクトに置いてください。
import java.io.*; class Java16_03 { public static void main(String args[]) { try { // ①ファイル入出力ストリームの作成 BufferedReader br = new BufferedReader(new FileReader("input.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt")); String str; while (true) { // ②入力ファイルから1行読み込む str = br.readLine(); if (str == null) break; // ③出力ファイルに、読み込んだ1行を書き込む bw.write(str + "\n"); } // ④ファイルの最後まで読み書きの繰り返し // ⑤ファイル入出力ストリームを閉じる br.close(); bw.close(); } catch (IOException e) { e.printStackTrace(); } } }
実行結果(output.txtファイル)
output.txtにinput.txtの内容がコピーされたことが確認できます。
少しプログラムの解説をします。
ファイルへの読み込みは一行単位です。
そのため、ループを使って繰り返し行います。
そして、ファイルの最後まで読み込むと、readLineメソッドの戻り値がnullになります。
そのとき、ループを抜けるように処理しています。
また、writeメソッドでは文字列を書き込んでいます。
このとき、"\n"を追加しています。
使用しないと、改行できません。
[4] データ解析
入出力の方法はだいたいわかったと思います。
次は、データの型を意識して読み込みを行います。
StringTokenizer
これまでの入力は文字列(String型)のみでした。
しかし、入力データは文字列ばかりでなく、数値もあります。
また、文字列と数値の混合データも考えられます。
こうした場合に、StringTokenizerクラスを使います。
このクラスは、入力データを解析し、トークンを生成することができます。
トークンとは、文字列・数値などの最小単位のことです。
例えば、次のようなファイルデータがあります。
太郎,日本,10
次郎,中国,11
三郎,独逸,12
見方は一行に「名前」と「国籍」と「年齢」が書いてあります。
つまり、3人分の個人情報です。
このデータを読み込む場合、これまでの方法では"太郎,日本,10"という単なる文字列で読み込んでしまいます。
このままでは、正しい入力とは言えません。
しかし、StringTokenizerクラスを使うと、"太郎"と"日本"と"10"という3つのトークンに分けることができます。
ただし、「型」はすべてString型です。
そのため、Integerクラスを使って、年齢は数値に変換します。
これで正しいデータ入力になります。
では、次にデータ解析のサンプルプログラムを示します。
サンプルプログラム
入力ファイル「text.txt」には
太郎,日本,10
次郎,中国,11
三郎,独逸,12
の個人情報を入れてください。
import java.io.*; import java.util.StringTokenizer; class Java16_04 { public static void main(String args[]) { try { BufferedReader br = new BufferedReader(new FileReader("text.txt")); String str; String name; String nationality; int age; while (true) { str = br.readLine(); if (str == null) break; // 区切り文字","を指定する StringTokenizer st = new StringTokenizer(str, ","); // トークンを取り出す name = st.nextToken(); nationality = st.nextToken(); age = Integer.parseInt(st.nextToken()); // 出力 System.out.print("名前は" + name); System.out.print(" 国籍は" + nationality); System.out.println(" 年齢は" + age); } br.close(); } catch (IOException e) { e.printStackTrace(); } } }
実行結果
ファイル入力の方法は今までと同じです。
入力した文字列を使って、StringTokenizerクラスでトークンに切り分けます。
このとき、どこで区切るかはコンストラクタで指定します。
トークンはnextTokenメソッドで受け取ります。
ただし、文字列しか返さないので、年齢などの異なる型には、ラッパークラスを用いて変換するようにしてください。
なお、StringTokenizerクラスは「java.util」パッケージにあるので、必ず、importするようにしてください。
[5] 練習問題 第1問
ファイルへの書き込みの練習です。
ファイル「test.txt」に「1,2,3,4,5,6,7,8,9,10」を書き込むプログラムを作成してください。
ファイル「test.txt」は以下のように表示されます。
[6] 第1問解答
第1問解説
6行目では、BufferedWriterクラスのオブジェクトbwを生成しています。
8行目では、writeメソッドを使って、引数の中身を書き込んでいます。
9行目では、closeでオブジェクトを閉じています。
[7] 練習問題 第2問
練習問題1でファイル「test.txt」に書き込んだ文字列「1,2,3,4,5,6,7,8,9,10」を読み込み、','でトークンに分け、数値に変換します。
そして、奇数、偶数別に合計を計算し、コンソールに表示してみましょう。
コンソールには以下のように表示されます。
注意事項
なお、文字列をトークンに分けるには、StringTokenizerクラスを使いましょう。
このクラスには、以下の主要メソッドがあります。必要なら使いましょう。
・ public boolean hasMoreTokens()・・・トークンがまだある場合trueを返します
・ public String nextToken()・・・次のトークンを返します
[8] 第2問解答
第2問解説
8行目:BufferedReaderクラス
8行目では、BufferedReaderクラスのオブジェクトbrを生成しています。
これから読み取るファイル(test.txt)の指定も行っています。
13行目:ファイルからの読み込み
13行目では、readLineを使って、test.txtファイルを1行読み込んでいます。
15行目:StringTokenizerクラス
15行目では、StringTokenizerクラスのオブジェクトstを生成しています。
これにより、トークンが','によって分けられることとなりました。
17~21行目:トークン、int型への変換、奇数と偶数の判別
17行目では、トークンがある間、繰り返し処理を行います。
18行目では、取り出したトークンをint型に変換しています。
19、20行目では、int型に変換された数字を2で割ったときの余りから、奇数か偶数かを判別し、その合計を求めます。
23~:コンソールへの出力
23、24行目では、奇数と偶数それぞれの合計をコンソールに出力します。
25行目では、brをcloseします。
コメントの投稿
トラックバックURL
http://www.isl.ne.jp/cgi-bin/mt/mt-tb.cgi/1083