你好!第 3 级的课程和任务教您如何在控制台上显示内容,以及如何从键盘上读取数据。
从键盘上阅读:“读者” - 1
您甚至学会了使用以下复杂构造来完成此操作:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
但是我们还没有回答一个问题。

这究竟是如何运作的?

实际上,程序很少是完全独立的。它们与其他程序、系统、互联网等进行通信。“通信”主要是指“交换数据”。也就是说,它们接收一些外部数据,同时也在某处发送内部程序数据。程序交换数据的例子在日常生活中比比皆是。例如,许多网站允许您使用 Facebook 或 Twitter 帐户登录而不是注册。在这种情况下,两个程序(例如 Twitter 和您正在登录的网站)交换必要的数据。最后的结果就是你登录成功了。“stream”这个词用于描述数据交换的过程。这个名字从何而来?根据您的经验,“溪流”可能更多地与河流相关,而不是与编程相关。这绝非偶然 :) 流本质上是一段移动的数据。换句话说,在编程中,流动的不是水,而是字节和字符形式的数据。我们可以从数据流中接收数据位,然后使用它们。再次,我们将使用水/流量类比:您可以从河里舀水来煮汤、灭火或浇花。Streams 让您可以使用任何数据源:无论是 Internet、您计算机的文件系统还是其他任何东西——都没有区别。流是一种通用工具。它们允许程序从任何地方(输入流)接收数据并将其发送到任何地方(输出流)。他们的任务是相同的:从一个地方获取数据并将其发送到另一个地方。有两种类型的流:
  1. 输入流用于接收数据
  2. 输出流用于发送数据。
InputStream在 Java 中,这些流由和类 实现OutputStream。但是流可以用另一种方式分类。除了输入和输出流,我们还谈到字节流字符流。这里的意思应该很清楚了:字节流以一组字节的形式发送信息,而字符流以一组字符的形式发送信息。在本课中,我们将详细介绍输入流。我将在课程结束时提供有关输出流信息的链接。您可以自己阅读它 :) 现在看一下这段代码:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
在上课的时候,你不觉得这句话很吓人吗?:) 一旦我们探索了它的工作原理,情况就不一样了。让我们把事情做好。我们将从最后开始。 System.in是一个InputStream对象,是我们之前谈到的类的一个实例。它是链接到系统输入设备(键盘)的输入流。顺便说一句,您间接熟悉此流。毕竟,你经常使用它的“同事”—— System.outSystem.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是一个InputStream对象)有一个read()方法可以让您读取数据。有一个问题:它读取字节,而不是字符。只使用英文字母很无聊,所以让我们尝试从键盘上读取汉字“鱼”(只需从此处复制该字母并使用 PC 上的 ctrl + v 或Mac上的Command + v将其粘贴到控制台)。顺便说一下,这个字符的意思是“鱼”。控制台输出: 233 173 154 10 这个符号和许多其他中文在计算机内存中占用 3 个字节(不像拉丁字母,只占用 1 个字节)。在这种情况下,从流中读取 4 个字节:前三个字节代表字符“鱼”,其他字节代表换行符(Enter)。因此,System.in以其朴素的形式不是我们的选择。人类(极少数例外!)不知道如何读取字节。但是 InputStreamReader班级来拯救!让我们看看这是什么动物。

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
我们传递System.inInputStreamReader对象。类名说明了一切!我们创建一个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. 现在它将能够从文件中读取数据(当然,如果文件实际存在于路径中)。我们还使用InputStreamReader类的read()方法来读取数据(数据源并不重要:控制台、文件或其他地方)。System.in.read()和有什么区别InputStreamReader.read()?\ 让我们再试着读读带有 . 的字符“鱼” InputStreamReaderSystem.in.read()我让您想起: 233 173 154 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);
       }
   }
}
控制台输出: 39770 10 差异立即显现。最后一个字节(代表新行)保持不变(数字 10),但字符“鱼”被转换为单个代码“39770”。这就是读字的意思!如果你不相信 39770 代表字母“鱼”,很容易说服自己:)
import java.io.IOException;

public class Main {

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

       char x = 39770;
       System.out.println(x);
   }
}
控制台输出: 但是如果InputStreamReader这么好,为什么我们还需要BufferedReaderInputStreamReader知道如何读取数据并将字节转换为字符。我们还能要求什么?为什么是另一个读者?:/ 答案很简单:为了更好的性能便利性。让我们从性能开始。当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);
   }
}
控制台输出: CodeGym是学习Java最好的网站! 我们从键盘上读到这行:CodeGym 是学习 Java 的最佳网站! 这在读取大量数据时特别有用。一个字一个字地读一两行文本还是可行的。但是在《战争与和平》中一次读一个字母会有些问题 :)

更多阅读: