JavaRush /จาวาบล็อก /Random-TH /การอ่านจากแป้นพิมพ์ - "ผู้อ่าน"

การอ่านจากแป้นพิมพ์ - "ผู้อ่าน"

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

สิ่งนี้ทำงานได้อย่างไร?

ที่จริงแล้ว โปรแกรมใด ๆ ส่วนใหญ่มักไม่มีอยู่ในตัวมันเอง สามารถสื่อสารกับโปรแกรม ระบบ อินเทอร์เน็ต อื่น ๆ ได้ คำว่า "สื่อสาร" ก่อนอื่นเราหมายถึง "แลกเปลี่ยนข้อมูล" นั่นคือรับข้อมูลบางส่วนจากภายนอก และในทางกลับกัน ส่งข้อมูลของคุณเองไปที่ใดที่หนึ่ง มีตัวอย่างการแลกเปลี่ยนข้อมูลระหว่างโปรแกรมมากมาย แม้กระทั่งในชีวิตประจำวัน ดังนั้น ในหลาย ๆ ไซต์ แทนที่จะลงทะเบียน คุณสามารถเข้าสู่ระบบโดยใช้บัญชี Facebook หรือ Twitter ของคุณได้ ในสถานการณ์เช่นนี้ สองโปรแกรม เช่น Twitter และไซต์ที่คุณพยายามลงทะเบียน แลกเปลี่ยนข้อมูลที่จำเป็นซึ่งกันและกัน หลังจากนั้นคุณจะเห็นผลลัพธ์สุดท้าย - การอนุญาตที่สำเร็จ คำ ว่า " flow " มักใช้เพื่ออธิบายกระบวนการแลกเปลี่ยนข้อมูลในการเขียนโปรแกรม ชื่อนี้มาจากไหน? “การไหล” มีความเกี่ยวข้องกับแม่น้ำหรือลำธารมากกว่าการเขียนโปรแกรม อันที่จริงนี่ไม่ใช่โดยไม่มีเหตุผล :) โดยพื้นฐานแล้วสตรีมคือชิ้นส่วนของข้อมูลที่เคลื่อนไหว นั่นคือในการเขียนโปรแกรมไม่ใช่น้ำที่ "ไหล" ไปตามกระแสน้ำ แต่เป็นข้อมูลในรูปแบบไบต์และตัวอักษร จากสตรีมข้อมูล เราสามารถรับข้อมูลเป็นบางส่วนและดำเนินการบางอย่างกับข้อมูลนั้นได้ อีกครั้ง ลองใช้คำเปรียบเทียบแบบ "น้ำไหล": คุณสามารถตักน้ำจากแม่น้ำเพื่อปรุงซุป ดับไฟ หรือดอกไม้น้ำได้ เมื่อใช้สตรีม คุณสามารถทำงานกับแหล่งข้อมูลใดก็ได้: อินเทอร์เน็ต ระบบไฟล์ของคอมพิวเตอร์ของคุณ หรืออย่างอื่น ไม่สำคัญ สตรีมเป็นเครื่องมือสากล อนุญาตให้โปรแกรมรับข้อมูลจากทุกที่ (สตรีมขาเข้า) และส่งไปได้ทุกที่ (สตรีมขาออก) หน้าที่ของพวกเขาคือหนึ่ง - นำข้อมูลไปไว้ในที่หนึ่งแล้วส่งไปยังอีกที่หนึ่ง สตรีมแบ่งออกเป็นสองประเภท:
  1. กระแสขาเข้า ( อินพุต ) - ใช้เพื่อรับข้อมูล
  2. สตรีมขาออก ( เอาท์พุต ) - สำหรับส่งข้อมูล
กระแส ข้อมูลขาเข้าใน Java ถูกนำไปใช้ในคลาสInputStreamและกระแสข้อมูลขาออกในคลาส OutputStreamแต่มีอีกวิธีหนึ่งในการแบ่งเธรด พวกมันถูกแบ่งไม่เพียงแต่เป็นขาเข้าและขาออกเท่านั้น แต่ยังแบ่งออกเป็นไบต์และอักขระด้วย ความหมายนี้ชัดเจนโดยไม่มีคำอธิบาย: สตรีมไบต์ส่งข้อมูลในรูปแบบของชุดไบต์ และสตรีมอักขระส่งข้อมูลในรูปแบบของชุดอักขระ ในการบรรยายนี้ เราจะอธิบายรายละเอียดเกี่ยวกับสตรีมที่เข้ามา และฉันจะแนบข้อมูลเกี่ยวกับลิงก์ขาออกในตอนท้ายและคุณสามารถอ่านได้ด้วยตัวเอง :) ดังนั้นรหัสของเรา:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
คุณอาจคิดว่าในขณะที่อ่านการบรรยายว่ามันดูน่ากลัวมากใช่ไหม? :) แต่นี่เป็นเพียงจนกว่าเราจะทราบว่าสิ่งนี้ทำงานอย่างไร มาแก้ไขกันตอนนี้! เริ่มจากจุดสิ้นสุดกันก่อน System.inเป็นวัตถุของชั้นเรียนInputStreamที่เราพูดถึงในตอนต้น นี่คือสตรีมขาเข้าและเชื่อมโยงกับอุปกรณ์อินพุตของระบบ - คีย์บอร์ด ยังไงก็ตามคุณคุ้นเคยกับเขาทางอ้อมแล้ว ท้ายที่สุดคุณมักจะใช้ "เพื่อนร่วมงาน" ของเขาในการทำงาน - System.out! System.out- นี่คือ สตรีมเอาต์พุต ข้อมูลระบบ ใช้สำหรับส่งออกไปยังคอนโซลในวิธีเดียวSystem.out.println()กับที่คุณใช้อยู่ตลอดเวลา :) System.out- สตรีมสำหรับส่งข้อมูลไปยังคอนโซลและSystem.in- สำหรับรับข้อมูลจากแป้นพิมพ์ ง่ายมาก :) นอกจากนี้: หากต้องการอ่านข้อมูลจากแป้นพิมพ์ เราสามารถทำได้โดยไม่ต้องมีโครงสร้างขนาดใหญ่นี้ และเพียงเขียน: System.in.read();
public class Main {

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

       while (true) {
           int x = System.in.read();
           System.out.println(x);
       }
   }
}
ในชั้นเรียนInputStream(และSystem.inฉันขอเตือนคุณว่าเป็นวัตถุของ class InputStream) มีวิธีการread()ที่ช่วยให้คุณสามารถอ่านข้อมูลได้ ปัญหาหนึ่ง: มันอ่านbytesไม่ใช่character ลองอ่านตัวอักษรรัสเซีย "Ya" จากแป้นพิมพ์ เอาต์พุตคอนโซล:
Я
208
175
10
ตัวอักษรรัสเซียใช้พื้นที่ 2 ไบต์ในหน่วยความจำของคอมพิวเตอร์ (ต่างจากตัวอักษรภาษาอังกฤษซึ่งใช้เพียง 1 ไบต์) ในกรณีนี้ มีการอ่านไบต์ 3 ไบต์จากสตรีม สองตัวแรกแสดงถึงตัวอักษร "I" ของเรา และอีกอันคือการขึ้นบรรทัดใหม่ (Enter) ดังนั้นตัวเลือกในการใช้ "เปลือย" System.inจึงไม่เหมาะกับเรา มนุษย์ (มีข้อยกเว้นที่หายาก!) ไม่สามารถอ่านไบต์ได้ นี่คือจุดที่ชั้นเรียนถัดไปมาช่วยเหลือเรา - InputStreamReader! เรามาดูกันว่านี่คือสัตว์ชนิดไหน
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
เราส่งกระแสSystem.inไปยังInputStreamReader. โดยทั่วไปหากคุณแปลชื่อเป็นภาษารัสเซีย ทุกอย่างจะดูชัดเจน - "ผู้อ่านสตรีมที่เข้ามา" จริงๆแล้วนั่นคือสิ่งที่มีไว้สำหรับ! เราสร้างคลาสอ็อบเจ็กต์InputStreamReaderและส่งผ่านสตรีมขาเข้าซึ่งควรอ่านข้อมูล ในกรณีนี้...
new InputStreamReader(System.in)
...เราบอกว่า: "คุณจะอ่านข้อมูลจากสตรีมอินพุตของระบบ (คีย์บอร์ด)" แต่นี่ไม่ใช่ฟังก์ชันเดียวเท่านั้น! InputStreamReaderไม่เพียงแต่รับข้อมูลจากสตรีมเท่านั้น นอกจากนี้ยังแปลงสตรีมไบต์เป็นสตรีมอักขระด้วย กล่าวอีกนัยหนึ่ง คุณไม่จำเป็นต้องกังวลเกี่ยวกับการแปลข้อมูลที่อ่านจากภาษา "คอมพิวเตอร์" เป็นภาษา "มนุษย์" อีกต่อไป - InputStreamReaderมันจะทำทุกอย่างให้คุณ InputStreamReaderแน่นอนว่าสามารถอ่านข้อมูลได้ไม่เพียงแต่จากคอนโซลเท่านั้น แต่ยังจากที่อื่นด้วย ตัวอย่างเช่นจากไฟล์:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

   public static void main(String[] args) throws IOException {
       InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("C:\\Users\\username\\Desktop\\testFile.txt"));
   }
}
ที่นี่เราสร้างสตรีมข้อมูลขาเข้าFileInputStream(นี่คือหนึ่งในหลากหลายInputStream) ส่งเส้นทางไปยังไฟล์เข้าไป และส่งกระแสข้อมูลนั้นเองInputStreamReader'y ตอนนี้จะสามารถอ่านข้อมูลจากไฟล์นี้ได้หากไฟล์อยู่ที่เส้นทางนี้อยู่แน่นอน หากต้องการอ่านข้อมูล (ไม่ว่าจะจากที่ไหน จากคอนโซล ไฟล์ หรือที่อื่นใด) คลาสInputStreamReaderยังใช้นามสกุลread(). ความแตกต่างระหว่างSystem.in.read()และ คืออะไร InputStreamReader.read()? ลองนับตัวอักษรตัวเดียวกัน “ฉัน” โดยใช้InputStreamReader. ฉันขอเตือนคุณนี่คือสิ่งที่ฉันคิดSystem.in.read():
Я
208
175
10
เขาทำงานเดียวกันได้ยังไง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);
       }
   }
}
เอาต์พุตคอนโซล:
Я
1071
10
ความแตกต่างที่เห็นได้ทันที ไบต์สุดท้าย - สำหรับการขึ้นบรรทัดใหม่ - ยังคงไม่เปลี่ยนแปลง (หมายเลข 10) แต่ตัวอักษรที่อ่าน "I" ถูกแปลงเป็นรหัสเดียว "1071" นี่คือการอ่านด้วยสัญลักษณ์! หากคุณไม่เชื่อว่ารหัส 1,071 หมายถึงตัวอักษร "ฉัน" คุณสามารถตรวจสอบได้ง่าย :)
import java.io.IOException;

public class Main {

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

       char x = 1071;
       System.out.println(x);
   }
}
เอาต์พุตคอนโซล:

Я
แต่ถ้าInputStreamReaderมันดีขนาดนั้นแล้วยังต้องการอีกทำไมBufferedReader? InputStreamReaderสามารถอ่านข้อมูลและแปลงไบต์เป็นอักขระได้ - เราต้องการอะไรอีก ทำไมต้องมี Reader อื่น? :/ คำตอบนั้นง่ายมาก - เพื่อผลผลิต ที่มากขึ้น และความสะดวกที่ มากขึ้น เริ่มต้นด้วยประสิทธิภาพกันก่อน เมื่ออ่านข้อมูล BufferedReaderจะใช้พื้นที่พิเศษ - บัฟเฟอร์โดยที่มันจะ "เพิ่ม" อักขระการอ่าน ด้วยเหตุนี้ เมื่อเราต้องการอักขระเหล่านี้ในโปรแกรม อักขระเหล่านี้จะถูกนำมาจากบัฟเฟอร์ และไม่ได้มาจากแหล่งข้อมูลโดยตรง (แป้นพิมพ์ ไฟล์ ฯลฯ) และช่วยประหยัดทรัพยากรได้มาก เพื่อให้เข้าใจว่าสิ่งนี้ทำงานอย่างไร ลองจินตนาการถึงงานของคนส่งเอกสารในบริษัทขนาดใหญ่ เป็นต้น คนส่งของนั่งอยู่ในสำนักงานและรอพัสดุมาให้เขาเพื่อจัดส่ง ทุกครั้งที่เขาได้รับพัสดุใหม่ เขาสามารถออกเดินทางได้ทันที แต่ระหว่างวันอาจมีพัสดุจำนวนมากและเขาจะต้องเดินทางระหว่างสำนักงานและที่อยู่ทุกครั้ง ผู้ให้บริการจัดส่งกลับวางกล่องไว้ในสำนักงานเพื่อให้ทุกคนสามารถใส่พัสดุของตนได้ ตอนนี้ผู้จัดส่งสามารถนำกล่องไปยังที่อยู่อย่างใจเย็น - เขาจะประหยัดเวลาได้มากเพราะเขาจะไม่ต้องกลับไปที่สำนักงานทุกครั้ง กล่องในตัวอย่างนี้เป็นบัฟเฟอร์อย่างแม่นยำ และ office เป็นแหล่งข้อมูล ผู้จัดส่งสามารถรับจดหมายจากกล่องธรรมดาเมื่อนำส่งได้ง่ายกว่าการไปที่สำนักงานทุกครั้ง นอกจากนี้ยังจะช่วยประหยัดน้ำมัน เช่นเดียวกับในโปรแกรม การใช้ข้อมูลจากบัฟเฟอร์ใช้ทรัพยากรน้อยกว่ามาก แทนที่จะเข้าถึงแหล่งข้อมูลทุกครั้ง นั่นเป็นสาเหตุที่BufferedReader+ InputStreamReaderทำงานเร็วกว่าเพียงแค่InputStreamReader. เราได้แยกแยะประสิทธิภาพแล้ว แต่ความสะดวกสบายล่ะ? ข้อได้เปรียบหลักคือBufferedReaderสามารถอ่านข้อมูลได้ไม่เพียงครั้งละหนึ่งอักขระ (แม้ว่าread()จะมีวิธีการสำหรับจุดประสงค์นี้ด้วยก็ตาม) แต่ยังรวมถึงทั้งบรรทัดด้วย! ทำได้โดยใช้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("We read this line from the keyboard:");
       System.out.println(s);
   }
}
เอาต์พุตคอนโซล:
JavaRush is the best site to learn Java!
Мы считали с клавиатуры эту строку:
JavaRush — лучший сайт для изучения Java!
สิ่งนี้มีประโยชน์อย่างยิ่งเมื่ออ่านข้อมูลจำนวนมาก ข้อความหนึ่งหรือสองบรรทัดยังสามารถอ่านได้ทีละตัวอักษร แต่การนับจดหมาย "สงครามและสันติภาพ" ทีละฉบับอาจเป็นปัญหาได้ :) ตอนนี้งานของเธรดมีความชัดเจนมากขึ้นสำหรับคุณ สำหรับการศึกษาเพิ่มเติม นี่คือแหล่งข้อมูลเพิ่มเติมสำหรับคุณ: คุณสามารถอ่านเพิ่มเติมเกี่ยวกับโฟลว์ขาเข้าและขาออกได้ที่นี่ วิดีโอรีวิวBufferedReaderจากนักเรียนคนหนึ่งของเรา ใช่ ใช่ นักเรียนของเราไม่เพียงแต่เรียนรู้ด้วยตนเองเท่านั้น แต่ยังบันทึกวิดีโอเพื่อการศึกษาให้คนอื่นๆ ด้วย! อย่าลืมกดไลค์และติดตามช่องของเรา :)
เป็นการดีกว่าถ้าคุณทำความคุ้นเคยกับการอ่านเอกสารอย่างเป็นทางการตั้งแต่เริ่มต้นการศึกษา เป็นแหล่งความรู้หลักเกี่ยวกับภาษา และคำตอบส่วนใหญ่ก็สามารถพบได้ที่นี่เสมอ
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION