"Bună, Amigo!"

"Bună, Bilaabo! Cum e viața?"

"Genial. Ieri, am încercat să scap de niște paraziți, dar până acum nu am avut prea mult succes. Și apoi a trebuit să petrec iar noaptea la coșul de gunoi."

— Deci... totul este încă grozav?

— Ai putea spune asta.

"Bine. Deci ce ai pentru mine azi?"

„Astăzi vă voi spune despre clasa RandomAccessFile ”.

RandomAccessFile etc. - 1

„Chestia este că FileInputStream și FileOutputStream reprezintă fișierele ca fluxuri: le puteți citi și scrie numai secvenţial.”

„Nu este întotdeauna foarte convenabil. Uneori trebuie să scrieți câteva rânduri în mijlocul unui fișier sau să citiți câteva pagini de text de la sfârșitul unui fișier de mai mulți megaocteți. Nu ar fi foarte eficient să citiți întregul dosar pentru aceste sarcini”.

„ Clasa RandomAccessFile a fost creată pentru a rezolva această problemă. O puteți folosi pentru a scrie oriunde în fișier, pentru a citi din el, precum și pentru a citi și a scrie în fișier în același timp.”

"Ce interesant!"

— Da. De fapt, este destul de convenabil.

„Dar cum citești dintr-o locație arbitrară?”

"Totul este destul de simplu. Imaginați-vă că aveți un editor de text, cum ar fi Notepad, deschis. Are un cursor. Când introduceți ceva, textul este adăugat oriunde se află cursorul. Citirea unui fișier este la fel. Citirea începe de la oriunde se află „cursorul”. Când citiți/scrierea, cursorul se mișcă automat.”

„Uite, ar fi mai bine să-ți arăt un exemplu:”

Citirea unui fișier:
// 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();

„În acest exemplu, aș dori să vă atrag atenția asupra două lucruri:”

„În primul rând, crearea obiectului RandomAccessFile . Al doilea argument este litera r. Aceasta înseamnă că fișierul este deschis pentru citire ( r - read ). Dacă doriți să deschideți un fișier pentru citire și scriere, trebuie să treceți « rw » către constructor, în loc de doar « r »."

„În al doilea rând, uitați-vă la metoda de căutare. Puteți utiliza această metodă pentru a sări în jurul fișierului și a schimba poziția cursorului pentru operația curentă de citire/scriere. Când un fișier este deschis pentru prima dată, cursorul este setat la al 0-lea octet. Sau, mai precis, înaintea octetului zero”.

„Am înțeles bine? Deschidem fișierul, iar cursorul este la început — în poziția 0. Apoi apelăm la căutare și mutam cursorul la al 100-lea octet. Și când apelăm readLine , începe să citească de la al sutelea octet. . Dreapta?"

"Da. Dar vreau să vă atrag atenția asupra faptului că metoda de căutare vă permite să săriți arbitrar în jurul fișierului. De exemplu:"

Citirea unui fișier:
// 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();

„În acest exemplu, citim mai întâi o linie care începe de la al 0-lea octet. Apoi sărim la o sută de octet și citim o linie acolo. Apoi am sărit din nou la al 0-lea octet și am citit o linie. Asta înseamnă că text1 și text3 sunt identice siruri de caractere."

— Ah. Asta face lucrurile mai clare.

„Genial. Atunci iată un alt exemplu:”

Citirea unui fișier:
// 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();

„Aici deschidem fișierul pentru citire și scriere, pasând „ rw ” ( citire/scriere ) către constructor.”

„Apoi scriem „ Este un șir ” în fișier.

„Apoi mutam cursorul la al 8-lea octet (care se întâmplă să fie începutul cuvântului „șir”)”

„Atunci scriem « surpriză !”

„Ca urmare, fișierul conține „ Este o surpriză !”

„Deci, octeții nu sunt inserați în mijlocul fișierului, ci mai degrabă îi înlocuiesc pe cei care erau acolo?”

"Da."

„Dacă mutăm cursorul până la sfârșitul fișierului?”

„Atunci octeții vor fi scrieți până la sfârșit, iar fișierul va deveni mai mare. Așa că ar fi aproape ca și cum ați scrie text într-un editor de text”.

"Hmm. Cred că înțeleg totul. Ați putea oferi o listă completă a metodelor clasei RandomAccessFile ?"

"Sigur. Poftim:"

Metodă Descriere
int read() Citește un octet și îl returnează
int read(byte b[], int off, int len) Citește o matrice de octeți
int read(byte b[]) Citește o matrice de octeți
void readFully(byte b[]) Citește o matrice de octeți și așteaptă adăugarea de noi octeți dacă nu sunt suficienți pentru a umple matricea
int skipBytes(int n) Omite n octeți. Cu alte cuvinte, acest lucru mută cursorul înainte cu n octeți.
void write(int b) Scrie un octet în locația cursorului
void write(byte b[]) Scrie o matrice de octeți în locația cursorului
void write(byte b[], int off, int len) Scrie o matrice de octeți în locația cursorului
long getFilePointer() Returnează numărul octetului către care indică cursorul. Poate varia de la 0 la lungimea fișierului
void seek(long pos) Mută ​​„cursorul” folosit pentru citire/scriere în locația specificată
long length() Returnează lungimea fișierului
void setLength(long newLength) Setează o nouă lungime de fișier. Dacă fișierul era mai mare, se trunchiază; dacă era mai mic, atunci extinde fișierul și completează noul spațiu cu zerouri
void close() Închide fișierul
boolean readBoolean() Citește un boolean din poziția curentă a cursorului în fișier
byte readByte() Citește un octet din poziția curentă a cursorului în fișier
char readChar() Citește un caracter din poziția curentă a cursorului în fișier
int readInt() Citește un int din poziția curentă a cursorului în fișier
long readLong() Citește un lung din poziția curentă a cursorului în fișier
float readFloat() Citește un float din poziția curentă a cursorului în fișier
double readDouble() Citește un dublu din poziția curentă a cursorului în fișier
String readLine() Citește o linie din fișier și o returnează
void writeBoolean(boolean v) Scrie un boolean în fișier (începând de la poziția cursorului)
void writeByte(int v) t Scrie un octet în fișier (începând de la poziția cursorului)
void writeChar(int v) Scrie un caracter în fișier (începând de la poziția cursorului)
void writeInt(int v) Scrie un int în fișier (începând de la poziția cursorului)
void writeLong(long v) Scrie un lung în fișier (începând de la poziția cursorului)
void writeFloat(float v) Scrie un float în fișier (începând de la poziția cursorului)
void writeDouble(double v) Scrie un dublu în fișier (începând de la poziția cursorului)
void writeBytes(String s) Scrie un șir în fișier (începând de la poziția cursorului)
void writeChars(String s) Scrie un șir în fișier (începând de la poziția cursorului)

"Hmm. Deci, nu este nimic nou aici. Cu excepția poate perechile metodei seek()/getFilePointer() și length()/setLength()."

"Da, Amigo. Totul este cam la fel. Dar nu este convenabil?"

"Este convenabil. Mulțumesc, Bilaabo, pentru o lecție interesantă și pentru exemplele pe care mi le-ai dat."

— Mă bucur să ajut, Amigo, prietene!