สแกนเนอร์กับ BufferedReader


284

เท่าที่ผมรู้ว่าทั้งสองวิธีที่พบมากที่สุดของการอ่านข้อมูลตัวอักษรตามจากไฟล์ในชวาจะใช้หรือScanner BufferedReaderฉันรู้ว่าการBufferedReaderอ่านไฟล์อย่างมีประสิทธิภาพโดยใช้บัฟเฟอร์เพื่อหลีกเลี่ยงการดำเนินการทางกายภาพของดิสก์

คำถามของฉันคือ:

  • ไม่Scannerดำเนินการเช่นเดียวBufferedReader?
  • ทำไมคุณถึงเลือกScannerมากกว่าBufferedReaderหรือในทางกลับกัน?

1
โดยทั่วไปฉันยังใช้สแกนเนอร์สำหรับการอ่านจากมาตรฐานใน ('สแกนเนอร์ใน = สแกนเนอร์ใหม่ (System.in)' รู้สึกสะอาดขึ้นมาก) ไม่แน่ใจว่าจริง ๆ แล้วมีประสิทธิภาพน้อยกว่า แต่เนื่องจากการอ่านจาก std in เป็นการบล็อกฉันไม่สามารถจินตนาการได้ว่าประสิทธิภาพของเครื่องสแกนน่าจะเป็นปัญหา
dimo414

คำตอบ:


201

Scannerใช้สำหรับการวิเคราะห์โทเค็นจากเนื้อหาของสตรีมในขณะที่BufferedReaderอ่านสตรีมและไม่ทำการแยกวิเคราะห์พิเศษใด ๆ

ในความเป็นจริงคุณสามารถส่ง a BufferedReaderถึงscannerเป็นแหล่งที่มาของอักขระที่จะแยกวิเคราะห์


55
BufferedReader ได้รับการซิงโครไนซ์และเครื่องสแกนไม่ได้ดังนั้นขึ้นอยู่กับคุณที่จะตัดสินใจ
รูเบน

1
ฉันรู้ว่าหัวข้อนี้เก่า แต่ฉันมีผลการผสมระหว่างระบบปฏิบัติการโดยใช้ BufferedReader เมื่อพยายาม slurp up เนื้อหาจากสตรีมที่จัดทำโดยกระบวนการ (เช่นการจับเอาท์พุทของคำสั่งภายนอก) เมื่อฉันเปลี่ยนรหัสของฉันเพื่อใช้สแกนเนอร์แทนดังที่ระบุไว้ในคำตอบที่แยกต่างหากสิ่งต่าง ๆ เริ่มทำงานอย่างสม่ำเสมอและตามที่คาดไว้
ewh

@ Reuben แต่Scannerท้ายที่สุดก็ขึ้นอยู่กับสิ่งอื่นสำหรับอินพุตซึ่งอาจจะซิงโครไนซ์กัน
มาร์ควิสแห่ง Lorne

189

ในล่าสุด JDK6 release / build (b27), Scannerมี buffer ขนาดเล็ก ( 1024 chars ) ตรงข้ามกับBufferedReader( 8192 chars ) แต่มันก็เพียงพอแล้ว

สำหรับตัวเลือกใช้Scannerถ้าคุณต้องการแยกไฟล์ใช้BufferedReaderถ้าคุณต้องการอ่านไฟล์ทีละบรรทัด ดูข้อความแนะนำของเอกสาร API ที่เกี่ยวข้องได้ด้วย

  • การแยก = ตีความอินพุตที่กำหนดเป็นโทเค็น (ชิ้นส่วน) สามารถคืนส่วนที่เจาะจงให้คุณโดยตรงเช่น int, string, ทศนิยมและอื่น ๆ ดูnextXxx()วิธีการทั้งหมดในScannerชั้นเรียน
  • การอ่าน = การสตรีมเป็นใบ้ มันช่วยคืนตัวละครทุกตัวที่คุณต้องตรวจสอบด้วยตนเองหากคุณต้องการจับคู่หรือเขียนสิ่งที่มีประโยชน์ แต่ถ้าคุณไม่จำเป็นต้องทำสิ่งนั้นการอ่านก็เพียงพอแล้ว

1
ทำได้ดีนี่. ขอบคุณสำหรับเคล็ดลับบัฟเฟอร์ กำลังมองหามันอยู่ตลอดเวลาเนื่องจากการอ่านของเจ้าของภาษามีราคาแพงมาก
Achow

7
@ Asif: parsing = ตีความอินพุตที่ให้เป็นโทเค็น (ชิ้นส่วน) มันสามารถคืนส่วนที่เจาะจงให้คุณได้โดยตรงเช่น int, string, ทศนิยม ฯลฯ ดูวิธีการ nextXxx () ทั้งหมดเหล่านั้นในคลาส Scanner การอ่าน = การสตรีมเป็นใบ้ มันช่วยคืนตัวละครทุกตัวที่คุณต้องตรวจสอบด้วยตนเองหากคุณต้องการจับคู่หรือเขียนสิ่งที่มีประโยชน์ แต่ถ้าคุณไม่จำเป็นต้องทำสิ่งนั้นการอ่านก็เพียงพอแล้ว
BalusC

@BalusC ตกลงฉันใช้ไปแล้วreadInt();readFloat (); เป็นต้นตอนนี้ได้ค่าเฉลี่ยของการแยกวิเคราะห์แล้ว และ BalusC คุณสามารถให้เวลากับฉันเพียง 10 นาทีในห้องสนทนาฉันต้องการถามเกี่ยวกับบัฟเฟอร์เพียงเล็กน้อยมันทำงานอย่างไร
Asif Mushtaq

สิ่งที่ฉันห่อBufferedReaderในตัวสร้างของสแกนเนอร์? นี่เป็นความคิดที่ดีหรือไม่?
vivek

1
Scannerบัฟเฟอร์ของจะถูกขยายตามความจำเป็นสำหรับการจับคู่รูปแบบ ดังนั้นหากคุณต้องการบัฟเฟอร์ที่มีขนาดใหญ่ขึ้นคุณจะต้องเรียกใช้เช่นfindWithinHorizon("\\z", 8192)บนและหลังจากนั้นมันจะใช้บัฟเฟอร์ที่มีความจุของ8192ตัวอักษร (หรือไฟล์ทั้งหมดหากมีขนาดเล็กกว่านั้น)
Holger

77

ดูลิงค์นี้อ้างอิงจากที่นี่:

BufferedReader เป็นคลาสที่เรียบง่ายหมายถึงการอ่านอย่างมีประสิทธิภาพจากสตรีมอันเดอร์ โดยทั่วไปแล้วคำขอการอ่านแต่ละรายการที่ทำจากเครื่องอ่านเช่น FileReader จะทำให้การร้องขอการอ่านที่เกี่ยวข้องนั้นถูกสร้างขึ้นในสตรีมที่สำคัญ การเรียกใช้ read () หรือ readLine () แต่ละครั้งอาจทำให้ไบต์อ่านจากไฟล์แปลงเป็นอักขระจากนั้นส่งคืนซึ่งอาจไม่มีประสิทธิภาพมาก ประสิทธิภาพจะได้รับการปรับปรุงให้ดีขึ้นถ้า Reader ถูกวาร์ปใน BufferedReader

BufferedReader ถูกซิงโครไนซ์ดังนั้นการดำเนินการอ่านบน BufferedReader สามารถทำได้อย่างปลอดภัยจากหลายเธรด

ในขณะที่เครื่องสแกนเนอร์มีชีสติดตั้งอยู่มากมาย มันสามารถทำทุกอย่างที่ BufferedReader สามารถทำได้และมีประสิทธิภาพในระดับเดียวกันเช่นกัน อย่างไรก็ตามนอกจากนี้สแกนเนอร์สามารถแยกสตรีมพื้นฐานสำหรับประเภทและสตริงดั้งเดิมโดยใช้นิพจน์ปกติ นอกจากนี้ยังสามารถโทเค็นสตรีมพื้นฐานด้วยตัวคั่นที่คุณเลือก นอกจากนี้ยังสามารถทำการสแกนไปข้างหน้าสตรีมพื้นฐานโดยไม่สนใจตัวคั่น!

สแกนเนอร์ไม่ด้ายปลอดภัย แต่จะต้องมีการทำข้อมูลให้ตรงกันภายนอก

ทางเลือกในการใช้ BufferedReader หรือสแกนเนอร์นั้นขึ้นอยู่กับรหัสที่คุณกำลังเขียนหากคุณกำลังเขียนตัวอ่านบันทึกอย่างง่ายบัฟเฟอร์ตัวอ่านบัฟเฟอร์นั้นเพียงพอแล้ว อย่างไรก็ตามถ้าคุณเขียน XML parser Scanner เป็นทางเลือกที่เป็นธรรมชาติมากกว่า

แม้ในขณะที่อ่านอินพุตหากต้องการยอมรับบรรทัดอินพุตของผู้ใช้ทีละบรรทัดและพูดเพียงเพิ่มลงในไฟล์ BufferedReader ก็ดีพอ ในทางตรงกันข้ามหากคุณต้องการยอมรับอินพุตของผู้ใช้เป็นคำสั่งที่มีหลายตัวเลือกจากนั้นตั้งใจที่จะดำเนินการต่าง ๆ ตามคำสั่งและตัวเลือกที่ระบุไว้เครื่องสแกนจะเหมาะสมกว่า


"สแกนเนอร์ในอีกด้านหนึ่งมีชีสติดตั้งอยู่มากมายมันสามารถทำทุกอย่างที่ BufferedReader สามารถทำได้และมีประสิทธิภาพในระดับเดียวกันด้วย" ไม่เห็นด้วย BufferedReader นั้นเร็วกว่าเครื่องสแกนเนอร์เล็กน้อยเนื่องจากสแกนเนอร์ทำการแยกวิเคราะห์ข้อมูลอินพุตและ BufferedReader จะอ่านลำดับอักขระได้อย่างง่ายดาย
Pratik

40
  1. BufferedReaderมีหน่วยความจำบัฟเฟอร์ใหญ่กว่าเครื่องสแกน ใช้BufferedReaderหากคุณต้องการรับสายยาวจากสตรีมและใช้Scannerถ้าคุณต้องการแยกโทเค็นประเภทเฉพาะจากสตรีม

  2. Scannerสามารถใช้โทเค็นโดยใช้ตัวคั่นที่กำหนดเองและแยกสตรีมเป็นข้อมูลประเภทดั้งเดิมในขณะที่BufferedReaderสามารถอ่านและจัดเก็บสตริงเท่านั้น

  3. BufferedReaderซิงโครนัสในขณะที่Scannerไม่อยู่ ใช้BufferedReaderหากคุณทำงานกับหลายเธรด

  4. Scannerซ่อน IOException ขณะที่BufferedReaderขว้างมันทันที


18

ฉันแนะนำให้ใช้BufferedReaderสำหรับอ่านข้อความ Scannerซ่อนIOExceptionในขณะที่BufferedReaderขว้างมันทันที


12

ความแตกต่างระหว่างBufferedReaderและScannerมีดังต่อไปนี้:

  1. BufferedReader ถูกซิงโครไนซ์แต่สแกนเนอร์ไม่ได้ถูกซิงโครไนซ์ไม่ตรงกัน
  2. BufferedReader เป็นเธรดที่ปลอดภัยแต่สแกนเนอร์ไม่ได้เป็นเธรดที่ปลอดภัยไม่ด้ายปลอดภัย
  3. BufferedReader มีหน่วยความจำบัฟเฟอร์ที่ใหญ่กว่าแต่ Scanner มีหน่วยความจำบัฟเฟอร์ขนาดเล็กมีหน่วยความจำบัฟเฟอร์ที่มีขนาดเล็ก
  4. BufferedReader เร็วกว่าแต่สแกนเนอร์ทำงานช้าลงช้าลงในการดำเนินการ
  5. รหัสอ่านบรรทัดจากคอนโซล:

    BufferedReader :

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

    เครื่องสแกน :

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

8

ต่อไปนี้เป็นข้อแตกต่างระหว่าง BufferedReader และสแกนเนอร์

  1. BufferedReader อ่านเฉพาะข้อมูล แต่สแกนเนอร์ยังแยกวิเคราะห์ข้อมูล
  2. คุณสามารถอ่าน String โดยใช้ BufferedReader เท่านั้น แต่คุณสามารถอ่าน int, long หรือ float โดยใช้ Scanner
  3. BufferedReader เก่ากว่าจาก Scanner มาจาก jdk 1.1 ในขณะที่ Scanner ถูกเพิ่มใน JDK 5 release
  4. ขนาดบัฟเฟอร์ของ BufferedReader มีขนาดใหญ่ (8KB) ​​เมื่อเทียบกับ 1KB ของเครื่องสแกน
  5. BufferedReader เหมาะสำหรับการอ่านไฟล์ที่มีสตริงยาวในขณะที่ Scanner เหมาะสำหรับการอ่านอินพุตผู้ใช้ขนาดเล็กจาก command prompt
  6. BufferedReader ได้รับการซิงโครไนซ์ แต่สแกนเนอร์ไม่ได้ซึ่งหมายความว่าคุณไม่สามารถใช้เครื่องสแกนร่วมกันในหลายเธรด
  7. BufferedReader นั้นเร็วกว่า Scanner เพราะมันไม่ได้ใช้เวลาในการแยกวิเคราะห์
  8. BufferedReader นั้นเร็วกว่าสแกนเนอร์เล็กน้อย
  9. BufferedReader มาจากแพ็คเกจ java.io และ Scanner มาจากแพ็คเกจ java.util ตามคะแนนที่เราสามารถเลือกได้

ขอบคุณ


6

ความแตกต่างหลัก:

  1. เครื่องสแกนเนอร์

  • เครื่องสแกนข้อความอย่างง่ายซึ่งสามารถแยกประเภทและสตริงดั้งเดิมโดยใช้การแสดงออกปกติ
  • เครื่องสแกนแบ่งการป้อนข้อมูลเป็นโทเค็นโดยใช้รูปแบบตัวคั่นซึ่งโดยค่าเริ่มต้นจะจับคู่กับช่องว่าง โทเค็นผลลัพธ์อาจถูกแปลงเป็นค่าของชนิดต่าง ๆ โดยใช้วิธีการถัดไปต่าง ๆ

ตัวอย่าง

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

พิมพ์เอาต์พุตต่อไปนี้:

 1
 2
 red
 blue 

สามารถสร้างเอาต์พุตเดียวกันด้วยรหัสนี้ซึ่งใช้นิพจน์ทั่วไปเพื่อวิเคราะห์โทเค็นทั้งสี่พร้อมกัน:

 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:

    • อ่านข้อความจากอินพุตสตรีมอักขระบัฟเฟอร์อักขระเพื่อจัดเตรียมการอ่านอักขระอาร์เรย์และบรรทัดที่มีประสิทธิภาพ

    • อาจระบุขนาดบัฟเฟอร์หรืออาจใช้ขนาดเริ่มต้น ค่าเริ่มต้นมีขนาดใหญ่พอสำหรับวัตถุประสงค์ส่วนใหญ่

โดยทั่วไปคำขอการอ่านแต่ละครั้งที่ทำจากเครื่องอ่านจะทำให้การร้องขอการอ่านที่สอดคล้องกันทำขึ้นมาจากอักขระพื้นฐานหรือสตรีมไบต์ ดังนั้นจึงแนะนำให้ห่อ BufferedReader รอบ ๆ Reader ที่การดำเนินการ read () อาจมีค่าใช้จ่ายสูงเช่น FileReaders และ InputStreamReaders ตัวอย่างเช่น,

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

จะบัฟเฟอร์อินพุตจากไฟล์ที่ระบุ หากไม่มีการบัฟเฟอร์การร้องขอ read () หรือ readLine () แต่ละรายการอาจทำให้ไบต์อ่านจากไฟล์แปลงเป็นอักขระจากนั้นส่งคืนซึ่งจะไม่มีประสิทธิภาพมาก โปรแกรมที่ใช้ DataInputStreams สำหรับการป้อนข้อความสามารถแปลเป็นภาษาท้องถิ่นโดยการแทนที่แต่ละ DataInputStream ด้วย BufferedReader ที่เหมาะสม

ที่มา: ลิงค์


3

มีวิธีการป้อนข้อมูลที่แตกต่างกันใน java เช่น:

1) BufferedReader 2) สแกนเนอร์ 3) อาร์กิวเมนต์บรรทัดคำสั่ง

BufferedReader อ่านข้อความจากอินพุตสตรีมอักขระบัฟเฟอร์อักขระเพื่อจัดเตรียมการอ่านอักขระอาร์เรย์และบรรทัดที่มีประสิทธิภาพ

Where Scanner เป็นเครื่องสแกนข้อความอย่างง่ายซึ่งสามารถแยกประเภทและสตริงดั้งเดิมโดยใช้นิพจน์ทั่วไป

หากคุณกำลังเขียนโปรแกรมอ่านบันทึกเรียบง่ายเครื่องอ่านบัฟเฟอร์มีเพียงพอ หากคุณกำลังเขียนตัวแยกวิเคราะห์ XML เป็นตัวเลือกที่เป็นธรรมชาติมากกว่า

สำหรับข้อมูลเพิ่มเติมโปรดดูที่:

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


1

คำตอบด้านล่างมาจากการอ่านจากคอนโซล: JAVA Scanner กับ BufferedReader

เมื่ออ่านอินพุตจากคอนโซลมีสองอ็อพชันเพื่อให้บรรลุ การใช้ครั้งแรกและการใช้ScannerอีกBufferedReaderครั้ง ทั้งคู่มีคุณสมบัติแตกต่างกัน มันหมายถึงความแตกต่างวิธีการใช้งาน

เครื่องสแกนรับการป้อนข้อมูลที่กำหนดให้เป็นโทเค็น BufferedReader เพียงแค่อ่านทีละบรรทัดรับอินพุตเป็นสตริง สแกนเนอร์ด้วยตนเองให้ความสามารถในการแยกวิเคราะห์เช่นเดียวกับ nextInt (), nextFloat ()

แต่อะไรคือความแตกต่างระหว่างคนอื่น ๆ ?

  • เครื่องสแกนรับการป้อนข้อมูลที่กำหนดให้เป็นโทเค็น BufferedReader เป็น stream line / String
  • สแกนเนอร์โทเค็นการป้อนข้อมูลที่กำหนดโดยใช้ regex การใช้ BufferedReader จะต้องเขียนรหัสพิเศษ
  • BufferedReader เร็วกว่าเครื่องสแกนเนอร์ * พอยท์หมายเลข 2
  • สแกนเนอร์ไม่ได้รับการซิงโครไนซ์ BufferedReader

เครื่องสแกนมาพร้อมกับรุ่น JDK ตั้งแต่ 1.5 ขึ้นไป

เมื่อใดควรใช้เครื่องสแกนเนอร์หรือเครื่องอ่านบัฟเฟอร์

ดูความแตกต่างที่สำคัญระหว่างทั้งสองอย่างหนึ่งรายการโดยใช้โทเค็นและอื่น ๆ ใช้สตรีมไลน์ เมื่อคุณต้องการแยกวิเคราะห์ความสามารถใช้สแกนเนอร์แทน แต่ฉันรู้สึกสะดวกสบายยิ่งขึ้นกับ BufferedReader เมื่อคุณต้องการอ่านจากไฟล์ให้ใช้ BufferedReader เพราะใช้บัฟเฟอร์เมื่ออ่านไฟล์ หรือคุณสามารถใช้ BufferedReader เป็นอินพุตให้กับเครื่องสแกน


0
  1. BufferedReader อาจจะให้ประสิทธิภาพที่ดีขึ้น (เนื่องจาก Scanner ใช้ InputStreamReader, แหล่งที่มาของการค้นหา)ยูพีเอสสำหรับการอ่านจากไฟล์จะใช้ nio เมื่อฉันทดสอบประสิทธิภาพของ nio กับประสิทธิภาพของ BufferedReader สำหรับไฟล์ขนาดใหญ่ nio จะแสดงประสิทธิภาพที่ดีขึ้นเล็กน้อย
  2. สำหรับการอ่านจากไฟล์ลอง Apache Commons IO

0

ฉันชอบScannerเพราะมันไม่ได้ทำการยกเว้นการตรวจสอบและดังนั้นจึงเป็นผลการใช้งานในรหัสความคล่องตัวมากขึ้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.