Máy quét so với BufferedReader


283

Theo tôi biết, hai phương pháp phổ biến nhất để đọc dữ liệu dựa trên ký tự từ một tệp trong Java là sử dụng Scannerhoặc BufferedReader. Tôi cũng biết rằng các BufferedReadertệp đọc hiệu quả bằng cách sử dụng bộ đệm để tránh các hoạt động đĩa vật lý.

Câu hỏi của tôi là:

  • Scannerthực hiện tốt như BufferedReader?
  • Tại sao bạn chọn Scannerhơn BufferedReaderhoặc ngược lại?

1
Tôi thường cũng sử dụng Trình quét để đọc từ tiêu chuẩn trong ('Máy quét trong = Máy quét mới (System.in)' cảm thấy sạch sẽ hơn nhiều). Không chắc điều đó có thực sự kém hiệu quả hay không, nhưng vì việc đọc từ std in đang bị chặn, tôi không thể tưởng tượng được hiệu quả của Scanner sẽ là vấn đề.
dimo414

Câu trả lời:


201

Scannerđược sử dụng để phân tích mã thông báo từ nội dung của luồng trong khi BufferedReaderchỉ đọc luồng và không thực hiện bất kỳ phân tích cú pháp đặc biệt nào.

Trong thực tế, bạn có thể chuyển từ a BufferedReaderđến a scannerlàm nguồn của các ký tự để phân tích cú pháp.


55
BufferedReader được đồng bộ hóa và Scanner thì không, do đó tùy bạn quyết định.
Reuben

1
Tôi biết chủ đề này đã cũ, nhưng tôi đã có kết quả lẫn lộn giữa các hệ điều hành khi sử dụng BufferedReader khi cố gắng làm lu mờ nội dung từ các luồng được cung cấp bởi Process (tức là bắt đầu ra của lệnh bên ngoài). Khi tôi thay đổi mã của mình để sử dụng Máy quét thay vào đó, như được lưu ý trong một câu trả lời riêng biệt , mọi thứ bắt đầu hoạt động ổn định và như mong đợi.
EWH

@Reuben Nhưng Scannercuối cùng phụ thuộc vào thứ khác cho đầu vào của nó, có thể được đồng bộ hóa.
Hầu tước Lorne

189

Trong bản phát hành / xây dựng JDK6 mới nhất (b27) hiện tại, Scannerbộ đệm có bộ đệm nhỏ hơn ( 1024 ký tự ) trái ngược với BufferedReader( 8192 ký tự ), nhưng nó là quá đủ.

Đối với lựa chọn, sử dụng Scannernếu bạn muốn phân tích tệp, sử dụng BufferedReadernếu bạn muốn đọc từng dòng tệp. Đồng thời xem văn bản giới thiệu về các tài liệu API đã nói ở trên.

  • Phân tích cú pháp = diễn giải đầu vào đã cho dưới dạng mã thông báo (phần). Nó có thể trả lại cho bạn các phần cụ thể trực tiếp dưới dạng int, chuỗi, thập phân, v.v. Xem thêm tất cả các nextXxx()phương thức đó trong Scannerlớp.
  • Đọc = phát trực tiếp câm. Nó liên tục trả lại cho bạn tất cả các ký tự mà đến lượt bạn phải kiểm tra thủ công nếu bạn muốn khớp hoặc soạn một cái gì đó hữu ích. Nhưng nếu bạn không cần phải làm điều đó, thì đọc là đủ.

1
Đẹp một. Cảm ơn các mẹo đệm. Đã tìm kiếm tất cả cùng vì đọc bản địa là vô cùng tốn kém.
Đạt được

7
@Asif: phân tích cú pháp = diễn giải đầu vào đã cho dưới dạng mã thông báo (phần). Nó có thể trả lại cho bạn các phần cụ thể trực tiếp dưới dạng int, chuỗi, thập phân, v.v. Xem thêm tất cả các phương thức nextXxx () trong lớp Scanner. Đọc = phát trực tiếp câm. Nó liên tục trả lại cho bạn tất cả các ký tự mà đến lượt bạn phải kiểm tra thủ công nếu bạn muốn khớp hoặc soạn một cái gì đó hữu ích. Nhưng nếu bạn không cần phải làm điều đó, thì đọc là đủ.
BalusC

@BalusC Ok tôi đã sử dụng, readInt();readFloat (); vv Bây giờ đã có ý nghĩa của phân tích cú pháp. và BalusC bạn có thể dành ít thời gian cho tôi chỉ 10 phút trong phòng chat, tôi muốn hỏi một chút về bộ đệm, cách thức hoạt động của nó.
Asif Mushtaq

Tôi gói cái gì BufferedReadertrong constructor của Scanner? Đây có phải là một ý tưởng tốt?
vivek

1
ScannerBộ đệm sẽ được mở rộng khi cần cho khớp mẫu. Vì vậy, nếu bạn muốn một bộ đệm lớn hơn, bạn chỉ cần gọi, ví dụ findWithinHorizon("\\z", 8192), trên nó và sau đó, nó sẽ sử dụng một bộ đệm có dung lượng 8192ký tự (hoặc toàn bộ tệp nếu nó nhỏ hơn).
Holger

77

Xem liên kết này , sau đây được trích dẫn từ đó:

BufferedReader là một lớp đơn giản có nghĩa là đọc hiệu quả từ luồng dưới quyền. Nói chung, mỗi yêu cầu đọc được tạo từ một Trình đọc như FileReader sẽ khiến yêu cầu đọc tương ứng được thực hiện cho luồng bên dưới. Mỗi lệnh gọi read () hoặc readLine () có thể khiến các byte được đọc từ tệp, được chuyển đổi thành các ký tự và sau đó được trả về, có thể rất kém hiệu quả. Hiệu quả được cải thiện đáng kể nếu một Reader bị vênh trong BufferedReader.

BufferedReader được đồng bộ hóa, do đó, các thao tác đọc trên BufferedReader có thể được thực hiện một cách an toàn từ nhiều luồng.

Mặt khác, một máy quét có nhiều phô mai hơn được tích hợp bên trong nó; nó có thể làm tất cả những gì mà BufferedReader có thể làm và ở cùng mức độ hiệu quả. Tuy nhiên, ngoài ra, Trình quét có thể phân tích luồng bên dưới cho các kiểu và chuỗi nguyên thủy bằng cách sử dụng các biểu thức thông thường. Nó cũng có thể mã hóa luồng cơ bản với dấu phân cách bạn chọn. Nó cũng có thể thực hiện quét về phía trước luồng bên dưới bỏ qua dấu phân cách!

Tuy nhiên, một máy quét không phải là luồng an toàn, nó phải được đồng bộ hóa bên ngoài.

Việc lựa chọn sử dụng BufferedReader hoặc Scanner tùy thuộc vào mã bạn đang viết, nếu bạn đang viết một trình đọc nhật ký đơn giản Trình đọc đệm là đủ. Tuy nhiên, nếu bạn đang viết một trình phân tích cú pháp XML thì máy quét là sự lựa chọn tự nhiên hơn.

Ngay cả trong khi đọc đầu vào, nếu muốn chấp nhận từng dòng đầu vào của người dùng và nói chỉ cần thêm nó vào một tệp, BufferedReader là đủ tốt. Mặt khác, nếu bạn muốn chấp nhận đầu vào của người dùng dưới dạng một lệnh có nhiều tùy chọn và sau đó có ý định thực hiện các hoạt động khác nhau dựa trên lệnh và các tùy chọn được chỉ định, Máy quét sẽ phù hợp hơn.


"Mặt khác, một máy quét có nhiều phô mai hơn được tích hợp vào nó; nó có thể làm tất cả những gì mà BufferedReader có thể làm và ở cùng mức độ hiệu quả." Không đồng ý, BufferedReader nhanh hơn một chút so với Scanner vì Scanner quét phân tích dữ liệu đầu vào và BufferedReader chỉ đơn giản là đọc chuỗi ký tự.
Pratik

40
  1. BufferedReadercó bộ nhớ đệm lớn hơn đáng kể so với Scanner. Sử dụng BufferedReadernếu bạn muốn nhận chuỗi dài từ luồng và sử dụng Scannernếu bạn muốn phân tích loại mã thông báo cụ thể từ luồng.

  2. Scannercó thể sử dụng mã thông báo bằng cách sử dụng dấu phân cách tùy chỉnh và phân tích luồng thành các loại dữ liệu nguyên thủy, trong khi BufferedReaderchỉ có thể đọc và lưu trữ Chuỗi.

  3. BufferedReaderlà đồng bộ trong khi Scannerkhông. Sử dụng BufferedReadernếu bạn đang làm việc với nhiều chủ đề.

  4. Scannerẩn IOException trong khi BufferedReaderném nó ngay lập tức.


18

Tôi đề nghị sử dụng BufferedReaderđể đọc văn bản. Scannerẩn IOExceptiontrong khi BufferedReaderném nó ngay lập tức.


12

Sự khác biệt giữa BufferedReaderScanner là như sau:

  1. BufferedReader là đồng bộ hóa nhưng Scanner không được đồng bộ hóa .
  2. BufferedReader là luồng an toàn nhưng Scanner không phảiluồng an toàn .
  3. Bộ đệm có bộ nhớ đệm lớn hơn nhưng Scanner có bộ nhớ đệm nhỏ hơn .
  4. BufferedReader là nhanh hơn nhưng Scanner chậm hơn khi thực thi .
  5. Mã để đọc một dòng từ bảng điều khiển:

    Bộ đệm :

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

    Máy quét :

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

8

Sau đây là sự khác biệt giữa BufferedReader và Scanner

  1. BufferedReader chỉ đọc dữ liệu nhưng máy quét cũng phân tích dữ liệu.
  2. bạn chỉ có thể đọc Chuỗi bằng BufferedReader, nhưng bạn có thể đọc int, long hoặc float bằng Scanner.
  3. BufferedReader cũ hơn từ Scanner, nó tồn tại từ jdk 1.1 trong khi Scanner được thêm vào bản phát hành JDK 5.
  4. Kích thước bộ đệm của BufferedReader lớn (8KB) ​​so với 1KB của Máy quét.
  5. BufferedReader phù hợp hơn để đọc tệp có Chuỗi dài trong khi Trình quét phù hợp hơn để đọc đầu vào của người dùng nhỏ từ dấu nhắc lệnh.
  6. BufferedReader được đồng bộ hóa nhưng Scanner thì không, điều đó có nghĩa là bạn không thể chia sẻ Scanner giữa nhiều luồng.
  7. BufferedReader nhanh hơn Scanner vì nó không dành thời gian cho việc phân tích cú pháp
  8. BufferedReader nhanh hơn một chút so với Scanner
  9. BufferedReader là từ gói java.io và Scanner là từ gói java.util trên cơ sở các điểm chúng ta có thể chọn lựa chọn của mình.

Cảm ơn


6

Sự khác biệt chính:

  1. Máy quét

  • Một trình quét văn bản đơn giản có thể phân tích các kiểu và chuỗi nguyên thủy bằng cách sử dụng các biểu thức thông thường.
  • Máy quét phá vỡ đầu vào của nó thành các mã thông báo bằng cách sử dụng mẫu dấu phân cách, theo mặc định khớp với khoảng trắng. Các mã thông báo kết quả sau đó có thể được chuyển đổi thành các giá trị của các loại khác nhau bằng các phương pháp tiếp theo khác nhau.

Thí dụ

 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(); 

in đầu ra sau:

 1
 2
 red
 blue 

Có thể tạo cùng một đầu ra với mã này, sử dụng biểu thức chính quy để phân tích tất cả bốn mã thông báo cùng một lúc:

 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. Bộ đệm:

    • Đọc văn bản từ luồng nhập ký tự, đệm các ký tự để cung cấp cho việc đọc hiệu quả các ký tự, mảng và dòng.

    • Kích thước bộ đệm có thể được chỉ định hoặc kích thước mặc định có thể được sử dụng. Mặc định là đủ lớn cho hầu hết các mục đích.

Nói chung, mỗi yêu cầu đọc được thực hiện bởi Reader khiến yêu cầu đọc tương ứng được tạo từ ký tự hoặc luồng byte bên dưới. Do đó, nên bọc BufferedReader xung quanh bất kỳ Trình đọc nào có hoạt động đọc () có thể tốn kém, chẳng hạn như FileReaders và InputStreamReaders. Ví dụ,

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

sẽ đệm đầu vào từ tệp được chỉ định. Nếu không có bộ đệm, mỗi lệnh gọi read () hoặc readLine () có thể khiến byte được đọc từ tệp, được chuyển đổi thành ký tự và sau đó được trả về, có thể rất kém hiệu quả. Các chương trình sử dụng DataInputStreams cho nhập văn bản có thể được bản địa hóa bằng cách thay thế mỗi DataInputStream bằng BufferedReader thích hợp.

Nguồn: Liên kết


3

Có nhiều cách khác nhau để lấy đầu vào trong java như:

1) BufferedReader 2) Máy quét 3) Đối số dòng lệnh

BufferedReader Đọc văn bản từ luồng nhập ký tự, đệm các ký tự để cung cấp cho việc đọc hiệu quả các ký tự, mảng và dòng.

Trong đó Scanner là một trình quét văn bản đơn giản có thể phân tích các kiểu và chuỗi nguyên thủy bằng các biểu thức thông thường.

nếu bạn đang viết một trình đọc nhật ký đơn giản Trình đọc đệm là đủ. nếu bạn đang viết một trình phân tích cú pháp XML thì máy quét là sự lựa chọn tự nhiên hơn.

Để biết thêm thông tin xin vui lòng tham khảo:

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


1

Câu trả lời dưới đây được lấy từ Reading từ Console: JAVA Scanner vs BufferedReader

Khi đọc một đầu vào từ bàn điều khiển, có hai tùy chọn tồn tại để đạt được điều đó. Đầu tiên sử dụng Scanner, sử dụng khác BufferedReader. Cả hai đều có đặc điểm khác nhau. Nó có nghĩa là sự khác biệt làm thế nào để sử dụng nó.

Máy quét được xử lý đầu vào dưới dạng mã thông báo. BufferedReader chỉ cần đọc từng dòng theo đầu vào dưới dạng chuỗi. Trình quét tự cung cấp khả năng phân tích cú pháp giống như nextInt (), nextFloat ().

Nhưng, sự khác biệt giữa những người khác là gì?

  • Máy quét được xử lý đầu vào dưới dạng mã thông báo. BufferedReader dưới dạng dòng / Chuỗi
  • Máy quét mã thông báo đầu vào đã cho bằng cách sử dụng regex. Sử dụng BufferedReader phải viết thêm mã
  • BufferedReader nhanh hơn Scanner * điểm không. 2
  • Máy quét không được đồng bộ hóa, được đồng bộ hóa BufferedReader

Máy quét đi kèm với phiên bản JDK 1.5 cao hơn.

Khi nào nên sử dụng Scanner, hay Buffered Reader?

Nhìn vào sự khác biệt chính giữa cả hai, một sử dụng mã thông báo, những người khác sử dụng dòng truyền phát. Khi bạn cần khả năng phân tích cú pháp, thay vào đó hãy sử dụng Máy quét. Nhưng, tôi thấy thoải mái hơn với BufferedReader. Khi bạn cần đọc từ Tệp, hãy sử dụng BufferedReader, vì nó sử dụng bộ đệm khi đọc tệp. Hoặc bạn có thể sử dụng BufferedReader làm đầu vào cho Máy quét.


0
  1. BufferedReader có thể sẽ cung cấp cho bạn hiệu suất tốt hơn (vì Trình quét dựa trên InputStreamReader, tìm nguồn).up, để đọc từ tập tin nó sử dụng nio. Khi tôi kiểm tra hiệu năng của nio so với hiệu suất của BufferedReader cho các tệp lớn, nio cho thấy hiệu năng tốt hơn một chút.
  2. Để đọc từ tệp, hãy thử Apache Commons IO.

0

Tôi thích Scannerbởi vì nó không đưa ra các ngoại lệ được kiểm tra và do đó, việc sử dụng nó dẫn đến một mã hợp lý hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.