CodeGym /จาวาบล็อก /สุ่ม /ฝึกฝนการทำงานกับคลาส BuffreredReader และ InputStreamReade...
John Squirrels
ระดับ
San Francisco

ฝึกฝนการทำงานกับคลาส BuffreredReader และ InputStreamReader

เผยแพร่ในกลุ่ม
สวัสดี! บทเรียนวันนี้จะแบ่งออกเป็นสองส่วนเพื่อความสะดวก เราจะพูดซ้ำหัวข้อเก่าที่เราพูดถึงไปก่อนหน้านี้ และเราจะพิจารณาคุณสมบัติใหม่บางอย่าง :) เรามาเริ่มกันที่ข้อแรก คุณมีคลาสBufferedReaderหลายครั้ง แล้ว ฉันหวังว่าคุณจะไม่มีเวลาลืมข้อความนี้:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
ก่อนอ่านเพิ่มเติม ให้ลองนึกถึงส่วนประกอบแต่ละอย่าง — System.in, InputStreamReader, BufferedReader— มีหน้าที่รับผิดชอบและเหตุใดจึงจำเป็น คุณจำได้ไหม? ถ้าไม่ก็ไม่ต้องกังวล :) หากคุณลืมบางสิ่งไป ให้อ่านบทเรียนนี้ อีกครั้ง ซึ่งมีไว้สำหรับชั้นเรียนผู้อ่านโดยเฉพาะ เราจะจำสั้น ๆ ว่าแต่ละคนสามารถทำอะไรได้บ้าง System.in— นี่คือสตรีมสำหรับรับข้อมูลจากแป้นพิมพ์  โดยหลักการแล้ว แค่ใช้ตรรกะที่จำเป็นในการอ่านข้อความก็เพียงพอแล้ว แต่อย่างที่คุณจำSystem.inได้ อ่านได้เฉพาะไบต์ ไม่ใช่อักขระ:

public class Main {

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

       while (true) { 
           int x = System.in.read(); 
           System.out.println(x); 
       } 
   } 
} 
ถ้าเรารันโค้ดนี้และป้อนอักษรซีริลลิก "Й" ผลลัพธ์จะเป็น:

Й
208
153
10 
อักขระซิริลลิกใช้หน่วยความจำ 2 ไบต์ และแสดงบนหน้าจอ ตัวเลข 10 คือการแสดงทศนิยมของอักขระป้อนบรรทัด เช่น จากการกด Enter การอ่านไบต์เป็นเรื่องที่น่ายินดี ดังนั้นการใช้งานSystem.inจึงไม่สะดวกนัก เพื่อให้อ่านอักษรซิริลลิก (และอื่นๆ) ได้อย่างถูกต้อง เราใช้InputStreamReaderเป็นตัวตัด:

public class Main { 

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

       InputStreamReader reader = new InputStreamReader(System.in); 
       while (true) { 
           int x = reader.read(); 
           System.out.println(x); 
       } 
   } 
} 
เราป้อนตัวอักษรเดียวกัน "Й" แต่ผลลัพธ์จะแตกต่างออกไปในครั้งนี้:

Й 
1049 
10
InputStreamReaderแปลงสองไบต์ (208 และ 153) เป็นเลขตัวเดียว 1049 นี่คือความหมายของการอ่านอักขระ 1,049 ตรงกับอักษรซีริลลิก "Й" เราสามารถโน้มน้าวตัวเองได้อย่างง่ายดายว่านี่คือความจริง:

public class Main { 

   public static void main(String[] args) throws IOException { 
       char x = 1049; 
       System.out.println(x); 
   } 
} 
เอาต์พุตคอนโซล:

Й
และเช่นเดียวกับforBufferedReader(และโดยทั่วไปBufferedAnythingYouWant) คลาสบัฟเฟอร์จะถูกใช้เพื่อเพิ่มประสิทธิภาพ การเข้าถึงแหล่งข้อมูล (ไฟล์ คอนโซล ทรัพยากรบนเว็บ) มีค่าใช้จ่ายค่อนข้างแพงในแง่ของประสิทธิภาพ ดังนั้นเพื่อลดจำนวนการเข้าถึงBufferedReaderอ่านและสะสมข้อมูลในบัฟเฟอร์พิเศษ และเราได้รับจากที่นั่น เป็นผลให้จำนวนครั้งที่เข้าถึงแหล่งข้อมูลถูกเฉือน — อาจมีหลายลำดับความสำคัญ! อีกคุณสมบัติหนึ่งBufferedReaderและข้อดีที่เหนือกว่าแบบธรรมดาInputStreamReaderคือreadLine()วิธีการที่มีประโยชน์อย่างมาก ซึ่งจะอ่านข้อมูลทั้งบรรทัด ไม่ใช่ตัวเลขเดี่ยวๆ แน่นอนว่าวิธีนี้สะดวกมากเมื่อต้องจัดการกับข้อความขนาดใหญ่ นี่คือลักษณะของบรรทัดการอ่าน:

public class Main { 

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

       BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 
       String s = reader.readLine(); 
       System.out.println ("The user entered the following text:"); 
       System.out.println(s); 
       reader.close(); 
   } 
}

BufferedReader+InputStreamReader is faster than InputStreamReader alone 
The user entered the following text: 
BufferedReader+InputStreamReader is faster than InputStreamReader alone
ฝึกฝนการทำงานกับคลาส BuffreredReader และ InputStreamReader - 2แน่นอนBufferedReaderมีความยืดหยุ่นมาก คุณไม่จำกัดการทำงานกับแป้นพิมพ์เท่านั้น ตัวอย่างเช่น คุณสามารถอ่านข้อมูลได้โดยตรงจากเว็บ เพียงแค่ส่ง URL ที่จำเป็นไปยังผู้อ่าน:

public class URLReader { 

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

       URL oracle = new URL("https://www.oracle.com/index.html"); 
       BufferedReader in = new BufferedReader( 
               new InputStreamReader(oracle.openStream())); 

       String inputLine; 
       while ((inputLine = in.readLine()) != null) 
           System.out.println(inputLine); 
       in.close(); 
   } 
}
คุณสามารถอ่านข้อมูลจากไฟล์โดยผ่านเส้นทางไฟล์:

public class Main { 

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

       FileInputStream fileInputStream = new FileInputStream("testFile.txt"); 
       BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream)); 

       String str; 

       while ((str = reader.readLine()) != null)   { 
           System.out.println (str); 
       } 

       reader.close(); 
   } 
}

แทนที่ System.out

ทีนี้มาดูความสามารถที่น่าสนใจที่เรายังไม่เคยสัมผัสมาก่อน อย่างที่คุณจำได้แน่นอนSystemคลาสมีฟิลด์สแตติกสองฟิลด์— System.inและ System.outพี่น้องฝาแฝดเหล่านี้เป็นวัตถุกระแส System.inเป็นInputStream. และSystem.out เป็นPrintStream. ในตอนนี้เราจะพูด  System.outถึง ถ้าเราใส่Systemซอร์สโค้ดของคลาส เราจะเห็นสิ่งนี้:

public final class System { 
……………... 
public final static PrintStream out = null; 
 ………… 
} 
ดังนั้นจึง  System.out  เป็นเพียงตัวแปรคงที่ธรรมดาของSystemคลาส ไม่มีอะไรวิเศษเกี่ยวกับมัน :) outตัวแปรคือPrintStreamการอ้างอิง นี่เป็นคำถามที่น่าสนใจ: เมื่อใดSystem.out.println()ที่ดำเนินการ เหตุใดเอาต์พุตจึงไปที่คอนโซล ไม่ใช่ที่อื่น และสิ่งนี้สามารถเปลี่ยนแปลงได้หรือไม่? ตัวอย่างเช่น สมมติว่าเราต้องการอ่านข้อมูลจากคอนโซลและเขียนลงในไฟล์ข้อความ เป็นไปได้ไหมที่จะใช้สิ่งนี้เพียงแค่ใช้  System.outคลาสตัวอ่านและตัวเขียนเพิ่มเติม จริงอยู่ :) และเราสามารถทำได้แม้ว่าSystem.outตัวแปรจะถูกทำเครื่องหมายด้วยfinalตัวดัดแปลง!  ฝึกทำงานกับคลาส BuffreredReader และ InputStreamReader - 3แล้วเราต้องทำอย่างไรจึงจะทำให้สิ่งนี้เกิดขึ้น? ก่อนอื่น เราต้องการPrintStreamวัตถุใหม่เพื่อแทนที่วัตถุปัจจุบัน วัตถุปัจจุบันตั้งอยู่ในSystemคลาสตามค่าเริ่มต้นไม่ตอบสนองวัตถุประสงค์ของเรา: มันชี้ไปที่คอนโซล คุณต้องสร้างไฟล์ใหม่ที่ชี้ไปที่ไฟล์ข้อความ ซึ่งเป็น "ปลายทาง" สำหรับข้อมูลของเรา ประการที่สอง เราต้องเข้าใจวิธีการกำหนดค่าใหม่ให้กับSystem.outตัวแปร คุณไม่สามารถใช้ตัวดำเนินการกำหนดอย่างง่ายได้ เนื่องจากตัวแปรถูกทำเครื่องหมายfinalไว้ มาทำงานกันต่อจากจุดสิ้นสุด เมื่อมันเกิดขึ้นSystemคลาสมีเมธอดที่เราต้องการ: setOut(). ใช้PrintStreamวัตถุและตั้งค่าเป็นปลายทางสำหรับเอาต์พุต นั่นคือสิ่งที่เราต้องการ! สิ่งที่เหลืออยู่คือการสร้างPrintStreamวัตถุ นี่เป็นเรื่องง่ายเช่นกัน:

PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
รหัสเต็มจะมีลักษณะดังนี้:

public class SystemRedirectService { 

   public static void main(String arr[]) throws FileNotFoundException 
   { 
       PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
       /* Save the current value of System.out in a separate variable so that later 
       we can switch back to console output */ 

       PrintStream console = System.out; 
       // Assign a new value to System.out 
       System.setOut(filePrintStream); 
       System.out.println("This line will be written to the text file"); 

       // Restore the old value of System.out 
       System.setOut(console); 
       System.out.println("But this line will be output to the console!"); 
   } 
}
ดังนั้น สตริงแรกจะถูกเขียนลงในไฟล์ข้อความ และสตริงที่สองจะแสดงในคอนโซล :) คุณสามารถคัดลอกโค้ดนี้ไปยัง IDE ของคุณและเรียกใช้ได้ เปิดไฟล์ข้อความแล้วคุณจะเห็นว่ามีการเขียนสตริงสำเร็จแล้ว :) ด้วยเหตุนี้บทเรียนของเราจึงสิ้นสุดลง วันนี้เรานึกถึงวิธีการทำงานกับสตรีมและผู้อ่าน เราจำได้ว่าทั้งสองอย่างนี้แตกต่างกันอย่างไร และได้เรียนรู้เกี่ยวกับความสามารถใหม่ๆ ของSystem.outที่เราใช้ในเกือบทุกบทเรียน :) จนกว่าจะถึงบทเรียนถัดไป!

อ่านเพิ่มเติม:

ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION