Java BufferedReader: Jak odczytać plik z przykładem

⚡ Inteligentne podsumowanie

Java BufferedReader odczytuje tekst z strumienia wejściowego poprzez buforowanie znaków, co sprawia, że ​​czytanie pliku wiersz po wierszu jest szybkie i proste.ping FileReader w środku BufferedReader i toaletaping na readLine dopóki nie zwróci wartości null drukuje cały plik.

  • ???? Główny cel: BufferedReader obejmuje każdego Readera, którego operacje odczytu są kosztowne, zmniejszając liczbę pojedynczych odczytów w stosunku do strumienia bazowego.
  • 🔁 Pętla odczytu: readLine zwraca jedną linię na wywołanie i null na końcu pliku, więc pętla while na tym wyniku przechodzi przez cały plik.
  • 🧱 Ścieżki ucieczki: A Windows ścieżka wewnątrz Java ciąg wymaga podwójnego ukośnika odwrotnego, w przeciwnym wypadku kompilator odrzuci nieprawidłową sekwencję ucieczki.
  • ♻️ Wydanie zasobu: Zamknięcie czytnika powoduje zwolnienie uchwytu pliku bazowego; polecenie try-with-resources powoduje automatyczne zamknięcie pliku.
  • ⌨️. Wprowadzanie danych z konsoli: Owińping System.in w InputStreamReader pozwala tej samej klasie odczytywać dane wejściowe z klawiatury, a nie z pliku.
  • ⚖️. Kontrast skanera: BufferedReader jest szybszy i zwraca surowe linie, podczas gdy Scanner bezpośrednio analizuje tokeny i typy prymitywne.
  • 🔤 Ostrzeżenie dotyczące zestawu znaków: FileReader stosuje domyślny zestaw znaków, więc wyraźne określenie jednego z nich pozwala uniknąć zniekształconych znaków na różnych komputerach.

BufferedReader w Java

Jak odczytać plik w Java?

Java Zapewnia kilka mechanizmów odczytu z pliku. Najbardziej użytecznym pakietem do tego celu jest java.io, którego mięśnie brzuchatract Reader Klasa definiuje odczyt strumienia znaków. java.io.BufferedReader jest konkretną podklasą używaną do efektywnego czytania na podstawie wierszy.

Czym jest BufferedReader w Java?

BufferedReader jest Java Klasa, która odczytuje tekst ze strumienia wejściowego, takiego jak plik, poprzez buforowanie znaków, co pozwala na efektywny odczyt znaków, tablic i wierszy. Bez buforowania każde żądanie odczytu obiektu Reader wyzwala odpowiadające mu żądanie odczytu z bazowego strumienia znaków lub bajtów.

Dlatego zaleca się owinięcie BufferedReader wokół każdego Czytelnika, którego read() operacje mogą być kosztowne, takie jak FileReader oraz InputStreamReaderTypowe zastosowanie polega na przekazaniu ścieżki do pliku czytnikowi w następujący sposób:

// Note the doubled backslash: a single \ starts an escape sequence
objReader = new BufferedReader(new FileReader("D:\\DukesDiary.txt"));

Spowoduje to załadowanie pliku do objReaderNastępnie iterujesz zawartość pliku i drukujesz każdy wiersz. Pętla while w poniższym kodzie odczytuje plik, aż dotrze do jego końca.

while ((strCurrentLine = objReader.readLine()) != null) {
    System.out.println(strCurrentLine);
}

strCurrentLine utrzymuje obecną linię i objReader.readLine() Zwraca ciąg znaków. Pętla kontynuuje iterację, dopóki zwrócona wartość nie jest nullem, i zatrzymuje się na pierwszym nullu, który sygnalizuje koniec pliku.

BufferPrzykład edReadera

Poniższy kod jest kompletny Java BufferPrzykład edReadera:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ReadFileExample {

    public static void main(String[] args) {
        BufferedReader objReader = null;
        try {
            String strCurrentLine;

            objReader = new BufferedReader(new FileReader("D:\\DukesDiary.txt"));

            while ((strCurrentLine = objReader.readLine()) != null) {
                System.out.println(strCurrentLine);
            }

        } catch (IOException e) {
            e.printStackTrace();

        } finally {
            try {
                if (objReader != null)
                    objReader.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

Uwaga: finally blok ma znaczenie. Gwarantuje, że objReader.close() działa niezależnie od tego, czy wyjątek został wyrzucony, co zwalnia uchwyt pliku bazowego i zachowuje zarządzanie pamięcią przewidywalne. Zagnieżdżona próba wewnątrz finally jest wymagane, ponieważ close() sam deklaruje IOException.

BufferPrzykład edReadera JDK7

Od wersji JDK 7 funkcja try-with-resources usuwa finally całkowicie zablokować. Każdy zasób zadeklarowany w nawiasach try Instrukcja jest zamykana automatycznie po wyjściu z bloku, w odwrotnej kolejności tworzenia, nawet jeśli wystąpi wyjątek:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ReadFileExample_jdk7 {

    private static final String FILENAME = "D:\\DukesDiary.txt";

    public static void main(String[] args) {

        try (BufferedReader br = new BufferedReader(new FileReader(FILENAME))) {

            String strCurrentLine;

            while ((strCurrentLine = br.readLine()) != null) {
                System.out.println(strCurrentLine);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Ta wersja jest krótsza i bezpieczniejsza, dlatego jest to forma preferowana w nowym kodzie. Odczyt pliku to tylko jedno z zastosowań tej klasy; w następnej sekcji porównano ją z alternatywą, po którą sięga większość początkujących.

BufferedReader kontra skaner: którego użyć

Obie klasy czytają tekst, a początkujący często wybierają jedną arbitralnie. Rozwiązują różne problemy, a błędny wybór skutkuje albo nieporadnym ręcznym analizowaniem składniowym, albo niską przepustowością, gdy dane wejściowe rozrosną się do tysięcy wierszy. Poniższa tabela zestawia je ze sobą.

WYGLĄD BufferedReader Scanner
Zwroty Całe linie jako ciąg znaków Przetworzone tokeny i prymitywy
Analiza wbudowana Nie — dzielisz się lub konwertujesz sam Tak — nextInt, nextDouble, następna linia
Domyślny bufor znaki 8192 znaki 1024
Prędkość dużych plików Szybciej Wolniej, ze względu na tokenizację wyrażeń regularnych
Bezpieczeństwo gwintu Syncchronizowany Niezsynchronizowane
Najlepszy dla Odczytywanie dużych plików linia po linii Małe interaktywne dane wejściowe wymagające wpisanych wartości

Dodaj BufferedReader, gdy celem jest szybkie poruszanie się po pliku i samodzielne przetwarzanie tekstu, oraz Scanner, gdy chcesz uzyskać wartości wpisane bez pisania kodu konwersji. Dzielenie każdego zwróconego wiersza za pomocą Metoda podziału ciągu daje BufferedReader oferuje większość wygody skanera przy wyższej prędkości.

Jak czytać dane wejściowe z konsoli BufferedReader

Ta sama klasa odczytuje dane wprowadzane z klawiatury, co jest przydatne w przypadku małych programów wiersza poleceń i wprowadzania danych w celu ułatwienia kodowania. System.in jest strumieniem bajtów, więc nie można go przekazać BufferedReader bezpośrednio. InputStreamReader łączy bajty ze znakami i BufferedReader dodaje następnie efektywne czytanie wierszy na podstawie tego mostu.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ReadConsoleExample {

    public static void main(String[] args) throws IOException {

        // Bridge the System.in byte stream to a character stream
        try (BufferedReader reader =
                new BufferedReader(new InputStreamReader(System.in))) {

            System.out.print("Enter your name: ");
            String name = reader.readLine();

            System.out.print("Enter your age: ");
            // readLine always returns text, so convert it explicitly
            int age = Integer.parseInt(reader.readLine().trim());

            System.out.println("Hello " + name + ", age " + age);
        }
    }
}

Warto pamiętać o trzech szczegółach. Po pierwsze, readLine() zawsze zwraca String, więc dane numeryczne muszą zostać przekonwertowane Integer.parseInt lub podobne, a wpis niebędący liczbą powoduje NumberFormatException — zawiń konwersję, jeśli dane wejściowe są niewiarygodne. Po drugie, wywołanie .trim() usuwa końcowy znak powrotu karetki, który Windows Konsole dołączają, co jest częstą przyczyną błędów analizy składniowej. Po trzecie, unikaj zamykania czytnika w trybie „zawiniętym” System.in jeśli program będzie potrzebował później danych wejściowych z konsoli, ponieważ zamknięcie opakowania powoduje trwałe zamknięcie strumienia bazowego dla tego procesu.

W przypadku programów odczytujących wiele wartości odczytanie jednego wiersza i podzielenie go jest znacznie szybsze niż wywołanie readLine() wielokrotnie, ponieważ każde wywołanie trafia do systemu operacyjnego dopiero po opróżnieniu bufora. To główny powód, dla którego programiści preferują BufferedReader przez skaner do wprowadzania danych masowych.

Nawet jeśli kod jest poprawny, kilka błędów pojawia się wielokrotnie.

wspólny BufferBłędy edReadera i jak je naprawić

Większość BufferAwarie edReadera wynikają ze ścieżek plików, obsługi zasobów lub kodowania znaków, a nie z samej pętli odczytu. Każdy błąd poniżej zawiera nazwę wyjątku i sposób jego rozwiązania.

  • Nielegalny znak ucieczki: ścieżka używa pojedynczego ukośnika odwrotnego, jak w "D:\DukesDiary.txt". Double jej "D:\\DukesDiary.txt"lub użyj ukośnika, który Java akceptuje na Windows.
  • Wyjątek FileNotFoundException: ścieżka jest względna do katalogu roboczego, a nie do pliku źródłowego. Drukuj new File(name).getAbsolutePath() zobaczyć gdzie Java faktycznie patrzy.
  • NullPointerException przy pierwszym odczycie: Czytnik nigdy nie został przypisany, ponieważ konstruktor rzucił wyjątek i został on połknięty. Sprawdź Obsługa wyjątków przed pętlą.
  • Zniekształcone znaki lub znaki zapytania: plik jest w formacie UTF-8, ale FileReader Zastosowano domyślny zestaw znaków platformy. Przekaż jawnie zestaw znaków, na przykład new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8).
  • Transmisja zamknięta: Czytnik został zamknięty w pętli lub ponownie użyty po zakończeniu operacji „wypróbuj z zasobami”. Otwórz nowy czytnik dla każdego przejścia przez plik.

FAQ

Tak. Drugi argument konstruktora ustawia bufor w znakach, na przykład new BufferedReader(reader, 16384)Domyślna wartość 8192 jest odpowiednia dla większości plików; jej zwiększenie pomaga jedynie w przypadku bardzo dużych, sekwencyjnych odczytów.

W przypadku małych plików tak — zwraca listę wierszy w jednym wywołaniu. W przypadku dużych plików preferuj Files.newBufferedReader or Files.linesponieważ readAllLines przechowuje cały plik w pamięci na raz.

Tak. AI Asystenci przepisują oczyszczanie bloku Finally na try-with-resources i sugerują odpowiedniki NIO. Następnie zweryfikuj zestaw znaków i zachowanie wyjątków, ponieważ generowane konwersje często pomijają jawne kodowanie.

Sztuczna inteligencja odczytuje stos trace i identyfikuje, czy przyczyną jest niewłaściwy katalog roboczy, brak uprawnień, czy niezgodność kodowania. Skraca to diagnozę, choć poprawka nadal wymaga weryfikacji z rzeczywistym plikiem.

Nie. Funkcja readLine usuwa terminator wiersza, więc zwrócony ciąg znaków nie zawiera końcowego znaku nowej linii. Pusty wiersz w pliku zwraca zatem pusty ciąg znaków zamiast wartości null.

Podsumuj ten post następująco: