java.io - 目录 | ||
---|---|---|
标准设备输入/输出 | 标准设备输入/输出:System | |
控制台读写类:Console | ||
文件基本处理 | 文件操作类:File | |
文件搜索类:FileFilter、FilenameFilter | ||
文件任意读写类:RandomAccessFile | ||
输入/输出流 | 输入/输出流 - 分类 | |
输入/输出流 - 实现类 | ||
序列化/反序列化 |
流体系:
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
---|---|---|---|---|
抽象类 | InputStream | OutputStream | Reader | Writer |
转换类 | InputStream- Reader |
OutputStream- Writer |
||
第一类:数据源类 | ||||
文件 | File- InputStream |
File- OutputStream |
FileReader | FilerWriter |
数组 | ByteArray- InputStream |
ByteArray- OutputStream |
CharArray- Reader |
CharArray- Writer |
对象 | Object- InputStream |
Object- OutputStream |
||
字符串 | StringBuffer- InputStream |
StringReader | StringWriter | |
第二类:数据流串联类 | ||||
管道 | Pipe- InputStream |
Pipe- OutputStream |
PipeReader | PipeWriter |
序列 | Sequence- InputStream |
|||
第三类:数据流过滤类 | ||||
过滤 | Filter- InputStream |
Filter- OutputStream |
FilterReader | FilterWriter |
缓冲 | Buffered- InputStream |
Buffered- OutputStream |
Buffered- Reader |
Buffered- Writer |
数据 | Data- InputStream |
Data- OutputStream |
||
行号 | LineNumber- InputStream |
LineNumber- Reader |
||
推回 | Pushback- InputStream |
Pushback- Reader |
||
格式化 | PrintStream | PrintWriter |
(一)文件流
graph LR T(["文件流
(低级文件流)"]):::p T --> t("可操作文件
中的内容"):::info t --> A(["按照(读/写)
方向分类"]):::p t --> B(["按照(读/写)
字节数大小分类"]):::b A -.-> |"in(读取)"| a("文件输入流
字节型文件输入流
字符型文件输入流"):::lp A -.-> |"out(写入)"| a2("文件输出流
字节型文件输出流
字符型文件输出流"):::lp B -.-> |"1字节"| b("字节型文件流
FileInputStream
FileOUtputStream"):::lb B -.-> |"1字符
(2字节)"| b2("字符型文件流
FileReader
FileWriter"):::lb classDef p fill:#ddaebd classDef b fill:#aab7d2 classDef g fill:#9ac5bb classDef lp fill:#f4e4e9 classDef lb fill:#d9dfeb classDef lg fill:#ddebe6 classDef info fill:#f6f6f7,color:#737379,stroke-dasharray: 3 3, stroke-width: 2px
(1)FileInputStram
字节型文件输入流
* 继承关系
继承于 InputStream 类(字节型输入流)
* 构造方法
构造方法 | 说明 |
---|---|
(没有无参构造方法) | |
FileInputStram(File file) | 通过File对象构造 |
FileInputStram(String name) | 通过文件路径字符串构造 |
* 常用方法
常用方法 | 说明 | 返回值类型 |
---|---|---|
finalize() | GC对象回收 | |
available() | 返回当前流管道中有多少缓存字节,每次读取一个字节对应的 Unicode 码。(读得到返回 0–65536,读不到返回-1) | int |
🔺 read() | 从输入流中读取单个字节,返回读取的字节数据(Unicode码) | int |
read(byte[]):将输入流内容写入数组里,返回实际读取的字节数。 | int | |
read(byte[] b, int off, int leng):将输入流内容写入数组里,从off位置开始,放入len个字节(不是从数组起点开始),返回实际读取的字节数。 | int | |
skip() | 跳过几个字节读取 | long n |
close() | 关闭流管道(⚠️ 必须要做,最好放在 finally{} 里) |
- read()
创建一个字节型文件输入流,读取文件中的内容。
|
- read(byte[] b)
读取文件内容,装入数组内。返回读取的有效字符个数。
|
- skip()
|
- close()
|
(2)FileOutputStream
字节型文件输出流
* 继承关系
继承于 OutputStream 类
* 构造方法
构造方法 | 说明 |
---|---|
(没有无参构造方法) | |
FileOutputStram(File file) | 利用File对象构造(默认覆盖原文) |
FileOutputStram(File file, Boolean append) | 利用File对象构造、是否将内容追加到文件末尾(true:不覆盖) |
FileOutputStram(String name) | 通过文件路径字符串构造 |
FileOutputStram(String name, Boolean append) | 通过文件路径构造、是否追加到文件末尾 |
* 常用方法
常用方法 | 说明 |
---|---|
*finalize()* | GC对象回收 |
write() | 写入到文件(与read()区别) |
write(int code):将给定code写入文件 (’=’字符char也行,会自动转换) | |
write(byte[]): 将数组内容写入文件流里(String—getByte()) | |
flush() | 刷新:将管道内字节推入文件 |
close() | * 注意:在finally中关闭 |
- write()
|
(3)FileReader
字符型文件输入流
* 继承关系
继承于InputStreamReader 类(字节型输入流)
* 构造方法
构造方法 | 说明 |
---|---|
(没有无参构造方法) | |
FileReader(File file) | 通过File对象构造(默认覆盖原文) |
FIleReader(String fileName) | 通过文件路径字符串构造 |
FileReader(FileDescriptor fd) | 通过文件描述符构建 (文件描述符的有效范围是 0 到 OPEN_MAX) |
* 常用方法
常用方法 | 说明 |
---|---|
🔺 read() | 从输入流中读取单个字符,返回所读取的字符数据 |
int read(char[] cbuf) | 从输入流中最多读取cbuf.length个字符的数据,并将其存储在字符数组cbuf中,返回实际读取的字符数。 |
int read(char[] cbuf, int off, int len) | 从输入流中最多读取len个字符的数据,并将其存储在字符数组cbuf中,从off位置开始存储(并不是从数组起点开始),返回实际读取的字符数。 |
(4)FileWriter
字符型文件输出流
* 继承关系
继承于 OutputStreamWriter 类 (字节型输出流)
* 构造方法
构造方法 | 说明 |
---|---|
(没有无参构造方法) | |
FileWriter(File file) | 利用File对象构建(默认覆盖原文) |
FileWriter(File file, Boolean boolean) | 利用File对象构造、是否将内容追加到文件末尾(true:不覆盖) |
FileWriter(String name) | 通过文件路径字符串构造 |
FileWriter(String name, Boolean boolean) | 通过文件路径字符串构造、是否追加到文件末尾 |
* 常用方法
常用方法 | 说明 |
---|---|
write() | 读取 |
write(char) | |
write(String) |
- write()
|
(5)Demo
① 文件的复制
|
② 文件的加密
|
③ 文件夹的复制
|
(二)对象流
(1)对象序列化
%%{ init: { 'themeVariables': { 'fontSize': '12px' } } }%% graph LR subgraph "应用层1" A("对象"):::lb end subgraph "应用层2" B("对象"):::lb end subgraph "网络协议" C("二进制流"):::p end A --> |"[ 转换 ]
ObjectOutputStream
FileOutputStream"|C C --> |"[ 还原 ]
ObjectInputStream
FileInputStream"|B style 网络协议 fill:#f4e4e9, stroke-dasharray: 3 3, stroke-width: 2px classDef p fill:#ddaebd classDef b fill:#aab7d2 classDef g fill:#9ac5bb classDef lp fill:#f4e4e9 classDef lb fill:#d9dfeb classDef lg fill:#ddebe6 classDef info fill:#f6f6f7,color:#3f3f3f,stroke-dasharray: 3 3, stroke-width: 1px
序列化:对象的持久存储
- ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用,通过在流中使用文件可以实现对象的持久存储。
- ObjectInputStream:用于恢复那些已经序列化存储的对象。确保从流创建的图形中所有对象的类型与Java虚拟机中显示的类相匹配。
序列化细节:
- 读写顺序要一致(对象类型转换异常:java.io.OptionalDataException)
- 要求必须实现 Serializable 或 Externalizable 接口
- 在序列化类中添加 SerialVersionUID,提高版本兼容性
- 序列化对象时默认所有属性都序列化,除 static 和 transit
- 序列化可继承性,若某类实现序列化,其子类也默认实现序列化
(2)方法
readObject()
readObject():负责读取通过对应的 writeObject() 方法写入的数据,为特定类读取和恢复对象的状态。
恢复状态:从 ObjectInputStream 读取数据并将其分配给对象的适当字段。
读取各种数据类型的函数
// 与 ObjectOutputStream write()相对应
boolean readBoolean(); // 读取一个boolean值
byte readByte(); // 读取一个8位的字节
char readChar(); // 读取一个16位的char值
double readDouble(); // 读取一个 64 位的double值
float readFloat(); // 读取一个 32 位的float值
int readInt(); // 读取一个 32 位的int值
long readLong(); // 读取一个 64 位的long值
short readShort(); // 读取一个 16 位的short值
// 从序列化流读取类描述符
protected ObjectStreamClass readClassDescriptor();
// 按名称从流中读取持久字段并使其可用
ObjectInputStream.GetField readFields();
// 允许子类读取并验证它们自己的流头部
protected void readStreamHeader();
// 从 ObjectInputStream 读取“非共享”对象
Object readUnshared();
(3)示例
① 对象序列化
Person 类:
public class Person implements java.io.Serializable {
// 🔹 使用Serializable来实现序列化,让目标类实现Serializable标记接口
private String name;
private int age;
// 注意此处没有提供无参数的构造器:🔻反序列化机制无须通过构造器来初始化Java对象
public Person(String name , int age) {
System.out.println("有参数的构造器");
this.name=name;
this.age=age;
}
// 省略name与age的setter和getter方法
...
}使用 ObjectOutputStream 将一个Person对象写入磁盘文件:
public class WriteObject{
public static void main(String[] args) {
try(
// 🔹(1)创建一个ObjectOutputStream输出流
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("object.txt"))) // 这个输出流是一个处理流,所以必须建立在其他节点流(文件输出流)的基础之上
{
Person per = new Person("孙悟空", 500);
// 🔹(2)调用ObjectOutputStream对象的writeObject()方法输出可序列化对象
oos.writeObject(per); // 将per对象写入输出流
}
catch (IOException ex){
ex.printStackTrace();
}
}
}
// 运行上面程序,将会看到生成了一个object.txt文件,该文件的内容就是Person对象。
② 对象反序列化
从刚刚生成的object.txt文件中读取Person对象:
public class ReadObject {
public static void main(String[] args) {
try(
// 🔹(1)创建一个ObjectInputStream输入流
ObjectInputStream ois=new ObjectInputStream(
new FileInputStream("object.txt"))) // 这个输入流是一个处理流,所以必须建立在其他节点流的基础之上。
{
// 🔹(2)从输入流中读取一个Java对象,并将其强制类型转换为Person类
Person p = (Person)ois.readObject(); // 调用ObjectInputStream对象的readObject()
System.out.println("名字为:" + p.getName()
+ "\n年龄为:" + p.getAge());
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
(三)转换流
转换流(InputStreamReader、OutputStreamWriter),Reader的子类,可以将 InputStream 包装成 Reader。用于实现将字节流转换成字符流。—— 可解决文件乱码问题。
Demo:获取键盘输入
/* 该程序将 System.in 包装成 BufferedReader,
BufferedReader流具有缓冲功能,它可以一次读取一行文本:
以换行符为标志,若没有读到换行符,则程序阻塞,等到读到换行符为止。*/
public class KeyinTest {
public static void main(String[] args) {
try{
// 将 Sytem.in 对象转换成 Reader 对象
InputStreamReader reader = new InputStreamReader(System.in);
// 将普通的Reader包装成BufferedReader
BufferedReader br = new BufferedReader(reader))
String buffer = null;
// 采用循环方式来逐行地读取
while ((buffer = br.readLine()) !=null) {
//如果读取的字符串为"exit",则程序退出
if (buffer.equals("exit")) {
System.exit(1);
}
//打印读取的内容
System.out.println("输入内容为:" + buffer);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}InputStreamReader
Java使用 System.in 代表标准输入(即键盘输入),但这个标准输入流是 InputStream 类的实例,使用不太方便,且键盘输入内容都是文本内容,所以可用 InputStreamReader 将其转换成字符输入流。
BufferedReader
:由于 BufferedReader 具有一个 readLine() 方法,可以非常方便地一次读入一行内容,所以经常把读取文本内容的输入流包装成 BufferedReader,用来方便地读取输入流的文本内容。
🔸 只有字节转字符:因为字符流比字节流操作更方便
(四)管道流
实现了pipe的概念,主要在线程中使用:一个线程可以随时向管道输出流发送数据,另一个线程随时从管道输入流读取数据,实现两个线程间的通信(异步传输数据)。
输入流和输出流必须结合使用:若向连接管道输出流提供数据字节的线程(发送端)不存在,则认为该管道已损坏。
📌 注意:数据的传输方向。
(1)PipedInputStream
管道输入流(接收端)应该连接到管道输出流(发送端)。
graph LR A[["线程1"]] B[["线程2"]] pi(["PipedOutputStream"]):::lp po(["PipedInputStream
提供要写入管道输出流的"]):::g A ==> |"发送"|pi pi -.-> |"|缓冲区"|po po ==> |"读取"|B subgraph "管道输出流|管道输入流" pi po end classDef p fill:#ddaebd classDef b fill:#aab7d2 classDef g fill:#9ac5bb classDef lp fill:#f4e4e9 classDef lb fill:#d9dfeb classDef lg fill:#ddebe6 classDef info fill:#f6f6f7,color:#3f3f3f,stroke-dasharray: 3 3, stroke-width: 1px
* 缓存区:管道输入流包含一个缓存区,可在缓存区限定的范围内将读操作和写操作分离开。
🔺 不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。
* 输入输出流的连接方法(1):构造方法
|
* 输入输出流的连接方法(2):connect()
|
* 常用方法:
|
* 示例:
|
(2)PipedOutputStream
PipedOutputStream 可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是指一个通信管道的发送端,它必须与一个作为接收端的PipedInputStream对象相连。
graph LR A[["线程1"]] B[["线程2"]] pi(["PipedOutputStream"]):::p po(["PipedInputStream"]):::lg A ==> |"发送"|pi pi -.-> |"|缓冲区"|po po ==> |"读取"|B subgraph "管道输出流|管道输入流" pi po end classDef p fill:#ddaebd classDef b fill:#aab7d2 classDef g fill:#9ac5bb classDef lp fill:#f4e4e9 classDef lb fill:#d9dfeb classDef lg fill:#ddebe6 classDef info fill:#f6f6f7,color:#3f3f3f,stroke-dasharray: 3 3, stroke-width: 1px
* 示例:
- 发送者线程Sender:创建了一个输出流 PipedOutputStream 的对象 out,在该线程的主函数 run() 中调用 out 的 write() 写入数据。
- 接收者线程Receiver:创建了一个输入流 PipedInputStream 的对象 in,在该线程的主函数 run() 中调用 in 的 read() 读取数据。
|
(五)序列流
SequenceInputStream 类允许连接多个 InputStream 流,表示其他输入流的逻辑串联。(串行输入流)
%%{ init: { 'themeVariables': { 'fontSize': '12px' } } }%% graph A([InputStream s1]):::lp B([InputStream s2]):::lp C([InputStream s3]):::lp D([InputStream s1]):::lb E([InputStream s2]):::lb A --> B --> C subgraph "(2) SequenceInputStream(e)" subgraph "Enumeration ⟨? extends InputStream⟩ e" A B C end end subgraph "(1) SequenceInputStream(s1, s2)" D --> E end classDef p fill:#ddaebd classDef b fill:#aab7d2 classDef g fill:#9ac5bb classDef lp fill:#f4e4e9 classDef lb fill:#d9dfeb classDef lg fill:#ddebe6 classDef info fill:#f6f6f7,color:#3f3f3f,stroke-dasharray: 3 3, stroke-width: 1px
串联输入源:它从输入流的有序集合开始,从第一个输入流开始读取,读到文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
* 构造函数:
|
* Demo:
|
(六)过滤流
过滤流用于扩展其他流,增强其功能。它包含其他一些输入/输出流,将这些流用做其基本数据源,它可以直接传输数据或提供一些额外的功能。
但是,例如 FilterInputStream 类本身只是简单地重写那些将所有请求传递给所包含输入流的 InputStream 的所有方法。因此,这个类本身对于数据流并没有什么作用。所以通常并不单独使用它们,而是使用它们的子类。
(七)缓冲流
缓冲流主要为输入/输出流缓存数据,因此需要使用 flush() 方法强制将缓存中的数据真正写入到输出流中。(输入流对象的关闭顺序必须与其创建的顺序相反,后面的输出流也是如此。)
(1)BufferedInpuStream
BufferedInputStream为另一个输入流添加一些功能,即缓存输入的能力。
在创建BufferedInputStream时,会创建一个内部缓存区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓存区,一次填充多个字节。
* Demo:
|
(2)BufferedOutputStream
BufferedOutputStream 继承自 FilterOutputStream,它与 BufferedInputStream 相对应,主要为输出流做缓存。
* demo
|
(3)BufferedReader
BufferedReader 从字符输入流中读取文本,缓存各个字符,以实现字符/数组/行的高效读取。
* 构造方法:
📌 Reader所做的每个读取请求都会导致对底层字符或字节流进行相应的读取请求。
因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的Reader(如 FileReader 和InputStreamReader)
|
* Demo:
|
(4)BufferedWriter
BufferedWriter 将文本写入字符输出流,缓存各个字符,从而提供单个字符、数组和字符串的高效写入。
* 使用
📌 通常 Writer 将其输出立即发送到底层字符或字节流。除非要求提示输出,否则建议用 BufferedWriter 包装所有其 write() 操作可能开销很高的 Writer(如FileWriters和OutputStreamWriters)。例如以下案例将缓冲 PrintWriter 对文件的输出。
|
* 输出换行
该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。
并非所有平台都使用新行符(
\n
)来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。
* Demo
|
(八)数据流
(1)DataInputStream
数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本Java数据类型。
* 方法
|
* 类似 ObjectInputStream
|
* Demo
|
*注意:
由于文件 D:/demo/data.tmp 是写入类调用 DataOutputStream 写入的对象,每一个对象的写入都是有顺序的,因此这里的读取也必须采用同样的顺序。如果顺序不一致,将会产生对象类型转换异常 java.io.OptionalDataException,它是IOException的子类。
(2)DataOutputStream
DataOutputStream 与 DataInputStream 相对应,允许应用程序将基本Java数据类型写入输出流中。然后,应用程序可以使用数据输入流 DataInputStream 将数据读入。
* 方法
|
* Demo
|
(九)行号输入流
(1)LineNumberInputStream
LineNumberInputStream 可跟踪行号、设置行号、对行做标记以便恢复等功能。
名词 | 说明 |
---|---|
行 | 以回车符(\r )、换行符(\n )、回车符后紧跟的换行符(\r\n )(三种情况)结尾的字节序列。 |
行号 | 以0开头,并在read返回换行符时递增1。 |
* 方法:(Deprecated)
|
* demo:
|
(2)LineNumberReader
* 构造方法:
由于该类继承自BufferedReader,因此它拥有与BufferedReader相同的两个构造方法:
|
* 方法:
|
* demo:
|
(十)推回输入流
PushbackInputStream 和 PushbackReader 为另一个输入流添加性能,允许将字节(字符)推回到流中:即“推回(pushback)”或“取消读取(unread)”一个字节(字符)的能力。
PushbackInputStream 和 PushbackReader 的3个方法:
方法 说明 void unread(int b) 将一个字节/字符推回到推回缓冲区里,从而允许重复读取刚刚读取的内容。 void unread(byte[]/char[] buf) 将一个字节/字符数组内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容。 void unread(byte[]/char[] b, int off, int len) 将一个字节/字符数组里从off开始,长度为len字节/字符的内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容。 在读取终止字节(字符)后,代码片段可以“取消读取”该字节(字符),这样,输入流上的下一个读取操作将会重新读取被推回的字节(字符)。
处理示意图
需指定缓冲区大小
当创建一个 PushbackInputStream 和 PushbackReader 时需要指定推回缓冲区的大小,默认的推回缓冲区的长度为1。
若程序中推回到推回缓冲区的内容超出了推回缓冲区的大小,将会引发 Pushback buffer overflow 的 IOException 异常。
Demo:
public class TestPushbackInputStream {
public static void main(String[] args) {
try {
// 创建文件输入流
FileInputStream fis = new FileInputStream("D:/demo/test.txt");
// 创建推回输入流
PushbackInputStream pis = new PushbackInputStream(fis);
// 读取对象数据
int c = pis.read();
System.out.print((char)c);
pis.unread(c); // 🔻 推回一个字节
c = pis.read(); // 再次读取
System.out.print((char)c);
// 关闭输入流
pis.close();
fis.close();
} catch (IOException e) {
}
}
}
// 运行该程序将会重复输出第一个字符。
(十一)打印流(格式化)
(1)PrintStream
%%{ init: { 'themeVariables': { 'fontSize': '13px' } } }%% graph LR A(["PrintStream(与OutputStream相比)"]):::p A -.-> a("添加了一组 print() / println() 方法,
可以打印各种数据类型,比较方便。"):::lp A -.-> b("不会抛出IOException"):::lp A -.-> c("自动刷新机制:
写入内容后自动调用flush()方法"):::lp classDef p fill:#ddaebd classDef lp fill:#f4e4e9
(字节型)
PrintStream
是一种 FilterOutputStream,在 OutputStream 的接口上,额外提供了一些写入各种数据类型的方法。以及对应的一组 println() 方法(自动加上换行符)。方法 说明 void print(boolean) 将boolean类型数据对应字符串写到PrintStream流中 void print(char) 将char类型数据对应字符串写到PrintStream流中 void print(int) 将int类型数据对应字符串写到PrintStream流中 void print(long) 将long类型数据对应字符串写到PrintStream流中 void print(float) 将float类型数据对应字符串写到PrintStream流中 void print(double) 将double类型数据对应字符串写到PrintStream流中 void print(char[]) 将字符串数组写到PrintStream流中 void print(String) 将字符串写到PrintStream流中 void print(Obj) 将对象对应字符串写到PrintStream中 🔺 两方法写入数据时都会将数据转换成字符串,实际调用的方法:write(String s)。
ptrint(0x61) = write(String.valueOf(0x61))
(2)PrintWriter
- (字符型)
PrintWriter
扩展了 Writer 接口,它的 print() / println() 方法最终输出的是 char 数据。使用方法同 PrintStream。
(3)重定向标准输入/输出
重定向标准输入/输出
Java的标准输入/输出分别通过 System.in(从键盘输入)和 System.out(输出到屏幕)来代表。而 System 类里提供了如下3个重定向标准输入/输出的方法。
方法 说明 static void setErr(PrintStream err) 重定向 “标准”错误输出流。 static void setIn(InputStream in) 重定向“标准”输入流。 static void setOut(PrintStream out) 重定向 “标准”输出流。 demo:重定向标准输出
/**
* 通过重定向标准输出流,将System.out的输出重定向到文件输出,而不是在屏幕上输出。
*/
public class RedirectOut {
public static void main(String[] args) {
try(
// 一次性创建PrintStream输出流
PrintStream ps=new PrintStream(new FileOutputStream("out.txt")))
{
// 将系统的标准输出重定向到ps输出流
System.setOut(ps);
// 向标准输出输出一个字符串
System.out.println("普通字符串");
// 向标准输出输出一个对象
System.out.println(new RedirectOut());
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}该代码创建了一个 PrintStream 输出流,并将系统的标准输出重定向到该 Print Stream 输出流。运行该程序无任何输出:因为标准输出不再输出到屏幕,而是输出到 out.txt 文件。
demo:重定向标准输入
/**
* 下面程序重定向标准输入,从而可以将System.in重定向到指定文件,而不是键盘输入。
*/
public class RedirectIn {
public static void main(String[] args) {
try(
FileInputStream fis=new FileInputStream("RedirectIn.java"))
{
// 将标准输入重定向到fis输入流
System.setIn(fis);
// 使用System.in创建Scanner对象,用于获取标准输入
Scanner sc=new Scanner(System.in);
// 增加下面一行只把回车作为分隔符
sc.useDelimiter("\n");
// 判断是否还有下一个输入项
while(sc.hasNext())
{
// 输出输入项
System.out.println("键盘输入的内容是:" + sc.next());
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}该代码创建了一个 FileInputStream 输入流,并使用 System 的 setIn() 方法将系统标准输入重定向到该文件输入流。
运行上面程序,程序不会等待用户输入,而是直接输出了 RedirectIn.java 文件的内容,这表明程序不再使用键盘作为标准输入,而是使用指定文件作为标准输入源。
- end -
🔖 笔记来自:
📎 补充: