Fișiere cu acces direct

Fișierele cu acces direct, numite și fisiere cu acces aleator (engl.: Random Access File), sunt fișiere la care programatorul poate indica prin program locul (adresa) din fișier de la care începe operația de citire sau de scriere. De regulă, astfel de fișiere pot fi utilizate atât pentru citire, cât și pentru scriere. Pentru ca înregistrările sale să poată fi parcurse într-o ordine arbitrară, fișierul cu acces direct trebuie să fie stocat pe un suport adresabil, cum ar fi discul magnetic, discul optic, memoria RAM sau ROM. În JDK, fișierele cu acces direct sunt instanțe ale clasei RandomAccessFile.

Clasa RandomAccessFile

Clasa java.io.RandomAccessFile este derivată direct din clasa Object, deci nu face parte din niciuna din cele patru ierarhii de fluxuri de intrare/ieșire prezentate anterior, deși face parte, ca și acestea, din pachetul java.io.

Fișierul cu acces direct este privit aici ca un tablou de octeți memorat într-un sistem de fișiere (de regulă în memoria externă). Există un cursor al fișierului (numit în engleză File Pointer), care se comportă ca un indice al acestui tablou.  Valoarea acestui indice (poziția cursorului de fișier relativ la începutul acestuia) poate fi "citită" cu metoda getFilePointer() și  poate fi modificată cu metoda seek(). Orice citire sau scriere se face începând de la poziția pe care se găsește acest cursor. La sfârșitul operației, cursorul se deplasează pe o distanță corespunzatoare cu numarul de octeți care au fost citiți sau scriși efectiv.

Fișierul cu acces direct poate fi deschis în modul read (numai pentru citire), write (numai pentru scriere) sau read/write. În ultimul caz, este posibil să se efectueze atât citiri , cât și scrieri.
 
Scrierea în fișierele cu acces direct se poate face atât în mod text (succesiunea de octeți fiind privită ca o succesiune de caractere), cât și în mod binar, la fel ca în fișierele de date, în care scrierea s-a făcut folosind un DataOutputStream. În consecință, clasa RandomAccessFile oferă atât metode de scriere și de citire de octeți, cât și metode de scriere și de citire pentru toate tipurile de date primitive și pentru șiruri de caractere, la fel ca în cazul claselor DataOutputStream și DataInputStream. Este evident că, la citirea din fișier, trebuie să se respecte modul în care acesta a fost scris.

Dacă la citire se întâlnește sfârșitul de fișier, se generează o excepție de sfârșit de fișier din clasa EOFException (End of File Exception), care este derivată din IOException. În toate celelalte cazuri când nu se poate efectua o operație de citire sau de scriere se genereaza o IOException (Input-Output Exception).


 
Constructori
    public RandomAccessFile(String file, String mode) throws FileNotFoundException - deschide fișierul cu acces direct cu numele file în modul de exploatare mode. Modul poate fi "r" (numai citire) sau "rw" (citire si scriere); dacă este "rw" și fișierul nu există, se creează un fișier nou;
    public RandomAccessFile(File file, String mode) throws IOException - acționează asemănător cu constructorul precedent, dar calea și numele fișierului care se deschide sunt date de instanța file a clasei File.

Metode
    public final FileDescriptor getFD() throws IOException - întoarce descriptorul de fișier;
    public int read() throws IOException - citește din fișier un singur octet (sau întoarce -1 dacă s-a atins sfârșitul fișierului); dacă în fluxul de intrare nu este disponibil nici un octet, se intră în așteptare;
    public int read(byte[] b) throws IOException - citește maximum b.length octeți pe care îi pune în tabloul b; întoarce numărul de octeți citit efectiv;
    public int read(byte[] b, int offset, int length)throws IOException - citește cel mult length octeți pe care îi pune în tabloul b începând de la poziția offset; întoarce numărul de octeți cititi efectiv sau -1;
    public final void readFully(byte[] b) throws IOException - citește exact b.length octeți, pe care îi pune în tabloul b; se blochează dacă nu are sufucienți octeți, iar la întâlnirea sfârșitului de fișier generează o EOFException;
    public final void readFully(byte[] b, int offset, int length) throws IOException - citește exact length octeți, pe care îi depune în tabloul b începând de la poziția offset;
    public int skipBytes(int n) - throws IOException - încearca să sară peste n octeți; întoarce numărul de octeți săriți efectiv;
    public void write(int n) throws IOException - scrie în fișier un singur octet;
    public void write(byte[] b) throws IOException - scrie în fișier conținutul tabloului b;
    public void write(byte[] b, int offset, int length)throws IOException - scrie length octeți din tabloul b începând cu cel de pe poziția offset;
    public long getFilePointer() throws IOException - întoarce poziția cursorului de fișier;
    public void seek(long pos) throws IOException - deplasează cursorul de fișier pe poziția pos;
    public long length() throws IOException - întoarce lungimea fișierului (exprimată în octeti);
    public void setLength(long newLength) throws IOException - setează noua lungime a fișierului;
    public void close() throws IOException - închide fișierul;
    public final boolean readBoolean() throws IOException - citește o valoare booleană (un octet);
    public final byte readByte() throws IOException - citește o valoare primitivă de tip byte;
    public final int readUnsignedByte() throws IOException - citește un singur octet, pe care îl interpretează ca număr întreg fără semn (în intervalul 0 .. 255);
    public final short readShort() throws IOException - citește un întreg scurt (pe doi octeți);
    public final int readUnsignedShort() throws IOException - citește doi octeți, pe care îi interpretează ca un numar întreg scurt fără semn;
    public final char readChar() throws IOException - citește doi octeți, pe care îi interpretează ca un caracter Unicode;
    public final int readInt() throws IOException - citește un int (pe patru octeți);
    public final long readLong() throws IOException - citește un long (pe opt octeți);
    public final float readFloat() throws IOException - citește un float (pe patru octeți);
    public final double readDouble()throws IOException - citește un double (pe opt octeți);
    public final String readLine() throws IOException - citește din fișier o linie de text, adică un șir de caractere încheiat prin marcajul de sfârșit de linie ('\n' pe platforme Unix sau '\r' '\n' pe platforme Microsoft);
    public final String readUTF() throws IOException - citește un șir de caractere în format UTF-8;
    public final void writeBoolean(boolean b) throws IOException - scrie o valoare booleană (pe un octet);
    public final void writeByte(byte v) throws IOException - scrie o valoare de tip byte;
    public final void writeShort(short v) throws IOException - scrie un short (pe doi octeți);
    public final void writeChar(char v) throws IOException - scrie un caracter Unicode (pe doi octeți);
    public final void writeInt(int v) throws IOException - scrie un int (pe patru octeți);
    public final void writeLong(long v) throws IOException - scrie un long (pe opt octeți);
    public final void writeFloat(float v) throws IOException - scrie un float (pe patru octeți);
    public final void writeDouble(double v) throws IOException - scrie un double (pe opt octeți);
    public final void writeBytes(String s) throws IOException - scrie un șir de caractere convertit în secvență de octeți (fiecare caracter este reprezentat pe un octet, eliminându-se octetul superior al codului caracterului);
    public final void writeChars(String s) throws IOException - scrie un șir de caractere Unicode;
    public final void writeUTF(String s) throws IOException - scrie un șir de caractere în format UTF-8.

Exemplu
În fișierul AccesDirect.java este dat un exemplu de aplicație, în care se creează și se utilizează un fișier cu acces direct, cu numele "Proba.fad". Prima dată fișierul este deschis în mod "rw" (read/write). Se fac două serii de scrieri de date, care apoi sunt citite și afișate. Înainte de fiecare citire a unei serii de date se poziționează cursorul de fișier la începutul seriei respective, iar datele se citesc respectând modul în care acestea au fost scrise. Fișierul este apoi închis și redeschis în mod "r" ("read"), după care se poziționează cursorul la începutul celei de a doua serii de date, care este citită și afișată.



© Copyright 2000 - Severin BUMBARU, Universitatea "Dunărea de Jos" din Galați