「こんにちは、アミーゴ!」

「こんにちは、ビラーボ!人生はどうですか?」

「よかったです。昨日、寄生虫を駆除しようとしましたが、今のところあまり成功していません。そして、またゴミ箱の中で一晩過ごさなければなりませんでした。」

「それで……まだ何もかも順調ですか?」

そう言えますね。

「わかりました。それで、今日は何かありますか?」

今日はRandomAccessFileクラスについてお話します。

ランダムアクセスファイルなど - 1

「実際のところ、FileInputStream と FileOutputStream はファイルをストリームとして表しており、それらの読み取りと書き込みはシーケンシャルにしか行えません。」

「これは常に非常に便利というわけではありません。ファイルの途中に数行書き込んだり、数メガバイトのファイルの末尾から数ページのテキストを読み取る必要がある場合があります。読み取るのはあまり効率的ではありません。」これらのタスクのファイル全体。」

RandomAccessFileクラスは、この問題を解決するために作成されました。このクラスを使用すると、ファイル内の任意の場所に書き込み、読み取りを実行できるだけでなく、ファイルの読み取りと書き込みを同時に行うことができます。」

"なんて面白い!"

「そうですね。本当に便利ですよ。」

「しかし、任意の場所からどうやって読むのでしょうか?」

「すべて非常に単純です。メモ帳などのテキスト エディターが開いていると想像してください。それにはカーソルがあります。何かを入力すると、カーソルのある場所にテキストが追加されます。ファイルの読み取りも同じです。読み取りは次から始まります。 「カーソル」がある場所に移動します。読み取り/書き込み時には、カーソルが自動的に移動します。

「ここで、例を示した方がよいでしょう。」

ファイルの読み取り:
// r - read, the file is opened only for reading.
RandomAccessFile raf = new RandomAccessFile("input.txt", "r");

// Move the «cursor» to the 100th character.
raf.seek(100);

// Read the line starting from the current cursor position until the end of the line.
String text = raf.readLine();

// Close the file.
raf.close();

「この例では、次の 2 つの点に注目していただきたいと思います。」

"最初に、 RandomAccessFileオブジェクトを作成します。2 番目の引数は文字 r です。これは、ファイルが読み取り用に開かれる ( r - read ) ことを意味します。読み取りと書き込み用にファイルを開きたい場合は、« rwを渡す必要があります。 " r "だけではなく、" をコンストラクターに追加します。"

「2 番目に、seek メソッドを見てください。このメソッドを使用すると、ファイル内をジャンプして、現在の読み取り/書き込み操作のカーソル位置を変更できます。ファイルが最初に開かれたとき、カーソルは 0 番目のバイトに設定されます。または、より正確には、0 番目のバイトの前です。」

「正しく理解できましたか? ファイルを開くと、カーソルは先頭、つまり位置 0 にあります。次に、seekを呼び出してカーソルを 100 番目のバイトに移動します。そして、 readLine を呼び出すと、100 番目のバイトから読み取りを開始します。 。 右?"

「はい。ただし、seek メソッドを使用すると、ファイル内を任意にジャンプできるという事実に注意していただきたいと思います。たとえば、次のようになります。」

ファイルの読み取り:
// r - read, the file is opened only for reading.
RandomAccessFile raf = new RandomAccessFile("input.txt", "r");

// The "cursor" is at the 0th character.
String text1 = raf.readLine();

// Move the "cursor" to the 100th character.
raf.seek(100);
String text2 = raf.readLine();

// Move the "cursor" to the 0th character.
raf.seek(0);
String text3 = raf.readLine();

// Close the file
raf.close();

「この例では、最初に 0 番目のバイトから始まる行を読み取ります。次に、100 番目のバイトにジャンプして、そこにある行を読み取ります。次に、再び 0 番目のバイトにジャンプして、行を読み取ります。つまり、text1 と text3 は同一です。文字列。」

「ああ。それは物事をより明確にします。」

「素晴らしいですね。それでは別の例をご紹介します。」

ファイルの読み取り:
// rw - read/write, the file is opened for reading and writing.
RandomAccessFile raf = new RandomAccessFile("seek.txt", "rw");

// Write to the file, starting from the 0th byte.
raf.writeBytes("It is a string");

// Move the "cursor" to the 8th character.
raf.seek(8);

// Write "surprise!" to the file.
raf.writeBytes("surprise!");

// Close the file.
raf.close();

「ここでは、« rw » (読み取り/書き込み) をコンストラクターに渡して、読み取りおよび書き込み用にファイルを開きます。」

「次に、ファイルに「文字列です」と書き込みます。

「次に、カーソルを 8 番目のバイト (これはたまたま単語 'string' の先頭です) に移動します。」

「それでは«サプライズ!»と書きます」

「その結果、ファイルには「驚きです!」という内容が含まれています。」

「つまり、バイトはファイルの途中に挿入されるのではなく、そこにあったバイトを置き換えるということですか?」

「はい。」

「カーソルをファイルの最後に移動したらどうなるでしょうか?」

「そうすると、バイトは最後まで書き込まれ、ファイルは大きくなります。つまり、テキスト エディタにテキストを書き込むようなものになります。」

「うーん。すべて理解できたと思います。RandomAccessFileクラスのメソッドの完全なリストを提供してもらえますか?」

「はい。どうぞ。」

方法 説明
int read() 1バイトを読み取って返します
int read(byte b[], int off, int len) バイト配列を読み取ります
int read(byte b[]) バイト配列を読み取ります
void readFully(byte b[]) バイトの配列を読み取り、配列を満たすのに十分なバイトがない場合は、新しいバイトが追加されるのを待ちます。
int skipBytes(int n) n バイトをスキップします。つまり、カーソルが n バイト前に移動します。
void write(int b) カーソルの位置に 1 バイトを書き込みます
void write(byte b[]) バイト配列をカーソルの位置に書き込みます
void write(byte b[], int off, int len) バイト配列をカーソルの位置に書き込みます
long getFilePointer() カーソルが指しているバイト番号を返します。範囲は 0 からファイルの長さまでです
void seek(long pos) 読み書きに使用する《カーソル》を指定した位置に移動します
long length() ファイルの長さを返します
void setLength(long newLength) 新しいファイルの長さを設定します。ファイルが大きい場合は切り詰められます。それより小さい場合は、ファイルを拡張し、新しいスペースをゼロで埋めます。
void close() ファイルを閉じます
boolean readBoolean() ファイル内のカーソルの現在位置からブール値を読み取ります。
byte readByte() ファイル内のカーソルの現在位置からバイトを読み取ります。
char readChar() ファイル内のカーソルの現在位置から文字を読み取ります。
int readInt() ファイル内のカーソルの現在位置から int を読み取ります。
long readLong() ファイル内のカーソルの現在位置からlongを読み取ります。
float readFloat() ファイル内のカーソルの現在位置から float を読み取ります。
double readDouble() ファイル内のカーソルの現在位置から double を読み取ります。
String readLine() ファイルから 1 行を読み取り、それを返します
void writeBoolean(boolean v) ブール値をファイルに書き込みます (カーソルの位置から開始)
void writeByte(int v) t ファイルにバイトを書き込みます(カーソルの位置から開始)
void writeChar(int v) 文字をファイルに書き込みます(カーソルの位置から開始)
void writeInt(int v) int をファイルに書き込みます (カーソルの位置から開始)
void writeLong(long v) ファイルにlongを書き込みます(カーソルの位置から開始)
void writeFloat(float v) ファイルに float を書き込みます (カーソルの位置から開始します)。
void writeDouble(double v) double をファイルに書き込みます (カーソルの位置から開始)
void writeBytes(String s) 文字列をファイルに書き込みます(カーソルの位置から開始)
void writeChars(String s) 文字列をファイルに書き込みます(カーソルの位置から開始)

「うーん。つまり、ここには何も新しいことはありません。おそらく、seek()/getFilePointer() メソッドと length()/setLength() メソッドのペアを除いて。」

「はい、アミーゴ。何もかも同じです。でも、それは便利ではありませんか?」

「便利です。ビラーボさん、興味深い授業と例を教えてくれてありがとう。」

「助けてよかった、アミーゴ、友よ!」