"Hej, Amigo!"

"Hej Bilaabo! Hur är livet?"

"Jättebra. Igår försökte jag bli av med några parasiter, men hittills har jag inte haft så mycket framgång. Och sedan fick jag tillbringa natten i soptunnan igen."

"Så... är allt fortfarande bra?"

"Du skulle kunna säga det."

"Bra. Så vad har du för mig idag?"

"Idag ska jag berätta om klassen RandomAccessFile ."

RandomAccessFile, etc. - 1

"Saken är att FileInputStream och FileOutputStream representerar filer som strömmar: du kan bara läsa och skriva till dem sekventiellt."

"Det är inte alltid så bekvämt. Ibland behöver du skriva ett par rader i mitten av en fil, eller läsa ett par sidor text från slutet av en multimegabyte fil. Det skulle inte vara särskilt effektivt att läsa hela filen för dessa uppgifter."

" Klassen RandomAccessFile skapades för att lösa det här problemet. Du kan använda den för att skriva var som helst i filen, läsa från den, samt läsa och skriva till filen samtidigt."

"Så intressant!"

"Japp. Det är faktiskt ganska bekvämt."

"Men hur läser man från en godtycklig plats?"

"Det hela är ganska enkelt. Föreställ dig att du har en textredigerare, till exempel Anteckningar, öppen. Den har en markör. När du skriver något läggs texten till varhelst markören är. Att läsa en fil är densamma. Läsningen börjar från kl. varhelst 'markören' är. När du läser/skriver flyttas markören automatiskt."

"Här är det bättre att visa dig ett exempel:"

Läsa en fil:
// 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();

"I det här exemplet skulle jag vilja fästa din uppmärksamhet på två saker:"

"Först, skapandet av RandomAccessFile- objektet. Det andra argumentet är bokstaven r. Det betyder att filen öppnas för läsning ( r - read ). Om du vill öppna en fil för läsning och skrivning måste du klara « rw » till konstruktören, istället för bara « r ».

"För det andra, titta på sökmetoden. Du kan använda den här metoden för att hoppa runt filen och ändra markörpositionen för den aktuella läs-/skrivoperationen. När en fil först öppnas ställs markören in på den 0:e byten. Eller, mer exakt, före nollbyten."

"Förstod jag rätt? Vi öppnar filen, och markören är i början - vid position 0. Sedan anropar vi sök och flyttar markören till den 100:e byten. Och när vi anropar readLine börjar den läsa från den hundrade byten . Höger?"

"Ja. Men jag vill göra dig uppmärksam på att sökmetoden låter dig hoppa godtyckligt runt filen. Till exempel:"

Läsa en fil:
// 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();

"I det här exemplet läser vi först en rad som börjar på den 0:e byten. Sedan hoppar vi till den hundrade byten och läser en rad där. Sedan hoppade vi till den 0:e byten igen och läser en rad. Det betyder att text1 och text3 är identiska strängar."

"Ah. Det gör saken tydligare."

"Bra. Här är ett annat exempel:"

Läsa en fil:
// 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();

"Här öppnar vi filen för läsning och skrivning genom att skicka « rw » ( läs/skriv ) till konstruktorn."

"Då skriver vi " Det är en sträng " till filen.

"Då flyttar vi markören till den 8:e byten (som råkar vara början på ordet 'sträng')"

"Då skriver vi " överraskning !"

"Som ett resultat innehåller filen « Det är en överraskning !»"

"Så, bytes infogas inte i mitten av filen, utan de ersätter snarare de som fanns där?"

"Japp."

"Vad händer om vi flyttar markören till slutet av filen?"

"Då kommer byten att skrivas till slutet, och filen blir större. Så det skulle nästan vara som att skriva text i en textredigerare."

"Hmm. Jag tror att jag förstår allt. Kan du ge en komplett lista över RandomAccessFile -klassens metoder?"

"Javisst här får du:"

Metod Beskrivning
int read() Läser en byte och returnerar den
int read(byte b[], int off, int len) Läser en array av byte
int read(byte b[]) Läser en array av byte
void readFully(byte b[]) Läser en array med byte och väntar på att nya byte läggs till om det inte finns tillräckligt med dem för att fylla arrayen
int skipBytes(int n) Hoppa över n byte. Med andra ord, detta flyttar markören framåt n byte.
void write(int b) Skriver en byte till markörens plats
void write(byte b[]) Skriver en array av byte till markörens plats
void write(byte b[], int off, int len) Skriver en array av byte till markörens plats
long getFilePointer() Returnerar numret på den byte som markören pekar på. Det kan variera från 0 till fillängden
void seek(long pos) Flyttar «markören» som används för att läsa/skriva till den angivna platsen
long length() Returnerar fillängden
void setLength(long newLength) Ställer in en ny fillängd. Om filen var större, trunkeras den; om den var mindre expanderar den filen och fyller i det nya utrymmet med nollor
void close() Stänger filen
boolean readBoolean() Läser ett booleskt värde från markörens nuvarande position i filen
byte readByte() Läser en byte från markörens nuvarande position i filen
char readChar() Läser ett tecken från markörens aktuella position i filen
int readInt() Läser en int från markörens aktuella position i filen
long readLong() Läser en lång från markörens nuvarande position i filen
float readFloat() Läser ett flyt från markörens aktuella position i filen
double readDouble() Läser en dubbel från markörens nuvarande position i filen
String readLine() Läser en rad från filen och returnerar den
void writeBoolean(boolean v) Skriver ett booleskt värde till filen (med början från markörens position)
void writeByte(int v) t Skriver en byte till filen (med början från markörens position)
void writeChar(int v) Skriver ett tecken till filen (med början från markörens position)
void writeInt(int v) Skriver en int till filen (med början från markörens position)
void writeLong(long v) Skriver en lång till filen (med början från markörens position)
void writeFloat(float v) Skriver ett flyt till filen (med början från markörens position)
void writeDouble(double v) Skriver en dubbel till filen (med början från markörens position)
void writeBytes(String s) Skriver en sträng till filen (med början från markörens position)
void writeChars(String s) Skriver en sträng till filen (med början från markörens position)

"Hmm. Så, det är inget nytt här. Förutom kanske metodparen seek()/getFilePointer() och length()/setLength()."

"Ja, Amigo. Allt är ungefär likadant. Men är det inte bekvämt?"

"Det är bekvämt. Tack, Bilaabo, för en intressant lektion och för de exempel du gav mig."

"Glad att hjälpa, Amigo, min vän!"