Liigu peamise sisu juurde

Faili kirjutamine

Sissejuhatus

Faili kirjutamine järgib sama mustrit nagu failist lugemine: Files abiklass pakub lihtsate toimingute jaoks erinevaid meetodeing ning BufferedWriter annab rohkem kontrolli suuremate või keerukamate toimingute jaoks.

Peamine otsus mida faili kirjutamisel langetama peab on, kas kirjutada terve fail üle või lisada uut sisu selle lõppu. Seda käitumist saab määrata läbi StandardOpenOption-i.

Sarnaselt failist lugemisele võivad ka kõik kirjutamistoimingud visata IOException-i. Antud peatükis tutvume vaikselt ka try-with-resources võttega. Viimase kohta saab lugeda ka eraldi peatükist, mille leiate siit.

Kogu sisu korraga kirjutamine

Files.writeString

Files.writeString kirjutab ette antud sõne faili, asendades olemasoleva sisu:

Path path = Path.of("catalogue.txt");

try {
Files.writeString(path, "978-0-13-468599-1,The Pragmatic Programmer,Hunt & Thomas,45.00");
} catch (IOException e) {
System.err.println("Could not write file: " + e.getMessage());
}

Files.write koos ridade järjendiga

Files.write võtab argumendiks List<String> ja kirjutab iga elemendi eraldi reana:

Path path = Path.of("books.txt");
List<String> lines = List.of(
"1,978-0-13-468599-1,The Pragmatic Programmer,Hunt & Thomas,45.00",
"2,978-0-20-163361-0,Clean Code,Robert C. Martin,38.00"
);

try {
Files.write(path, lines);
} catch (IOException e) {
System.err.println("Could not write file: " + e.getMessage());
}

Nii Files.write kui ka Files.writeString kirjutavad faili vaikimisi üle. Kui faili ei eksisteeri, siis see luuakse meetodi poolt ise.

StandardOpenOption

Seda, et fail kirjutatakse vaikimisi üle saab muuta StandardOpenOption kaudu. Nii Files.writeString kui ka Files.write võtavad seda argumendina, lubatud on null või mitu sellist parameetrit:

// Overwrite (default behaviour — this is explicit but equivalent)
Files.writeString(path, content, StandardOpenOption.TRUNCATE_EXISTING);

// Append to existing content instead of replacing it
Files.writeString(path, content, StandardOpenOption.APPEND);

// Create the file if it does not exist; fail if it already does
Files.writeString(path, content, StandardOpenOption.CREATE_NEW);

// Create if absent, otherwise overwrite (most common explicit combination)
Files.writeString(path, content, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);

Kõige sagedamini kasutatavad valikud:

ValikMõju
CREATELoob faili, kui seda ei eksisteeri
CREATE_NEWLoob faili, ebaõnnestub, kui see juba eksisteerib
TRUNCATE_EXISTINGTühjendab fail enne kirjutamist
APPENDKirjutab olemasoleva sisu faili lõppu

Rida-rea haaval kirjutamine BufferedWriter-iga

Sisu järk-järguliseks koostamiseks - või kui kirjutamine toimub tsüklis - on BufferedWriter sobivam kui Files.write korduv kutsumine.

Path path = Path.of("books.txt");

try (BufferedWriter writer = Files.newBufferedWriter(path)) {
writer.write("1,978-0-13-468599-1,The Pragmatic Programmer,Hunt & Thomas,45.00");
writer.newLine();
writer.write("2,978-0-20-163361-0,Clean Code,Robert C. Martin,38.00");
writer.newLine();
} catch (IOException e) {
System.err.println("Could not write file: " + e.getMessage());
}

newLine() kirjutab platvormipõhise reavahetuse märgi, hoides väljundi teisaldatavana.

Uue sisu juurde lisamiseks (mitte üle kirjutamiseks) tuleb juurde lisada StandardOpenOption:

try (BufferedWriter writer = Files.newBufferedWriter(path, StandardOpenOption.APPEND)) {
writer.write("3,978-0-13-235088-4,Refactoring,Martin Fowler,42.00");
writer.newLine();
} catch (IOException e) {
System.err.println("Could not write file: " + e.getMessage());
}
hoiatus

BufferedWriter (ja ka iga teine kirjutaja) ei toeta sisu kustutamist. Kui tekib vajadus näiteks eemaldada konkreetne rida, tuleb kogu fail uuesti kirjutada - lugeda read mällu, jätta kustutatav rida vahele ning kirjutada ülejäänud sisu faili tagasi.

Miks on puhverdamine oluline

Ilma puhverdamiseta põhjustab iga write() kutse eraldi kettakirjutuse. BufferedWriter kogub väljundi esmalt mällu ja kirjutab selle kettale suuremate plokkidena, mis on paljude väikeste kirjutamise puhul oluliselt kiirem.

Puhvrit tühjendatakse automaatselt läbi close() meetodi. Try-with-resources tagab, et close() kutsutaks välja ka siis, kui kirjutamise ajal tekib erind. See omakorda tagab, et puhver tühjendatakse alati ning ei teki andmekadu.