สวัสดี! การบรรยายในวันนี้จะแบ่งออกเป็นสองส่วน เราจะทำซ้ำหัวข้อเก่าๆ ที่เราเคยพูดถึงไปแล้ว และดูคุณสมบัติใหม่ๆ :)
มาเริ่มกันที่หัวข้อแรกกันดีกว่า การทำซ้ำเป็นแม่ของการเรียนรู้ :) คุณใช้คลาสเช่น
แน่นอนว่า
แล้วเราต้องการอะไรสำหรับสิ่งนี้? ประการแรกเราต้องการอ็อบเจ็กต์คลาสใหม่
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);
}
}
}
หากเรารันโค้ดนี้และป้อนตัวอักษร "Y" ในคอนโซล ผลลัพธ์จะเป็นดังนี้:
Й
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);
}
}
}
หากเราป้อนตัวอักษรเดียวกัน "Y" ลงในคอนโซล ผลลัพธ์ในครั้งนี้จะแตกต่างออกไป:
Й
1049
10
InputStreamReader
แปลงไบต์ที่อ่านสองไบต์ (208, 153) เป็นตัวเลขเดียว 1,049 นี่คือการอ่านทีละอักขระ 1,049 ตรงกับตัวอักษร "Y" ซึ่งสามารถตรวจสอบได้ง่าย:
public class Main {
public static void main(String[] args) throws IOException {
char x = 1049;
System.out.println(x);
}
}
เอาต์พุตคอนโซล:
Й
สำหรับBufferedReader
'a (และโดยทั่วไป - BufferedAnything) คลาสที่บัฟเฟอร์จะถูกใช้เพื่อเพิ่มประสิทธิภาพการทำงาน การเข้าถึงแหล่งข้อมูล (ไฟล์ คอนโซล ทรัพยากรบนอินเทอร์เน็ต) เป็นการดำเนินการที่ค่อนข้างแพงในแง่ของประสิทธิภาพ ดังนั้น เพื่อลดจำนวนการโทรดังกล่าวBufferedReader
ระบบจะอ่านและรวบรวมข้อมูลในบัฟเฟอร์พิเศษ ซึ่งเราจะรับข้อมูลได้ในภายหลัง ส่งผลให้จำนวนการโทรไปยังแหล่งข้อมูลลดลงหลายเท่าหรือหลายสิบเท่า! คุณลักษณะเพิ่มเติมอีกประการหนึ่งของBufferedReader
'a และข้อดีเหนือปกติ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("Пользователь ввел следующий текст:");
System.out.println(s);
reader.close();
}
}
BufferedReader+InputStreamReader работает быстрее, чем просто InputStreamReader
Пользователь ввел следующий текст:
BufferedReader+InputStreamReader работает быстрее, чем просто InputStreamReader

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"));
/*Сохраним текущее meaning System.out в отдельную переменную, чтобы потом
можно было переключиться обратно на вывод в консоль*/
PrintStream console = System.out;
// Присваиваем System.out новое meaning
System.setOut(filePrintStream);
System.out.println("Эта строка будет записана в текстовый файл");
// Возвращаем System.out старое meaning
System.setOut(console);
System.out.println("А эта строка - в консоль!");
}
}
ด้วยเหตุนี้บรรทัดแรกจะถูกเขียนลงในไฟล์ข้อความและบรรทัดที่สองจะถูกส่งออกไปยังคอนโซล :) คุณสามารถคัดลอกโค้ดนี้ไปยัง IDE ของคุณและเรียกใช้ได้ เมื่อเปิดไฟล์ข้อความแล้วคุณจะเห็นว่ามีการเขียนบรรทัดที่ต้องการเรียบร้อยแล้ว :) นี่เป็นการสรุปการบรรยาย วันนี้เราจำวิธีทำงานร่วมกับสตรีมและผู้อ่านได้ จำได้ว่ามีความแตกต่างกันอย่างไร และได้เรียนรู้ฟีเจอร์ใหม่ๆSystem.out
ที่เราใช้ในเกือบทุกบทเรียน :) เจอกันในการบรรยายครั้งต่อไป!
GO TO FULL VERSION