JavaRush /จาวาบล็อก /Random-TH /ฝึกทำงานกับคลาส BufferedReader และ InputStreamReader

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

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

       /*Сохраним текущее 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ที่เราใช้ในเกือบทุกบทเรียน :) เจอกันในการบรรยายครั้งต่อไป!
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION