BufferedReader, BufferedWriter a try with resources

BufferedReader načítatá textová data do paměti (buffer) a umožňuje efektivnější čtení po řádcích. Obdobně to platí pro BufferedWriter, který zase zapisuje po blocích a ne znak po znaku. Blok try-with-resources zjednodušuje práci se zdroji a zpracování výjimek a je vhodný například právě pro načítání ze a zápis do souborů. Zdroje (zde to představuje streamy pro čtení a zápis) definované v části try budou po skončení bloku (a nebo v případě vyhození výjimky) korektně uzavřeny.

V následujícím příkladu čtu ze souboru input.txt, který je uložen v kódování Windows-1250 a hned načtené řádky ukládám do souboru output.txt. Pro ukládání používám kódování UTF-8. Soubor input.txt se nachází v adresáři s projektem (v adresáři, kde je i složka src).

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;

public class App {

	public static void main(String[] args) throws UnsupportedEncodingException, FileNotFoundException, IOException {
		
		try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt"), "Cp1250"))) {
			try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("output.txt"), "UTF-8"))) {
				
				String line = null;
				while ((line = br.readLine()) != null) {
					System.out.println(line);
					bw.write(line);
					bw.newLine();
				}
			}
		}
	}
}

Pravděpodobně jste si všimli, pro někoho trochu divoké, konstrukce BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt"), "Cp1250")). Při práci se streamy se jednotlivé streamy zabalují do sebe a tím se výslednému streamu přidává funkcionalita. V tomto příkladu FileInputStream dokáže číst ze souboru ale pouze ve výchozím kódování. Pokud je kódování jiné, výstup vypadá třeba takto:

�lu�ou�k� k�� �p�l ��belsk� �dy.

Pokud ale tento stream zabalíme do InputStreamReader, může určit i kódování souboru. Stále ale načítáme znaky jednotlivě, což není příliš efektivní a určitě by bylo lepší je načítat po blocí (po řádcích). V tom případě použijeme BufferedReader, kterému předáme jako parametr InputStreamReader. Obdobné je i pro zapisování BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("output.txt"), "UTF-8")). Zde se ale zase používají streamy obsahující v názvu Writer nebo Output.

Samotné čtení a zápis se děje v této části:

String line = null;
while ((line = br.readLine()) != null) {
	System.out.println(line);
	bw.write(line);
	bw.newLine();
}

Do proměnné line postupně načítáme řádky. V případě že BufferedReader#readLine() vrátí null znamená to, že jsem na konci souboru. Pro zápis se používá metoda BufferedWriter#write(). Pokud chceme zapsat konec rádky, používá se metoda BufferedWriter#newLine(). Po skončení práce se streamy by se na nich měla zavolat metoda close(). To platí i v případě, že máme otevřený stream a dojde k výjimce. Používám ale blok try-with-resources takže to udělá za mě.


Zdroje:

Napsat komentář