Skaner kontra buforowany czytnik


284

O ile wiem, dwie najczęstsze metody odczytu danych znakowych z pliku w Javie to Scannerlub BufferedReader. Wiem również, że BufferedReaderodczytuje pliki skutecznie, używając bufora, aby uniknąć operacji na dysku fizycznym.

Moje pytania to:

  • Czy Scannerdziała równie dobrze BufferedReader?
  • Dlaczego miałbyś wybierać Scannerna BufferedReaderodwrót?

1
Generalnie używam również skanera do odczytu ze standardowego wejścia („Skaner w = nowy skaner (System.in)” jest o wiele czystszy). Nie jestem pewien, czy to faktycznie jest mniej wydajne, ale ponieważ odczytywanie ze standardowego wejścia jest blokowane, nie mogę sobie wyobrazić, że wydajność skanera byłaby problemem.
dimo414

Odpowiedzi:


201

Scannersłuży do analizowania tokenów z zawartości strumienia, podczas gdy BufferedReaderpo prostu odczytuje strumień i nie wykonuje żadnej specjalnej analizy.

W rzeczywistości można przejść BufferedReaderdo scannerjako źródło znaków do analizowania.


55
BufferedReader jest zsynchronizowany, a skaner nie, więc decyzja należy do Ciebie.
Reuben

1
Wiem, że ten temat jest stary, ale miałem różne wyniki wśród systemów operacyjnych korzystających z BufferedReader, gdy próbowałem zamazać zawartość ze strumieni dostarczanych przez proces (tj. Przechwytywanie danych wyjściowych polecenia zewnętrznego). Gdy zmieniłem kod, aby zamiast tego używać skanera, jak zauważono w osobnej odpowiedzi , wszystko zaczęło działać konsekwentnie i zgodnie z oczekiwaniami.
ewh

@Reuben Ale Scannerostatecznie zależy od czegoś innego, co może być zsynchronizowane.
Markiz Lorne

189

W najnowszej wersji / kompilacji JDK6 (b27), Scannerma mniejszy bufor ( 1024 znaki ) w przeciwieństwie do BufferedReader( 8192 znaków ), ale jest więcej niż wystarczający.

Jeśli chodzi o wybór, użyj Scannerjeśli chcesz przeanalizować plik, użyj BufferedReaderjeśli chcesz odczytać plik linia po linii. Zobacz także tekst wprowadzający ich wcześniej wymienionych dokumentacji API.

  • Parsowanie = interpretacja podanych danych wejściowych jako tokenów (części). Jest w stanie zwrócić ci określone części bezpośrednio jako int, ciąg, dziesiętny, itp. Zobacz także wszystkie te nextXxx()metody w Scannerklasie.
  • Czytanie = głupie przesyłanie strumieniowe. Ciągle zwraca ci wszystkie postacie, które z kolei musisz ręcznie sprawdzić, czy chcesz dopasować lub skomponować coś przydatnego. Ale jeśli i tak nie musisz tego robić, czytanie jest wystarczające.

1
Niezłe. Dzięki za wskazówkę dotyczącą bufora. Szukałem tego przez cały czas, ponieważ natywne odczyty są niezwykle drogie.
Achow

7
@Asif: parsing = interpretując dane wejściowe jako tokeny (części). Jest w stanie zwrócić ci określone części bezpośrednio jako int, ciąg, dziesiętny itp. Zobacz także wszystkie metody nextXxx () w klasie Scanner. Czytanie = głupie przesyłanie strumieniowe. Ciągle zwraca ci wszystkie postacie, które z kolei musisz ręcznie sprawdzić, czy chcesz dopasować lub skomponować coś przydatnego. Ale jeśli i tak nie musisz tego robić, czytanie jest wystarczające.
BalusC,

@BalusC Ok już używane, readInt();readFloat (); itd. Teraz rozumiem, co to znaczy parsowanie. i BalusC, czy możesz dać mi mało czasu tylko 10 minut na czacie, chcę zapytać trochę o buforowane, jak to działa.
Asif Mushtaq,

Co zawijam BufferedReaderw konstruktorze skanera? czy to dobry pomysł?
vivek

1
ScannerBufor zostanie rozszerzony w razie potrzeby do dopasowania wzorca. Więc jeśli chcesz większego bufora, musisz tylko wywołać, np. findWithinHorizon("\\z", 8192)Na nim, a potem użyje bufora o pojemności 8192znaków (lub całego pliku, jeśli jest mniejszy).
Holger

77

Zobacz ten link , stąd zacytowano:

BufferedReader to prosta klasa przeznaczona do efektywnego odczytu ze strumienia podrzędnego. Zasadniczo każde żądanie odczytu złożone z czytnika, takiego jak FileReader, powoduje wysłanie odpowiedniego żądania odczytu do strumienia bazowego. Każde wywołanie read () lub readLine () może spowodować odczyt bajtów z pliku, konwersję na znaki, a następnie zwrócenie, co może być bardzo nieefektywne. Wydajność ulega znacznej poprawie, jeśli czytnik jest wypaczony w buforze buforowym.

BufferedReader jest zsynchronizowany, więc operacje odczytu na BufferedReader można bezpiecznie wykonywać z wielu wątków.

Z drugiej strony skaner ma o wiele więcej sera; może zrobić wszystko, co może zrobić buforowany czytnik i przy tym samym poziomie wydajności. Jednak dodatkowo skaner może analizować strumień źródłowy dla typów pierwotnych i łańcuchów za pomocą wyrażeń regularnych. Może także tokenizować strumień bazowy za pomocą ogranicznika do wyboru. Może także wykonywać skanowanie do przodu strumienia bazowego z pominięciem ogranicznika!

Jednak skaner nie jest bezpieczny dla wątków, musi być zsynchronizowany zewnętrznie.

Wybór użycia BufferedReader lub Scanner zależy od pisanego kodu, jeśli piszesz prosty czytnik dziennika Czytnik buforowany jest wystarczający. Jeśli jednak piszesz parser XML, bardziej naturalnym wyborem jest skaner.

Nawet podczas odczytywania danych wejściowych, jeśli chcesz zaakceptować dane wprowadzane przez użytkownika wiersz po wierszu i powiedzieć, że po prostu dodaj go do pliku, buforowany czytnik jest wystarczająco dobry. Z drugiej strony, jeśli chcesz zaakceptować dane wejściowe użytkownika jako polecenie z wieloma opcjami, a następnie zamierzasz wykonywać różne operacje w oparciu o określone polecenie i opcje, skaner będzie bardziej odpowiedni.


„Z drugiej strony skaner ma wbudowane o wiele więcej sera; może zrobić wszystko, co może zrobić buforowany czytnik i przy tym samym poziomie wydajności”. Nie zgadzaj się, BufferedReader jest nieco szybszy w porównaniu do Scannera, ponieważ Scanner parsuje dane wejściowe, a BufferedReader po prostu odczytuje sekwencję znaków.
Pratik

40
  1. BufferedReaderma znacznie większą pamięć bufora niż skaner. Użyj, BufferedReaderjeśli chcesz uzyskać długie ciągi ze strumienia, i użyj, Scannerjeśli chcesz przeanalizować określony typ tokena ze strumienia.

  2. Scannermoże używać tokenize przy użyciu niestandardowego ogranicznika i analizować strumień w prymitywne typy danych, a jednocześnie BufferedReadermoże tylko czytać i przechowywać ciąg.

  3. BufferedReaderjest synchroniczny, podczas gdy Scannernie jest. Użyj, BufferedReaderjeśli pracujesz z wieloma wątkami.

  4. Scannerukrywa wyjątek IOException i BufferedReadernatychmiast go wyrzuca.


18

Sugeruję używać BufferedReaderdo czytania tekstu. Scannerchowa się IOException, BufferedReaderrzucając go natychmiast.


12

Różnice między BufferedReader i Scanner są następujące:

  1. BufferedReader jest zsynchronizowany, ale skaner nie jest zsynchronizowany .
  2. BufferedReader jest bezpieczny dla wątków, ale skaner nie jest bezpieczny dla wątków .
  3. BufferedReader ma większą pamięć buforową, ale skaner ma mniejszą pamięć buforową .
  4. BufferedReader jest szybszy, ale skaner działa wolniej .
  5. Kod do odczytu linii z konsoli:

    BufferedReader :

     InputStreamReader isr=new InputStreamReader(System.in);
     BufferedReader br= new BufferedReader(isr);
     String st= br.readLine();

    Skaner :

    Scanner sc= new Scanner(System.in);
    String st= sc.nextLine();

8

Poniżej przedstawiono różnice między BufferedReader i Scanner

  1. BufferedReader odczytuje tylko dane, ale skaner również analizuje dane.
  2. możesz czytać tylko String używając BufferedReader, ale możesz czytać int, long lub float za pomocą Scannera.
  3. BufferedReader jest starszy od Scannera, istnieje od jdk 1.1, podczas gdy Scanner został dodany w wersji JDK 5.
  4. Rozmiar bufora BufferedReadera jest duży (8 KB) w porównaniu do 1 KB skanera.
  5. BufferedReader jest bardziej odpowiedni do odczytu pliku z długim ciągiem, podczas gdy skaner jest bardziej odpowiedni do odczytu danych wejściowych małych użytkowników z wiersza polecenia.
  6. BufferedReader jest zsynchronizowany, ale skaner nie, co oznacza, że ​​nie można udostępnić skanera wielu wątkom.
  7. BufferedReader jest szybszy niż skaner, ponieważ nie spędza czasu na analizie
  8. BufferedReader jest nieco szybszy w porównaniu do skanera
  9. BufferedReader pochodzi z pakietu java.io, a skaner pochodzi z pakietu java.util na podstawie punktów, które możemy wybrać.

Dzięki


6

Główne różnice:

  1. Skaner

  • Prosty skaner tekstowy, który potrafi analizować prymitywne typy i łańcuchy za pomocą wyrażeń regularnych.
  • Skaner dzieli swoje dane wejściowe na tokeny za pomocą wzoru separatora, który domyślnie pasuje do białych znaków. Otrzymane tokeny można następnie przekonwertować na wartości różnych typów przy użyciu różnych następnych metod.

Przykład

 String input = "1 fish 2 fish red fish blue fish";
 Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
 System.out.println(s.nextInt());
 System.out.println(s.nextInt());
 System.out.println(s.next());
 System.out.println(s.next());
 s.close(); 

wypisuje następujące dane wyjściowe:

 1
 2
 red
 blue 

Ten sam wynik można wygenerować za pomocą tego kodu, który używa wyrażenia regularnego do analizy wszystkich czterech tokenów jednocześnie:

 String input = "1 fish 2 fish red fish blue fish";

 Scanner s = new Scanner(input);
 s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)");
 MatchResult result = s.match();
 for (int i=1; i<=result.groupCount(); i++)
     System.out.println(result.group(i));
 s.close(); `


  1. BufferedReader:

    • Odczytuje tekst ze strumienia wprowadzania znaków, buforując znaki, aby zapewnić efektywny odczyt znaków, tablic i linii.

    • Można określić rozmiar bufora lub użyć rozmiaru domyślnego. Wartość domyślna jest wystarczająco duża dla większości celów.

Zasadniczo każde żądanie odczytu złożone z czytnika powoduje wysłanie odpowiedniego żądania odczytu z podstawowego strumienia znaków lub bajtów. Dlatego wskazane jest, aby owinąć BufferedReader wokół dowolnego czytnika, którego operacje read () mogą być kosztowne, takie jak FileReaders i InputStreamReaders. Na przykład,

BufferedReader in
   = new BufferedReader(new FileReader("foo.in"));

buforuje dane wejściowe z określonego pliku. Bez buforowania każde wywołanie read () lub readLine () może spowodować odczyt bajtów z pliku, konwersję na znaki, a następnie zwrócenie, co może być bardzo nieefektywne. Programy wykorzystujące DataInputStreams do wprowadzania tekstu można zlokalizować, zastępując każdy DataInputStream odpowiednim BufferedReader.

Źródło: Link


3

Istnieją różne sposoby przyjmowania danych wejściowych w Javie, takie jak:

1) BufferedReader 2) Scanner 3) Argumenty wiersza poleceń

BufferedReader Odczytuje tekst ze strumienia wprowadzania znaków, buforuje znaki, aby zapewnić efektywny odczyt znaków, tablic i linii.

Gdzie skaner to prosty skaner tekstowy, który może analizować prymitywne typy i ciągi znaków przy użyciu wyrażeń regularnych.

jeśli piszesz prosty czytnik dziennika Czytnik buforowany jest wystarczający. jeśli piszesz parser XML Skaner jest bardziej naturalnym wyborem.

Aby uzyskać więcej informacji, zapoznaj się z:

http://java.meritcampus.com/t/240/Bufferedreader?tc=mm69


1

Poniższa odpowiedź pochodzi z Reading from Console: JAVA Scanner vs BufferedReader

Po odczytaniu danych wejściowych z konsoli istnieją dwie opcje, aby to osiągnąć. Pierwsze użycie Scanner, kolejne użycie BufferedReader. Oba mają różne cechy. Oznacza różnice w sposobie korzystania z niego.

Skaner traktował dane wejściowe jako token. BufferedReader po prostu odczytuje wiersz po wierszu podany sygnał wejściowy jako ciąg znaków. Skaner sam zapewnia możliwości analizowania, tak jak nextInt (), nextFloat ().

Ale jakie są inne różnice?

  • Skaner traktował dane wejściowe jako token. BufferedReader jako stream stream / String
  • Skaner tokenizował dane wejściowe za pomocą wyrażenia regularnego. Korzystanie z BufferedReader wymaga napisania dodatkowego kodu
  • BufferedReader szybszy niż skaner * punkt nr. 2)
  • Skaner nie jest zsynchronizowany, BufferedReader zsynchronizowany

Skaner jest dostarczany od wersji JDK 1.5 wyższej.

Kiedy należy korzystać ze skanera lub buforowanego czytnika?

Spójrz na główne różnice między nimi, jedna za pomocą tokena, druga za pomocą linii strumienia. Jeśli potrzebujesz możliwości analizowania, użyj skanera. Ale czuję się bardziej komfortowo z BufferedReader. Kiedy musisz czytać z pliku, użyj BufferedReader, ponieważ używa bufora podczas odczytu pliku. Lub możesz użyć BufferedReader jako danych wejściowych do skanera.


0
  1. BufferedReader prawdopodobnie zapewni lepszą wydajność (ponieważ skaner jest oparty na InputStreamReader, patrz źródła). ups, do odczytu z plików używa nio. Kiedy testowałem wydajność nio w porównaniu z wydajnością BufferedReader dla dużych plików, nio pokazuje nieco lepszą wydajność.
  2. Do odczytu z pliku wypróbuj Apache Commons IO.

0

Wolę, Scannerponieważ nie zgłasza sprawdzonych wyjątków, a zatem jego użycie skutkuje bardziej usprawnionym kodem.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.