在之前的文章中我们已经提过一些输入输出流,文件的读取与写入Java操作文件-优快云博客,在本文中我们将继续探究输入输出流,以及他们在Java中对应的API.
一、输入流
在计算机领域,输入流(Input Stream)是指从外部数据源(如键盘、文件、网络连接等)输入数据到程序或系统中的流。输入流的作用是将外部的数据输入到计算机系统中,以供程序或系统进行处理。
操作系统中的输入流通常涉及以下几个概念:
-
标准输入流(Standard Input):标准输入流是指与程序的输入相关联的默认输入流。在大多数操作系统中,它通常表示键盘输入。当程序从标准输入流中读取数据时,它会从键盘接收用户的输入。
-
文件输入流(File Input):文件输入流是指从文件中读取数据的流。在操作系统中,文件输入流用于从文件中读取数据到程序中,允许程序对文件进行读取和处理。
-
网络输入流(Network Input):网络输入流是指从网络连接中读取数据的流。在网络编程中,程序可以通过网络输入流从网络连接中接收数据,允许程序与远程计算机通信和交换数据。
这些输入流的概念在操作系统中扮演着重要的角色,它们为程序提供了从不同来源获取数据的能力,使得程序能够与用户交互、读取文件、处理网络数据等。
在Java中,针对操作系统的输入流,对应的API包括:
-
标准输入流:
- Java标准库提供了System类,它包含了标准输入、输出和错误的静态字段,分别是System.in、System.out和System.err。System.in表示标准输入流,通常与键盘输入关联。
-
文件输入流:
- 文件输入流在Java中通过InputStream的子类FileInputStream来实现。FileInputStream用于从文件中读取字节数据。
-
网络输入流:
- 网络输入流通常通过网络编程API来实现。在Java中,可以使用Socket类来创建网络连接,并通过Socket的InputStream获取网络输入流,从而读取来自网络连接的数据。
字节流与字符流:
字节流和字符流是针对数据的不同处理方式而分类的。在输入流方面,这两种流的区别主要在于处理的数据单位和数据的编码。
-
字节流(Byte Streams):
- 字节流处理的数据单位是字节(8位),适用于处理二进制数据,如图像、音频、视频等。
- 字节流以字节为单位读取和写入数据,不会对数据进行任何解码或编码。
- 典型的字节流类包括InputStream和OutputStream及其子类,如FileInputStream、FileOutputStream等。
-
字符流(Character Streams):
- 字符流处理的数据单位是字符,适用于处理文本数据。
- 字符流可以正确地处理Unicode字符,并且能够根据指定的字符编码将字符转换为字节进行输入输出。
- 字符流提供了Reader和Writer类及其子类来处理字符数据,比如FileReader、FileWriter等。
为什么要区分字节流和字符流呢?
- 字节流适用于处理二进制数据,因为它们不对数据进行任何解码或编码,可以直接传输二进制数据。这在处理图像、音频等二进制文件时非常有用。
- 字符流则更适合处理文本数据,因为它们能够正确地处理字符编码,从而避免了编码问题,并提供了更方便的字符处理方法,比如可以直接读取一行文本数据等。
Java中对于操作系统的API
在Java中,针对操作系统的输入流,对应的API包括:
-
标准输入流:
- Java标准库提供了System类,它包含了标准输入、输出和错误的静态字段,分别是System.in、System.out和System.err。System.in表示标准输入流,通常与键盘输入关联。
-
文件输入流:
- 文件输入流可以是字节流(例如FileInputStream),也可以是字符流(例如FileReader)。
- FileInputStream用于从文件中读取字节数据,而FileReader则用于从文件中读取字符数据。FileReader实际上是使用了InputStreamReader类,将字节流转换为字符流。
import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.Reader; public class Main { public static void main(String[] args) { // 使用字节流读取文件 try { InputStream inputStream = new FileInputStream("input.txt"); int data; while ((data = inputStream.read()) != -1) { System.out.print((char) data); } inputStream.close(); } catch (IOException e) { e.printStackTrace(); } // 使用字符流读取文件 try { Reader reader = new FileReader("input.txt"); int data; while ((data = reader.read()) != -1) { System.out.print((char) data); } reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
-
网络输入流:
- 网络输入流同样也可以是字节流或字符流。
- 对于网络输入流,如果您使用Socket类的getInputStream()方法,则得到的是字节流,可以直接读取字节数据。如果需要字符流,则可以使用InputStreamReader将字节流转换为字符流。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class Main { public static void main(String[] args) { try { URL url = new URL("https://www.example.com"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // 使用字节流读取网络数据 InputStream inputStream = connection.getInputStream(); int data; while ((data = inputStream.read()) != -1) { System.out.print((char) data); } inputStream.close(); System.out.println(); // 使用字符流读取网络数据 BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } reader.close(); connection.disconnect(); } catch (IOException e) { e.printStackTrace(); } } }
在这个示例中,我们使用了URL类来创建网络连接,并使用HttpURLConnection类来打开连接。第一个try块中使用了字节流来读取网络数据,而第二个try块中使用了字符流来读取同一个网络数据。在接下来的文章中,我还会继续介绍有关网络编程的知识。
Scanner
Scanner类实际上不属于上述提到的输入流(即字节输出流和字符输出流)。它是一个独立的类,用于处理从各种输入源读取数据的任务。
Scanner类提供了方便的方法来从输入源中读取数据,例如标准输入、文件、字符串等。它可以处理各种数据类型(整数、浮点数、字符串等)并提供了灵活的方式来解析输入。
虽然Scanner类的工作原理与输入流类似,但它是专门设计用于解析输入数据的,而不是像输入流那样直接从源中读取原始数据。因此,Scanner类通常被用于从标准输入或其他数据源中解析数据,而不是作为输入流来直接处理数据流。
Scanner类的一些常用方法包括:
nextInt()
:读取并返回下一个整数。nextDouble()
:读取并返回下一个双精度浮点数。next()
:读取并返回下一个字符串,以空白字符(空格、制表符、换行符等)作为分隔符。hasNextInt()
:检查是否还有下一个整数可读。hasNext()
:检查是否还有下一个单词(字符串)可读。useDelimiter(String pattern)
:设置用于分隔输入的定界符模式。
二、输出流
操作系统的输出流(OS Output Stream)指的是操作系统中用于向外部写入数据的流。在操作系统级别,输出流可以是任何将数据写入到外部设备或目的地的通道,比如写入到屏幕、文件、网络连接等。
在Java中,要向外部写入数据,您可以使用Java I/O库提供的OutputStream类及其子类。这些类可以将数据写入到文件、网络连接、内存中等各种目的地。以下是一些常见的Java输出流类及其对应的操作系统输出流:
-
FileOutputStream(文件输出流):
- Java中的FileOutputStream类用于将数据写入到文件中。它创建了一个与文件相关联的输出流,可以向文件中写入字节数据。
- 操作系统级别的文件输出流将数据写入到文件系统中的文件。
-
SocketOutputStream(套接字输出流):
- Java中的SocketOutputStream类用于将数据写入到套接字连接中,用于进行网络编程。
- 操作系统级别的套接字输出流将数据写入到与套接字相关联的网络连接中,用于在网络上发送数据。
-
BufferedOutputStream(缓冲输出流):
- Java中的BufferedOutputStream类是一个缓冲输出流,它使用缓冲区来提高写入性能。
- 操作系统级别的缓冲输出流将数据先写入到内存缓冲区中,然后再由操作系统将缓冲区中的数据写入到目的地。
-
DataOutputStream(数据输出流):
- Java中的DataOutputStream类是一个数据输出流,用于写入Java基本数据类型的数据到输出流中。
- 操作系统级别的数据输出流将数据按照特定的格式写入到输出流中。
这些Java输出流类提供了一种方便的方式来将数据写入到不同的目的地,从而与操作系统的输出流进行交互。在使用这些输出流类时,Java会在底层与操作系统的输出流进行交互,以将数据写入到目的地。