สวัสดี! บทเรียนวันนี้จะแบ่งออกเป็นสองส่วนเพื่อความสะดวก เราจะพูดซ้ำหัวข้อเก่าที่เราพูดถึงไปก่อนหน้านี้ และเราจะพิจารณาคุณสมบัติใหม่บางอย่าง :) เรามาเริ่มกันที่ข้อแรก คุณมีคลาส
แน่นอน
แล้วเราต้องทำอย่างไรจึงจะทำให้สิ่งนี้เกิดขึ้น? ก่อนอื่น เราต้องการ
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

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
ตัวดัดแปลง! 
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
ที่เราใช้ในเกือบทุกบทเรียน :) จนกว่าจะถึงบทเรียนถัดไป!
อ่านเพิ่มเติม: |
---|
GO TO FULL VERSION