"Cześć, Amigo!"
„Cześć, Bilaabo! Jak tam życie?”
"Świetnie. Wczoraj próbowałem pozbyć się kilku pasożytów, ale jak dotąd nie odniosłem większego sukcesu. A potem znowu musiałem spędzić noc w śmietniku."
"Więc... czy nadal wszystko jest w porządku?"
"Moglbys to powiedziec."
- Dobrze. Więc co masz dzisiaj dla mnie?
„Dzisiaj opowiem o klasie RandomAccessFile ”.
„Rzecz w tym, że FileInputStream i FileOutputStream reprezentują pliki jako strumienie: można je tylko odczytywać i zapisywać sekwencyjnie”.
„Nie zawsze jest to bardzo wygodne. Czasami trzeba napisać kilka wierszy w środku pliku lub przeczytać kilka stron tekstu z końca wielomegabajtowego pliku. Czytanie nie byłoby zbyt wydajne cały plik dla tych zadań”.
„ Klasa RandomAccessFile została stworzona, aby rozwiązać ten problem. Możesz jej użyć do zapisu w dowolnym miejscu pliku, odczytu z niego, a także jednoczesnego odczytu i zapisu do pliku”.
"Jakie interesujące!"
„Tak. Właściwie to całkiem wygodne”.
„Ale jak czytać z dowolnego miejsca?”
„To wszystko jest całkiem proste. Wyobraź sobie, że masz otwarty edytor tekstu, taki jak Notatnik. Ma on kursor. Kiedy coś wpisujesz, tekst jest dodawany w miejscu, w którym znajduje się kursor. Odczyt pliku jest taki sam. gdziekolwiek jest „kursor”. Podczas czytania/zapisywania kursor porusza się automatycznie”.
„Tutaj lepiej będzie pokazać ci przykład:”
// 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();
„W tym przykładzie chciałbym zwrócić uwagę na dwie rzeczy:”
"Najpierw utworzenie obiektu RandomAccessFile . Drugim argumentem jest litera r. Oznacza to, że plik jest otwarty do odczytu ( r - read ). Jeśli chcesz otworzyć plik do odczytu i zapisu, musisz przekazać « rw » do konstruktora, zamiast po prostu « r »."
„Po drugie, spójrz na metodę wyszukiwania. Możesz użyć tej metody, aby przeskakiwać po pliku i zmieniać pozycję kursora dla bieżącej operacji odczytu/zapisu. Kiedy plik jest otwierany po raz pierwszy, kursor jest ustawiany na bajcie 0. Lub, dokładniej, przed bajtem zerowym”.
„Czy dobrze zrozumiałem? Otwieramy plik, a kursor jest na samym początku — na pozycji 0. Następnie wywołujemy seek i przesuwamy kursor do setnego bajtu. A kiedy wywołujemy readLine , zaczyna czytać od setnego bajtu . Prawidłowy?"
„Tak. Ale chcę zwrócić twoją uwagę na fakt, że metoda seek pozwala na dowolne przeskakiwanie po pliku. Na przykład:”
// 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();
„W tym przykładzie najpierw czytamy wiersz zaczynający się od bajtu 0. Następnie przeskakujemy do bajtu setnego i czytamy tam wiersz. Następnie ponownie przeskakujemy do bajtu 0 i czytamy wiersz. Oznacza to, że tekst1 i tekst3 są identyczne smyczki."
„Ach. To czyni sprawę jaśniejszą”.
„Świetnie. Oto kolejny przykład:”
// 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();
„Tutaj otwieramy plik do odczytu i zapisu, przekazując « rw » ( odczyt/zapis ) do konstruktora”.
„Następnie piszemy « It is a string » do pliku.
„Następnie przesuwamy kursor do ósmego bajtu (który jest początkiem słowa„ łańcuch ”)”
„Wtedy piszemy « niespodzianka !»”
„W rezultacie plik zawiera « To niespodzianka !»
„Więc bajty nie są wstawiane w środku pliku, ale raczej zastępują te, które tam były?”
"Tak."
„Co jeśli przesuniemy kursor na sam koniec pliku?”
„Wtedy bajty zostaną zapisane do końca, a plik powiększy się. Byłoby to prawie jak pisanie tekstu w edytorze tekstu”.
„Hmm. Chyba wszystko rozumiem. Czy mógłbyś podać pełną listę metod klasy RandomAccessFile ?”
"Jasne, prosze:"
metoda | Opis |
---|---|
int read() |
Odczytuje jeden bajt i zwraca go |
int read(byte b[], int off, int len) |
Odczytuje tablicę bajtów |
int read(byte b[]) |
Odczytuje tablicę bajtów |
void readFully(byte b[]) |
Odczytuje tablicę bajtów i czeka na dodanie nowych bajtów, jeśli nie ma ich wystarczająco dużo, aby wypełnić tablicę |
int skipBytes(int n) |
Pomiń n bajtów. Innymi słowy, przesuwa kursor o n bajtów do przodu. |
void write(int b) |
Zapisuje jeden bajt w lokalizacji kursora |
void write(byte b[]) |
Zapisuje tablicę bajtów w lokalizacji kursora |
void write(byte b[], int off, int len) |
Zapisuje tablicę bajtów w lokalizacji kursora |
long getFilePointer() |
Zwraca numer bajtu, na który wskazuje kursor. Może wynosić od 0 do długości pliku |
void seek(long pos) |
Przesuwa «kursor» używany do odczytu/zapisu w określone miejsce |
long length() |
Zwraca długość pliku |
void setLength(long newLength) |
Ustawia nową długość pliku. Jeśli plik był większy, zostanie obcięty; jeśli był mniejszy, to rozszerza plik i wypełnia nowe miejsce zerami |
void close() |
Zamyka plik |
boolean readBoolean() |
Odczytuje wartość logiczną z bieżącej pozycji kursora w pliku |
byte readByte() |
Odczytuje bajt z bieżącej pozycji kursora w pliku |
char readChar() |
Odczytuje znak z bieżącej pozycji kursora w pliku |
int readInt() |
Odczytuje int z bieżącej pozycji kursora w pliku |
long readLong() |
Odczytuje długą z bieżącej pozycji kursora w pliku |
float readFloat() |
Odczytuje liczbę zmiennoprzecinkową z bieżącej pozycji kursora w pliku |
double readDouble() |
Odczytuje podwójne z bieżącej pozycji kursora w pliku |
String readLine() |
Odczytuje wiersz z pliku i zwraca go |
void writeBoolean(boolean v) |
Zapisuje wartość logiczną do pliku (zaczynając od pozycji kursora) |
void writeByte(int v) t |
Zapisuje bajt do pliku (zaczynając od pozycji kursora) |
void writeChar(int v) |
Zapisuje znak do pliku (zaczynając od pozycji kursora) |
void writeInt(int v) |
Zapisuje int do pliku (zaczynając od pozycji kursora) |
void writeLong(long v) |
Zapisuje long do pliku (zaczynając od pozycji kursora) |
void writeFloat(float v) |
Zapisuje float do pliku (zaczynając od pozycji kursora) |
void writeDouble(double v) |
Zapisuje double do pliku (zaczynając od pozycji kursora) |
void writeBytes(String s) |
Zapisuje String do pliku (zaczynając od pozycji kursora) |
void writeChars(String s) |
Zapisuje String do pliku (zaczynając od pozycji kursora) |
„Hmm. Więc nie ma tu nic nowego. Może z wyjątkiem par metod seek()/getFilePointer() i length()/setLength()”.
„Tak, Amigo. Wszystko jest mniej więcej takie samo. Ale czy to nie wygodne?”
„To wygodne. Dziękuję, Bilaabo, za interesującą lekcję i przykłady, które mi dałeś”.
"Cieszę się, że mogłem pomóc, Amigo, mój przyjacielu!"
GO TO FULL VERSION