JavaRush /Java 博客 /Random-ZH /练习使用 BufferedReader 和 InputStreamReader 类

练习使用 BufferedReader 和 InputStreamReader 类

已在 Random-ZH 群组中发布
你好!今天的讲座将分为两个部分。我们将重复一些之前已经讨论过的旧主题,并研究一些新功能:) 练习使用 BufferredReader 和 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)转换为单个数字 1049。这是按字符读取。1049对应的是字母“Y”,很容易验证:
public class Main {

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

       char x = 1049;
       System.out.println(x);
   }
}
控制台输出:

Й
好吧,对于BufferedReader'a(以及一般情况下的 BufferedAnything),缓冲类用于优化性能。就性能而言,访问数据源(文件、控制台、Internet 上的资源)是一项相当昂贵的操作。因此,为了减少此类调用的次数,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
练习使用 BufferredReader 和 InputStreamReader 类 - 2当然,BufferedReader这是一种非常灵活的机制,让您不仅可以使用键盘进行工作。例如,您可以直接从 Internet 读取数据,只需将所需的 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.inSystem.out。这对孪生兄弟是线程类对象。System.in- 抽象类InputStream。一System.outPrintStream。现在我们就具体来说一下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,但我们仍然可以做到! 练习使用 BufferredReader 和 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