W Javie, podobnie jak i w wielu innych językach programowania, odczyt i zapis do plików realizowany jest na zasadzie strumieni. Koncepcja strumieni może początkowo wydawać się dziwna, ale po jej zrozumieniu można łatwo i efektywnie operować na plikach.
Po otwarciu pliku do odczytu, caÅ‚a jego zawartość jest w strumieniu. Później, odczytujÄ…c z niego dane, ‘wyciÄ…gamy’ je bajt po bajcie ze strumienia, aż strumieÅ„ bÄ™dzie pusty.
Standardowo czytanie i zapis do pliku odbywa się bajt po bajcie. Do odczytu pojedynczych bajtów służy klasa FileInputStream, a do zapisu FileOutputStream. Może na początek mały przykład wyświetlenia na ekran zawartości pliku odczytując jego zawartość bajt po bajcie.
FileInputStream fis = new FileInputStream("pliktestowy.txt");
int bajt = fis.read();
while(bajt != -1){
System.out.print((char)bajt);
bajt = fis.read();
}
Jak można zauważyć w powyższym przykładzie, metoda
PrzykÅ‚ad ten jednak nie zadziaÅ‚a. Dlaczego? Bo operacje na pliku muszÄ… znajdować siÄ™ wewnÄ…trz bloku try{ … } catch(){}. Powyższy przykÅ‚ad można zapisać trochÄ™ Å‚adniej (już wersja dziaÅ‚ajÄ…ca).
try{
FileInputStream fis = new FileInputStream("pliktestowy.txt");
int bajt = 0;
while((bajt = fis.read()) != -1){
System.out.print((char)bajt);
}
} catch (IOException ex){
System.out.println("Błąd przy odczycie danych: "+ex);
}
Klasa FileInputStream ma jeszcze jednÄ… przydatnÄ… metodÄ™: available(), która zwraca ilość bajtów, które można jeszcze odczytać z danego strumienia, a wiÄ™c powyższy przykÅ‚ad można zbudować jeszcze inaczej – czytajÄ…c znaki z pliku jeÅ›li available() jest wiÄ™ksze od zera.
StrumieÅ„ można zamknąć korzystajÄ…c z metody close(), jednak jeÅ›li nie zachodzi potrzeba, żeby zrobić to przed zakoÅ„czeniem dziaÅ‚ania programu (np. jeÅ›li najpierw chcemy plik odczytać, zamknąć go i coÅ› do niego zapisać), to można spokojnie zostawić to zadanie Javie – wszystkie pliki sÄ… zamykane na koÅ„cu wykonywania programu.
Analogicznie realizowany jest zapis do pliku. Klasa FileOutputStream ma metodę write(), która zapisuje bajt (podany w postaci typu int). Trzeba pamiętać, że otwarcie pliku do zapisu spowoduje wyczyszczenie zawartości tego pliku i rozpoczęcie pisania od początku. Jeśli przed otwarciem plik nie istniał, to zostanie utworzony. Poniżej znajduje się przykład zapisu stringa do pliku.
try{
String str = "Próba zapisu";
FileOutputStream fos = new FileOutputStream("plik_zapis.txt");
for(int i = 0; i < str.length(); i++){
fos.write((int)str.charAt(i));
}
} catch(IOException ex){
System.out.println("Błąd operacji na pliku: "+ex);
}
Java, oprócz czytania bajt po bajcie, oferuje także możliwość odczytu całej linii do stringa. Możliwe jest to dzięki tzw. strumieniom buforowanym. Otwarcie takiego strumienia jest trochę bardziej skomplikowane. Najpierw trzeba utworzyć obiekt FileReader, a następnie trzeba stworzyć obiekt BufferedReader, podając mu obiekt FileReader jako parametr. Jak to wygląda w praktyce można zobaczyć poniżej.
FileReader fr = new FileReader("plik_testowy.txt");
BufferedReader bfr = new BufferedReader(fr);
W tym momencie można już korzystać z metody readLine() klasy BufferedReader, która odczytuje całą linijkÄ™ z pliku i zwraca jÄ… w postaci stringa. Po odczytaniu caÅ‚ego pliku zwracana jest wartość null (nie string “null”, tylko wartość null). Czyli wyglÄ…da to tak:
String linia = "";
try{
FileReader fr = new FileReader("plik_testowy.txt");
BufferedReader bfr = new BufferedReader(fr);
while((linia = bfr.readLine()) != null){
System.out.println(linia);
}
} catch( IOException ex ){
System.out.println("Błąd przy operacji na pliku: "+ex);
}
To tyle z zagadnieÅ„ teoretycznych. Może teraz coÅ› z praktyki. Zadanie jest takie: plik “wejscie.txt” zawiera dowolny tekst; podmieÅ„ wszystkie wystÄ…pienia litery ‘a’ na sekwencjÄ™ “>a<" i zapisz dane wyjÅ›ciowe do pliku "wyjscie.txt".
Są dwie metody rozwiązania tego zadania. Można najpierw otworzyć plik wejściowy do odczytu, wyciągnąć z niego dane do stringa, następnie zapisać poprawione dane do pliku wyjściowego. Dane można poprawiać albo przy zapisywaniu danych do stringa, albo już przy wpisywaniu do pliku. Druga metoda, znacznie krótsza, to jednoczesne czytanie z pliku, analizowanie danych (tzn. podmiana 'a' na ">a<") i od razu zapis tych danych do pliku. Poniżej znajduje się gotowe rozwiązanie dla pierwszego przypadku.
// Deklaracje zmiennych
// nazwy plików
String nazwa = "wejscie.txt";
String nazwaOut = "wyjscie.txt";
// string odczytany z pliku
String str = "";
// string do zapisu
String out = "";
// znak pobrany z pliku
int znak = 0;
try{
// nowy strumień wejściowy
FileInputStream wejscie = new FileInputStream(nazwa);
// wczytanie całego pliku do stringu
znak = wejscie.read();
while( znak != -1 ){
str += (char) znak;
znak = wejscie.read();
}
wejscie.close();
}catch(IOException ex){
System.out.println("Blad zwiazany z odczytem z pliku. "+ex);
}
// pętla konwertująca
// sprawdzany jest każdy znak stringu str
for(int i = 0; i<str.length(); i++){
// jeÅ›li bieżący znak to ‘a’
if(str.charAt(i) == ‘a’)
// to wstaw poprawiony string
out += ">a<";
else
// jeśli nie to poprostu wstaw ten znak
out += str.charAt(i);
}
try{
// no i teraz zapis do pliku
FileOutputStream wyjscie = new FileOutputStream(nazwaOut);
for(int i=0; i < out.length(); i++){
wyjscie.write( out.charAt(i) );
}
wyjscie.close();
}catch(IOException ex){
System.out.println("Blad zwiazany z zapisem do pliku. "+ex);
}


Tagi:
Zostaw komentarz