JavaRush /Blog Java /Random-VI /Đọc từ bàn phím - “người đọc”

Đọc từ bàn phím - “người đọc”

Xuất bản trong nhóm
Xin chào! Trong các bài giảng và bài tập, chúng ta đã học cách xuất dữ liệu ra bảng điều khiển và ngược lại - đọc dữ liệu từ bàn phím. Đọc từ bàn phím - “người đọc” - 1Bạn thậm chí còn học cách sử dụng một cấu trúc phức tạp cho việc này:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Nhưng chúng tôi vẫn chưa trả lời một câu hỏi.

Làm thế nào điều này thậm chí hoạt động?

Trên thực tế, bất kỳ chương trình nào thường không tự tồn tại. Nó có thể giao tiếp với các chương trình, hệ thống, Internet, v.v. Với từ “giao tiếp”, trước hết chúng tôi có nghĩa là “trao đổi dữ liệu”. Tức là nhận một số dữ liệu từ bên ngoài và ngược lại, gửi dữ liệu của chính bạn đi đâu đó. Có rất nhiều ví dụ về trao đổi dữ liệu giữa các chương trình, ngay cả trong cuộc sống hàng ngày. Vì vậy, trên nhiều trang, thay vì đăng ký, bạn có thể đăng nhập bằng tài khoản Facebook hoặc Twitter. Trong tình huống này, hai chương trình, chẳng hạn như Twitter và trang web nơi bạn đang cố đăng ký, trao đổi dữ liệu cần thiết với nhau, sau đó bạn sẽ thấy kết quả cuối cùng - ủy quyền thành công. Thuật ngữ “ luồng ” thường được dùng để mô tả quá trình trao đổi dữ liệu trong lập trình . Cái tên này thậm chí đến từ đâu? “Dòng chảy” gắn liền với dòng sông hoặc dòng suối hơn là với việc lập trình. Trên thực tế, điều này không phải là không có lý do :) Về bản chất, luồng là một phần dữ liệu chuyển động. Tức là, trong lập trình, không phải nước “chảy” dọc theo dòng mà là dữ liệu ở dạng byte và ký tự. Từ luồng dữ liệu, chúng ta có thể nhận dữ liệu theo từng phần và thực hiện điều gì đó với dữ liệu đó. Một lần nữa, chúng ta hãy sử dụng phép tương tự “dòng nước”: bạn có thể múc nước từ sông để nấu súp, dập lửa hoặc tưới hoa. Sử dụng luồng, bạn có thể làm việc với bất kỳ nguồn dữ liệu nào: Internet, hệ thống tệp của máy tính của bạn hoặc thứ gì khác - điều đó không thành vấn đề. Luồng là một công cụ phổ quát. Chúng cho phép chương trình nhận dữ liệu từ mọi nơi (luồng đến) và gửi dữ liệu đến bất kỳ đâu (luồng đi). Nhiệm vụ của họ là một - lấy dữ liệu ở một nơi và gửi nó đến nơi khác. Các luồng được chia thành hai loại:
  1. Luồng đến ( Input ) - dùng để nhận dữ liệu
  2. Luồng đi ( Đầu ra ) - để gửi dữ liệu.
Luồng dữ liệu đến trong Java được triển khai trong lớp InputStreamvà luồng dữ liệu đi trong lớp OutputStream. Nhưng có một cách khác để chia chủ đề. Chúng không chỉ được chia thành đến và đi mà còn được chia thành byteký tự . Ở đây ý nghĩa rất rõ ràng mà không cần giải thích: luồng byte truyền thông tin dưới dạng tập hợp byte và luồng ký tự truyền thông tin dưới dạng tập hợp ký tự. Trong bài giảng này chúng ta sẽ đi vào chi tiết về các luồng đến. Và tôi sẽ đính kèm thông tin về các liên kết gửi đi ở cuối và bạn có thể tự đọc về nó :) Vì vậy, mã của chúng tôi:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Có lẽ bạn đã nghĩ khi đọc các bài giảng rằng nó trông khá đáng sợ phải không? :) Nhưng điều này chỉ xảy ra cho đến khi chúng ta tìm ra cách thức hoạt động của thứ này. Hãy sửa nó ngay bây giờ! Hãy bắt đầu từ cuối. System.inlà một đối tượng của lớp InputStreammà chúng ta đã nói đến lúc đầu. Đây là luồng đến và nó được gắn với thiết bị đầu vào của hệ thống - bàn phím. Nhân tiện, bạn gián tiếp quen thuộc với anh ấy. Rốt cuộc, bạn thường sử dụng “đồng nghiệp” của anh ấy trong công việc của mình - System.out! System.out- đây là luồng đầu ra dữ liệu hệ thống , nó được sử dụng để xuất ra bảng điều khiển theo chính phương thức System.out.println()mà bạn thường xuyên sử dụng :) System.out- luồng để gửi dữ liệu đến bảng điều khiển và System.in- để nhận dữ liệu từ bàn phím. Thật đơn giản :) Hơn nữa: để đọc dữ liệu từ bàn phím, chúng ta có thể thực hiện mà không cần cấu trúc lớn này và chỉ cần viết: 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);
       }
   }
}
Trong lớp InputStream(và System.in, để tôi nhắc bạn, là một đối tượng của lớp InputStream) có một phương thức read()cho phép bạn đọc dữ liệu. Một vấn đề: nó đọc byte chứ không phải ký tự . Hãy thử đọc chữ cái tiếng Nga “Ya” từ bàn phím. Đầu ra của bảng điều khiển:
Я
208
175
10
Các chữ cái tiếng Nga chiếm 2 byte trong bộ nhớ của máy tính (không giống như các chữ cái tiếng Anh chỉ chiếm 1 byte). Trong trường hợp này, 3 byte đã được đọc từ luồng: hai byte đầu tiên đại diện cho chữ cái “I” của chúng ta và byte còn lại là ngắt dòng (Enter). Vì vậy, lựa chọn sử dụng “khỏa thân” System.insẽ không phù hợp với chúng tôi. Con người (hiếm có ngoại lệ!) Không thể đọc byte. Đây là lúc lớp tiếp theo đến trợ giúp chúng tôi - InputStreamReader! Hãy cùng tìm hiểu xem đây là loại động vật nào nhé.
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
Chúng tôi chuyển luồng System.intới InputStreamReader. Nói chung, nếu bạn dịch tên của nó sang tiếng Nga, mọi thứ đều có vẻ rõ ràng - “trình đọc các luồng đến”. Trên thực tế, đó chính xác là mục đích của nó! Chúng tôi tạo một đối tượng lớp InputStreamReadervà truyền cho nó một luồng đến để nó đọc dữ liệu. Trong trường hợp này...
new InputStreamReader(System.in)
...chúng tôi nói với nó: "bạn sẽ đọc dữ liệu từ luồng đầu vào của hệ thống (bàn phím)." Nhưng đây không phải là chức năng duy nhất của nó! InputStreamReaderkhông chỉ nhận dữ liệu từ luồng. Nó cũng chuyển đổi luồng byte thành luồng ký tự . Nói cách khác, bạn không còn phải lo lắng về việc dịch dữ liệu đã đọc từ ngôn ngữ “máy tính” sang ngôn ngữ “con người” - InputStreamReadernó sẽ làm mọi thứ cho bạn. InputStreamReaderTất nhiên, có thể đọc dữ liệu không chỉ từ bảng điều khiển mà còn từ những nơi khác. Ví dụ: từ tệp:
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"));
   }
}
Ở đây, chúng tôi đã tạo một luồng dữ liệu đến FileInputStream(đây là một trong các loại InputStream), chuyển đường dẫn đến tệp vào đó và truyền chính luồng đó InputStreamReader'y. Bây giờ nó sẽ có thể đọc dữ liệu từ tệp này, tất nhiên nếu tệp ở đường dẫn này tồn tại. Để đọc dữ liệu (bất kể từ đâu, từ bảng điều khiển, tệp hoặc bất kỳ nơi nào khác), lớp InputStreamReadercũng sử dụng read(). Sự khác biệt giữa System.in.read()và là gì InputStreamReader.read()? Hãy thử đếm cùng một chữ cái “I” bằng cách sử dụng InputStreamReader. Hãy để tôi nhắc bạn, đây là những gì tôi nghĩ System.in.read():
Я
208
175
10
Làm thế nào anh ta có thể làm công việc tương tự 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);
       }
   }
}
Đầu ra của bảng điều khiển:
Я
1071
10
Sự khác biệt có thể nhìn thấy ngay lập tức. Byte cuối cùng - để ngắt dòng - vẫn không thay đổi (số 10), nhưng chữ cái “I” đã đọc đã được chuyển đổi thành một mã duy nhất “1071”. Đây là cách đọc bằng ký hiệu! Nếu bạn đột nhiên không tin rằng mã 1071 có nghĩa là chữ “I”, thật dễ dàng để xác minh điều này :)
import java.io.IOException;

public class Main {

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

       char x = 1071;
       System.out.println(x);
   }
}
Đầu ra của bảng điều khiển:

Я
Nhưng nếu InputStreamReadernó tốt như vậy thì tại sao bạn lại cần nhiều hơn BufferedReader? InputStreamReadervừa có thể đọc dữ liệu vừa chuyển byte thành ký tự - chúng ta còn cần gì nữa? Tại sao lại là một Reader khác? :/ Câu trả lời rất đơn giản - để có năng suất cao hơn và thuận tiện hơn . Hãy bắt đầu với hiệu suất. Khi đọc dữ liệu, BufferedReader sử dụng một vùng đặc biệt - bộ đệm, nơi nó “thêm” các ký tự đã đọc. Do đó, khi chúng ta cần những ký tự này trong chương trình, chúng sẽ được lấy từ bộ đệm chứ không phải trực tiếp từ nguồn dữ liệu (bàn phím, tệp, v.v.) và điều này giúp tiết kiệm rất nhiều tài nguyên. Để hiểu cách thức hoạt động của điều này, hãy tưởng tượng, ví dụ, công việc của một người chuyển phát nhanh trong một công ty lớn. Người chuyển phát nhanh ngồi trong văn phòng và đợi bưu kiện được mang đến cho anh ta để giao. Mỗi lần nhận được một bưu kiện mới, anh ta có thể lên đường ngay lập tức. Nhưng có thể có rất nhiều bưu kiện trong ngày và anh ấy sẽ phải di chuyển giữa văn phòng và các địa chỉ mỗi lần. Thay vào đó, người chuyển phát nhanh đặt một chiếc hộp trong văn phòng để mọi người có thể đặt bưu kiện của mình. Bây giờ người chuyển phát nhanh có thể bình tĩnh lấy chiếc hộp và đi đến các địa chỉ - anh ta sẽ tiết kiệm được rất nhiều thời gian, vì anh ta sẽ không phải quay lại văn phòng mỗi lần. Hộp trong ví dụ này chính xác là bộ đệm và văn phòng là nguồn dữ liệu. Việc người chuyển phát nhanh lấy một lá thư từ một chiếc hộp thông thường khi giao nó sẽ dễ dàng hơn nhiều so với việc mỗi lần đến văn phòng. Nó cũng sẽ tiết kiệm gas. Trong một chương trình cũng vậy - việc lấy dữ liệu từ bộ đệm sẽ ít tốn tài nguyên hơn thay vì truy cập vào nguồn dữ liệu mọi lúc. Đó là lý do tại sao BufferedReader+ InputStreamReaderhoạt động nhanh hơn chỉ InputStreamReader. Chúng tôi đã sắp xếp hiệu suất, nhưng còn sự tiện lợi thì sao? Ưu điểm chính là BufferedReadernó có thể đọc dữ liệu không chỉ một ký tự tại một thời điểm (mặc dù read()nó cũng có một phương thức cho mục đích này) mà còn có thể đọc toàn bộ dòng! Việc này được thực hiện bằng cách sử dụng 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);
   }
}
Đầu ra của bảng điều khiển:
JavaRush is the best site to learn Java!
Мы считали с клавиатуры эту строку:
JavaRush — лучший сайт для изучения Java!
Điều này đặc biệt hữu ích khi đọc một lượng lớn dữ liệu. Một hoặc hai dòng văn bản vẫn có thể đọc được từng ký tự. Nhưng việc đếm từng chữ cái một trong Chiến tranh và Hòa bình sẽ có phần khó khăn :) Giờ đây, công việc của các chủ đề đã trở nên rõ ràng hơn đối với bạn. Để nghiên cứu thêm, đây là một nguồn bổ sung cho bạn: Tại đây bạn có thể đọc thêm về các luồng đến và đi. Video đánh giá BufferedReadertừ một trong những sinh viên của chúng tôi. Vâng, vâng, học sinh của chúng tôi không chỉ tự học mà còn quay video giáo dục cho người khác! Đừng quên like và subscribe kênh của mình nhé :)
Tốt hơn là bạn nên tập cho mình thói quen đọc tài liệu chính thức ngay từ khi bắt đầu học. Đây là nguồn kiến ​​thức chính về ngôn ngữ và hầu hết các câu trả lời luôn có thể được tìm thấy ở đó.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION