Javaゼミ第11回目

Javaゼミ第11回目
11.6 ランダムアクセスファイル
11.7 StreamTokenizerクラス
発表日 6月28日
発表者 加藤 友宏
ランダムアクセスファイル
ストリームクラスでは、順次アクセスでファイル内
のデータを読み書きのみ。
 RandomAccessFileクラスは、ファイルのどの位
置でもシークでき、その位置でデータの読み書き
が可能。
例えば、ファイルに格納されているデータレコード
セットを管理するのに使う。

ランダムアクセスファイル

RandomAccessFileクラスのコンストラクタ
(1) RandomAccessFile(File file, String mode)
(2) RandomAccessFile(String name, String mode)
(1) fileを読み込み元として、また場合によっては書き込み先とし
て、ランダムアクセスファイルストリームを作成する。
(2) nameを持つファイルからの読み込み、およびオプションで書き
込みを行うランダムアクセスファイルストリームを作成する 。
modeは、アクセスモードの指定。以下の4種類がある。
変数
説明
読み込み専用。開いたオブジェクトの任意のwriteメソッドを呼び出すと、
"r"
IOException がスローされます。
"rw" 読み込み・書き込み専用。ファイルが存在しない場合は、新規作成する。
"rw" と同様に、読み込み・書き込み専用。ファイルの内容またはメタデータ
"rws"
を更新したときは、元になる記憶装置にも同時に適用する必要がある。
"rw" と同様に、読み込み・書き込み専用。ファイルの内容を更新したとき
"rwd"
は、元になる記憶装置にも同時に適用する必要がある。
ランダムアクセスファイル


RandomAccessFileは、DataInputインターフェ
イスとDataOutputインターフェイスを実装
RandomAccessFileクラスに定義されている主
なインスタンスメソッド
メソッド
説明
void close() throws IOException ファイルをクローズする
ファイルポインタの現在位置を返す。これ
long getFilePointer() throws
により、次に読み取るまたは書き込むバ
IOException
イトの位置を識別する
long length() throws
ファイル内のバイト数を返す
IOException
ファイルからバイトを読み取って返す。
int read() throws IOException
データが利用可能になるまで待機する。
ランダムアクセスファイル

RandomAccessFileクラスに定義されている主
なインスタンスメソッドの続き
説明
ファイルからsizeバイト読み取り、位置indexを先頭
としてbufferに入れる。実際によい取ったバイト数
を返す。データが利用可能になるまで待機する。
ファイルからバイトを読み取り、bufferに入れる。
int read(byte buffer[]) throws
読み取ったバイト数を返す。データが利用可能に
IOException
なるまで待機する。
ファイルの先頭からnバイトの位置にファイルポイ
void seek(long n) throws
ンタを位置付ける。この位置で次の読み取りまた
IOException
は書き込みが発生する。
現在のファイルポインタにnだけ追加して飛ばす。
int skipBytes(int n) throws
実際に飛ばしたバイト数を返す。nが負の場合に
IOException
はバイトの飛ばしは行われない
メソッド
int read(byte buffer[], int
index, int size) throws
IOException
ファイルのどの位置にもランダムにアクセスできる → seek()が重要
ランダムアクセスファイルの例
ファイルの最後から指定した個数のバイトを表示するプログラム
import java.io.*;
// ファイルの長さを決める
long position = raf.length();
class Tail {
public static void main(String args[]) {
try {
// RandomAccessFileオブジェクトを
//作成する
RandomAccessFile raf =
new RandomAccessFile(args[0], "r");
// ファイルの終わりに表示する
// バイト数を決める
long count =
Long.valueOf(args[1]).longValue();
// 現在の位置にシークする
position -= count;
if (position < 0)
position = 0;
raf.seek(position);
// バイトを読み取って、表示する
while(true) {
// バイトを読み取る
try {
byte b = raf.readByte();
ランダムアクセスファイルの例
// 文字として表示する
System.out.print((char)b);
}
catch (EOFException eofe) {
break;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
実行結果
作成したプログラムの
最後40バイトを指定。
e.printStackTrace();
}
}
}
StreamTokenizerクラス

StreamTokenizerクラスは、文字入力ストリーム
からデータを解析して、トークンの列を生成。
数字または単語を表す文字のグループ

パーサ、コンパイラ、文字入力を処理するプログ
ラムで重要な機能
StreamTokenizerクラス

StreamTokenizerクラスのコンストラクタ
StreamTokenizer(Reader r)
rはReaderオブジェクト

4つ定数が定義されている
TT_EOF
TT_EOL
TT_NUMBER
TT_WORD
ファイルの終わり
行の終わり
数字を読み取ったこと
単語を読み取ったこと
StreamTokenizerクラス




3つのインスタンス変数に、重要な情報がある
トークンが数字
→nvalに値、ttypeにTT_NUMBER
トークンが文字列
→svalに値、ttypeにTT_WORD
トークンが数字、文字列以外
→ ttypeに読み取った文字
StreamTokenizerクラス
StreamTokenizerクラスに定義されているインスタン
スメソッド

メソッド
void commentChar(int ch)
説明
chが単一行コメントから始まることを示す
void eollsSignificant(boolean
flag)
int lineno()
flagが真の場合には、行の終わりをトークンとして扱
い、偽の場合は空白として扱う
現在の行番号を返す
void lowerCaseMode(boolean
flag)
flagが真の場合には、トークンを自動的に小文字に
変換し、偽の場合変換しない
int nextToken() throws
IOException
次のトークンが数字の場合はTT_NUMBERを返し、
次のトークが単語の場合はTT_WORDを返す。それ
以外の場合は、次のトークンに等しい文字を返す
void ordinaryChar(int ch)
chを通常文字として扱うことを指定する
void ordinaryChars(int c1, int c2)
範囲c1~c2(c1およびc2を含む)内のすべての文字
を通常文字として扱うことを指定する
StreamTokenizerクラス
StreamTokenizerクラスに定義されているインスタ
ンスメソッドの続き

メソッド
void parseNumbers()
void pushBack()
void quoteChar(int ch)
void resetSyntax()
説明
数字を解析することを指定する
現在のトークンを入力ストリームに戻す
chを文字列リテラルの引用符文字として定義する
すべての文字を通常文字として扱うことを指定する
void slashSlashComments(boolean
flag)
flagが真の場合には、//コメントを無視し、偽の場合
には無視しない
void slashStarComments(boolean flag)
String toString()
void whitespaceChars(int c1, int c2)
void wordChars(int c1, int c2)
flagが真の場合には、/*...*/コメントを無視し、偽の
場合には無視しない
現在のトークンと等価の文字列を返す
範囲c1~c2(c1およびc2を含む)内のすべての文
字をホワイトスペースとして扱うことを指定する
範囲c1~c2(c1およびc2を含む)内のすべての文
字を単語の文字として扱うことを指定する
StreamTokenizerを
使用する手順
1.
2.
3.
4.
5.
6.
7.
ReaderのStreamTokenizerオブジェクトを作成
文字を処理する方法を定義
nextToken()を呼び出し次のトークンを取得
ttypeインスタンス変数を読み取り、トークンの方
を判断
sval、nval、ttypeのいずれかのインスタンス変
数からトークンの値を読み取る
トークンを処理
nextToken()がStreamTokenizer.TT_EOFを返す
までステップ3~6を繰り返す
StreamTokenizerクラスの例
テキストファイルを読み取って、その内容を解析するプログラム
import java.io.*;
class StreamTokenizerDemo {
public static void main(String args[]) {
try {
// FileReaderオブジェクトを作成
FileReader fr = new
FileReader(args[0]);
// BufferedReaderオブジェクトを作成
BufferedReader br = new
BufferedReader(fr);
// StreamTokenizerオブジェクトを作成
StreamTokenizer st = new
StreamTokenizer(br);
// ピリオドを通常文字として定義する
st.ordinaryChar('.');
// アポストロフを単語文字として定義する
st.wordChars('\'', '\'');
// トークンを処理する
while(st.nextToken() !=
StreamTokenizer.TT_EOF) {
switch(st.ttype) {
case StreamTokenizer.TT_WORD:
System.out.println(st.lineno() + ") " +
st.sval);
break;
StreamTokenizerクラスの例
case StreamTokenizer.TT_NUMBER:
System.out.println(st.lineno() + ")
"+
st.nval);
break;
default:
System.out.println(st.lineno() + ")
"+
(char)st.ttype);
}
}
// FileReaderオブジェクトをクローズする
fr.close();
}
catch (Exception e) {
System.out.println("Exception: " + e);
}
}
}
StreamTokenizerクラスの例
実行結果
指定したテキストファイルの中身
ファイル名:tokens.txt
The price is $23.45
Is that too expensive?
(I don't think so)
1)
1)
1)
1)
1)
2)
2)
2)
2)
2)
3)
3)
3)
3)
3)
3)
The
price
is
$
23.45
Is
that
too
expensive
?
(
I
don't
think
so
)
練習問題1

RandomAccessFileクラスを用いて、コマンドライン引数か
ら取得した文字列をファイルに追加していくプログラムを
作成せよ。
書き込んだ後、ファイルの中身を表示すること。
なお、書き込むファイル名、書き込む内容は任意とする。
実行例
作成したファイルの中身
1行目
2行目
3行目
4行目
5行目
orange
strawberry
apple
banana
avocado
:
:
:
:
:
orange
strawberry
apple
banana
avocado
練習問題2

コマンドライン引数で取得したファイル名のソースに、
Java のいくつかの予約語が、どのくらいの回数使われて
いるのかを調べるプログラムを作成せよ。
調べる予約語は、if,else,try,catch,while,switch,break,
continueの8個とする。
実行例
ifが使われた回数は、12回
elseが使われた回数は、10回
tryが使われた回数は、4回
catchが使われた回数は、4回
whileが使われた回数は、4回
switchが使われた回数は、3回
breakが使われた回数は、3回
continueが使われた回数は、3回