java io 流
io 流總覽
io 流主要提供四個接口
-
InputStream
: 輸入字節(jié)流 -
OutputStream
: 輸出字節(jié)流 -
Reader
: 輸入字符流 -
Writer
: 輸出字符流
InputStream
InputStream
輸入字節(jié)流玄窝,關注字節(jié)的讀取蹋辅,io 包提供如下 InputStream 的實現(xiàn)
-
ByteArrayInputStream
: 字節(jié)數(shù)組輸入流 -
FileInputStream
: 文件字節(jié)輸入流 -
PipedInputStream
: 管道輸入流婚瓜,可和其他的 PipedOutStream 連接鞍恢,通常用于線程間通信 -
DataInputStream
: 二進制數(shù)據(jù)輸入流 -
ObjectInputStream
: 對象輸入流 -
BufferedInputStream
: 帶緩沖 buffer 的字節(jié)輸入流 -
SequenceInputStream
: 能將多個字節(jié)流合并成一個 -
PushbackInputStream
: 能回退的字節(jié)流
InputStream
提供如下接口:
-
read
: 從流中讀取一個字節(jié) -
read(buffer)
: 從流中讀取字節(jié)到 buffer 中,返回真實讀取的字節(jié)數(shù) -
read(buffer, offset, length)
: 從流中讀取 length 個字節(jié)石抡,寫入到 buffer 的 offset 處作煌,返回真實讀取的字節(jié)數(shù) -
readNBytes(buffer, offset, length)
: 和 read 一樣,但是保證讀取 length 個字節(jié)匕荸,除非流中沒有數(shù)據(jù) -
readAllBytes
: 讀取所有字節(jié),返回一個字節(jié)數(shù)組 -
skip
: 跳過前 n 個字節(jié) -
available
: 剩余字節(jié)數(shù) -
mark
: 標記當前讀取的位置 -
reset
: 將流指針重置到上次標記的位置 -
close
: 關閉流枷邪,釋放資源
{
InputStream in = new ByteArrayInputStream("0123456789".getBytes());
assertEquals(in.read(), '0');
}
{
InputStream in = new ByteArrayInputStream("0123456789".getBytes());
byte[] buf = new byte[4];
assertEquals(in.read(buf), 4);
assertArrayEquals(buf, "0123".getBytes());
}
{
InputStream in = new ByteArrayInputStream("0123456789".getBytes());
byte[] buf = new byte[20];
assertEquals(in.read(buf), 10);
assertArrayEquals(Arrays.copyOf(buf, 10), "0123456789".getBytes());
}
{
InputStream in = new ByteArrayInputStream("0123456789".getBytes());
byte[] buf = new byte[20];
assertEquals(in.read(buf, 1, 4), 4);
assertArrayEquals(Arrays.copyOfRange(buf, 1, 1 + 4), "0123".getBytes());
}
{
InputStream in = new ByteArrayInputStream("0123456789".getBytes());
byte[] buf = new byte[20];
assertEquals(in.readNBytes(buf, 1, 4), 4);
assertArrayEquals(Arrays.copyOfRange(buf, 1, 1 + 4), "0123".getBytes());
}
{
InputStream in = new ByteArrayInputStream("0123456789".getBytes());
assertArrayEquals(in.readAllBytes(), "0123456789".getBytes());
}
{
InputStream in = new ByteArrayInputStream("0123456789".getBytes());
assertEquals(in.skip(2), 2);
assertEquals(in.available(), 8);
assertEquals(in.read(), '2');
assertEquals(in.available(), 7);
in.mark(0);
assertEquals(in.read(), '3');
in.reset();
assertEquals(in.available(), 7);
assertEquals(in.read(), '3');
in.close();
}
{
InputStream in = new ByteArrayInputStream("0123456789".getBytes());
for (int ch = in.read(); ch != -1; ch = in.read()) {
System.out.println(ch);
}
}
OutputStream
OutputStream
輸出字節(jié)流榛搔,關注字節(jié)的寫入,io 包提供了如下 OutputStream 的實現(xiàn)
-
ByteArrayOutputStream
: 輸出 byte 數(shù)組 -
FileOutputStream
: 文件輸出流 -
PipedOutputStream
: 管道輸出流东揣,可和其他的 PipedInputStream 連接践惑,通常用于線程間通信 -
DataOutputStream
: 二進制數(shù)據(jù)輸出流 -
ObjectOutputStream
: 對象輸出流 -
BufferedOutputStream
: 帶緩沖 buffer 的輸出流 -
SequenceOutputStream
: 能將多個輸出流合并成一個
OutputStream
提供如下接口:
-
write
: 寫入一個字節(jié) -
write(buffer)
: 寫入 buffer 中的數(shù)據(jù) -
write(buffer, offset, length)
: 寫入 buffer 從 offset 起的 length 個字節(jié)的數(shù)據(jù) -
flush
: 將緩沖區(qū)的數(shù)據(jù)刷到實際的存儲中 -
close
: 關閉流
OutputStream out = new ByteArrayOutputStream();
out.write('0');
out.write("123456789".getBytes());
out.write("0123456789".getBytes(), 1, 2);
out.flush();
out.close();
Reader
Reader
字符輸入流,關注字符的讀取嘶卧,io 包提供如下 Reader
的實現(xiàn)
-
CharArrayReader
: 字符數(shù)組輸入流 -
FileReader
: 文件字符輸入流 -
PipedReader
: 管道輸入流尔觉,可以和PipedWriter
連接,通常用于線程間通信 -
StringReader
: 字符串輸入流 -
BufferedReader
: 帶緩沖 buffer 的字符輸入流 -
LineNumberReader
: 帶行號的字符輸入流 -
PushbackReader
: 能回退的字符輸入流 -
InputStreamReader
: 輸入字節(jié)流轉(zhuǎn)字符流
Reader
提供如下接口:
-
read
: 從流中讀取一個字符 -
read(buffer)
: 從流中讀取字符到 buffer 中芥吟,返回真實讀取的字符數(shù) -
read(buffer, offset, length)
: 從流中讀取 length 個字符侦铜,寫入到 buffer 的 offset 處,返回真實讀取的字符數(shù) -
read(CharBuffer
: 從流中讀取字符到 CharBuffer 中钟鸵,返回真實讀取的字符數(shù) -
skip
: 跳過前 n 個字符 -
mark
: 標記當前讀取的位置 -
reset
: 將流指針重置到上次標記的位置 -
close
: 關閉流钉稍,釋放資源
{
Reader reader = new CharArrayReader("0123456789".toCharArray());
assertEquals(reader.read(), '0');
}
{
Reader reader = new CharArrayReader("0123456789".toCharArray());
char[] buf = new char[4];
assertEquals(reader.read(buf), 4);
assertArrayEquals(buf, "0123".toCharArray());
}
{
Reader reader = new CharArrayReader("0123456789".toCharArray());
char[] buf = new char[20];
assertEquals(reader.read(buf), 10);
assertArrayEquals(Arrays.copyOf(buf, 10), "0123456789".toCharArray());
}
{
Reader reader = new CharArrayReader("0123456789".toCharArray());
char[] buf = new char[20];
assertEquals(reader.read(buf, 1, 4), 4);
assertArrayEquals(Arrays.copyOfRange(buf, 1, 1 + 4), "0123".toCharArray());
}
{
Reader reader = new CharArrayReader("0123456789".toCharArray());
CharBuffer buf = CharBuffer.allocate(20);
assertEquals(reader.read(buf), 10);
}
{
Reader reader = new CharArrayReader("0123456789".toCharArray());
assertTrue(reader.ready());
assertEquals(reader.skip(2), 2);
assertEquals(reader.read(), '2');
reader.mark(0);
assertEquals(reader.read(), '3');
reader.reset();
assertEquals(reader.read(), '3');
reader.close();
}
{
Reader reader = new CharArrayReader("0123456789".toCharArray());
for (int ch = reader.read(); ch != -1; ch = reader.read()) {
System.out.println(ch);
}
}
Writer
Writer
字符輸出流,關注字符的寫入棺耍,io 包提供如下 Writer
的實現(xiàn)
-
CharArrayWriter
: 字符數(shù)組輸出流 -
FileWriter
: 文件字符輸出流 -
PipedWriter
: 管道輸出流贡未,可以和PipedReader
連接,通常用于線程間通信 -
StringWriter
: 字符串輸出流 -
BufferedWriter
: 帶緩沖 buffer 的字符輸出流 -
OutputStreamWriter
: 輸出字節(jié)流轉(zhuǎn)字符流
Writer
提供如下接口:
-
write(char)
: 寫入一個字符 -
write(string)
: 寫入一個字符串 -
write(string, offset, length)
: 寫入 string 從 offset 起的 length 個字符的數(shù)據(jù) -
write(char[])
: 寫入字符數(shù)組中的數(shù)據(jù) -
write(char[], offset, length)
: 寫入字符數(shù)組從 offset 起的 length 個字符的數(shù)據(jù) -
append(ch)
: 寫入一個字符蒙袍,和 write 一樣 -
append(CharSequence)
: 寫入字符序列的所有數(shù)據(jù)(String, StringBuilder, StringBuffer 都是 CharSequence 的子類) -
append(CharSequence, offset, length)
: 寫入字符序列從 offset 起的 length 個字符的數(shù)據(jù) -
flush
: 將緩沖區(qū)的數(shù)據(jù)刷到實際的存儲中 -
close
: 關閉流
Writer writer = new CharArrayWriter();
writer.write('0');
writer.write("0123456789");
writer.write("0123456789", 1, 4);
writer.write("0123456789".toCharArray());
writer.write("0123456789".toCharArray(), 1, 4);
writer.append('0');
writer.append(new StringBuilder("0123456789"));
writer.append(new StringBuilder("0123456789"), 1, 4);
writer.flush();
writer.close();
文件字節(jié)流
文件字節(jié)流關注文件的讀取和寫入
{
FileOutputStream fout = new FileOutputStream("/tmp/test.txt");
fout.write("No patient who, who has no wisdom".getBytes());
fout.close();
}
{
FileInputStream fin = new FileInputStream("/tmp/test.txt");
assertArrayEquals(fin.readAllBytes(), "No patient who, who has no wisdom".getBytes());
fin.close();
}
緩沖字節(jié)流
緩沖字節(jié)流采用裝飾者模式俊卤,裝飾在其他流上,使流擁有了緩存功能害幅,從而提高讀寫了效率
{
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("/tmp/test.txt"));
bout.write("People lack the willpower, rather than strength".getBytes());
bout.close();
}
{
BufferedInputStream bin = new BufferedInputStream(new FileInputStream("/tmp/test.txt"));
assertArrayEquals(bin.readAllBytes(), "People lack the willpower, rather than strength".getBytes());
bin.close();
}
二進制字節(jié)流
二進制字節(jié)流關注在基本數(shù)據(jù)類型的讀取和寫入消恍,采用裝飾者模式,能裝飾在其他流上
DataOutputStream
在 OutputStream
的基礎上新增了如下接口:
-
writeBoolean
: 寫入一個 boolean 值 -
writeByte
: 寫入一個字節(jié) -
writeShort
: 寫入一個短整型 -
writeInt
: 寫入一個整型 -
writeLong
: 寫入一個長整型 -
writeFloat
: 寫入一個浮點型 -
writeDouble
: 寫入一個雙精度浮點型 -
writeChar
: 寫入一個字符 -
writeUTF
: 寫入一個 unicode 字符串
DataInputStream
在 InputStream
的基礎上新增了如下接口:
-
readBoolean
: 讀取一個 boolean 值 -
readByte
: 讀取一個字節(jié) -
readShort
: 讀取一個 short -
readInt
: 讀取一個整型 -
readLong
: 讀取一個長整型 -
readFloat
: 讀取一個浮點型 -
readDouble
: 讀取一個雙精度浮點型 -
readChar
: 讀取一個字符 -
readUTF
: 讀取一個 unicode 字符串
{
DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("/tmp/test.txt")));
dout.writeBoolean(false);
dout.writeByte('x');
dout.writeShort(123);
dout.writeInt(123456);
dout.writeLong(123456789);
dout.writeFloat((float) 123.456);
dout.writeDouble(123.456);
dout.writeUTF("Rome wasn’t built in one day");
dout.close();
}
{
DataInputStream din = new DataInputStream(new BufferedInputStream(new FileInputStream("/tmp/test.txt")));
assertEquals(din.readBoolean(), false);
assertEquals(din.readByte(), 'x');
assertEquals(din.readShort(), 123);
assertEquals(din.readInt(), 123456);
assertEquals(din.readLong(), 123456789);
assertEquals(din.readFloat(), (float) 123.456);
assertEquals(din.readDouble(), 123.456);
assertEquals(din.readUTF(), "Rome wasn’t built in one day");
din.close();
}
對象字節(jié)流
對象字節(jié)流關注對象的寫入和讀取以现,同時擁有二進制字節(jié)流的所有功能哺哼,同樣采用裝飾者模式
ObjectOutputStream
相比 DataOutputStream
新增了如下接口:
-
writeObject
: 寫入任何 Serializable 對象
ObjectInputStream
相比 DataInputStream
新增了如下接口:
-
readObject
: 從流中讀取一個對象
{
ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("/tmp/test.txt")));
oout.writeBoolean(false);
oout.writeByte('x');
oout.writeShort(123);
oout.writeInt(123456);
oout.writeLong(123456789);
oout.writeFloat((float) 123.456);
oout.writeDouble(123.456);
oout.writeUTF("Nothing is impossible to a willing heart");
oout.writeObject(new Point(123, 456));
oout.close();
}
{
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(new FileInputStream("/tmp/test.txt")));
assertEquals(oin.readBoolean(), false);
assertEquals(oin.readByte(), 'x');
assertEquals(oin.readShort(), 123);
assertEquals(oin.readInt(), 123456);
assertEquals(oin.readLong(), 123456789);
assertEquals(oin.readFloat(), (float) 123.456);
assertEquals(oin.readDouble(), 123.456);
assertEquals(oin.readUTF(), "Nothing is impossible to a willing heart");
Point point = (Point) oin.readObject();
assertEquals(point.x, 123);
assertEquals(point.y, 456);
oin.close();
}
回退字節(jié)流
可回退字節(jié)流內(nèi)部維護了一個固定大小的緩沖區(qū)(可通過構(gòu)造函數(shù)配置 buffer 的大小),允許將字節(jié)回退到緩沖區(qū)叼风,如果超過了緩沖區(qū)大小取董,會拋出異常
PushbackInputStream
在 InputStream
的基礎上新增了如下接口:
-
unread
: 回退一個字節(jié) -
unread(buffer)
: 將 buffer 中的數(shù)據(jù)回退到流的緩沖區(qū) -
unread(buffer, offset, length)
: 從 buffer 的 offset 處回退 length 個字節(jié)到流緩沖區(qū)
PushbackInputStream pin = new PushbackInputStream(new ByteArrayInputStream("Failure is the mother of success".getBytes()), 10);
byte[] buf = new byte[7];
assertEquals(pin.read(buf), 7);
assertArrayEquals(buf, "Failure".getBytes());
pin.unread(buf);
assertEquals(pin.read(buf), 7);
assertArrayEquals(buf, "Failure".getBytes());
// 超過 buffer 的大小,拋出 IOException
assertThrows(IOException.class, () -> pin.unread("01234567890".getBytes()));
SequenceInputStream
SequenceInputStream
將多個 InputStream
合并成一個
InputStream in1 = new ByteArrayInputStream("For man is man and master of his fate\n".getBytes());
InputStream in2 = new ByteArrayInputStream("Cease to struggle and you cease to live\n".getBytes());
Vector<InputStream> vi = new Vector<>(List.of(in1, in2));
SequenceInputStream sin = new SequenceInputStream(vi.elements());
assertArrayEquals(sin.readAllBytes(), "For man is man and master of his fate\nCease to struggle and you cease to live\n".getBytes());
管道字節(jié)流
PipedInputStream
和 PipedOutputStream
通過調(diào)用 connect
方法建立連接无宿,往 PipedOutputStream
寫入茵汰,能從 PipedInputStream
讀取,這種管道模式是一對一的孽鸡,對一個管道流建立兩次連接會拋出異常
PipedOutputStream
在 OutputStream
的基礎上提供如下接口:
-
connect
: 與一個PipedInputStream
建立連接蹂午,如果已經(jīng)建立連接栏豺,將拋出異常
PipedInputStream
在 InputStream
的基礎上提供如下接口:
-
connect
: 與一個PipedOutputStream
建立連接,如果已經(jīng)建立連接豆胸,將拋出異常
ExecutorService es = Executors.newCachedThreadPool();
PipedInputStream pin = new PipedInputStream();
PipedOutputStream pout = new PipedOutputStream();
pin.connect(pout);
es.execute(() -> {
try {
ObjectOutputStream oout = new ObjectOutputStream(pout);
oout.writeInt(123456);
oout.writeUTF("如果你還沒能找到讓自己熱愛的事業(yè)奥洼,繼續(xù)尋找,不要放棄");
oout.close();
} catch (IOException e) {
e.printStackTrace();
}
});
es.execute(() -> {
try {
ObjectInputStream oin = new ObjectInputStream(pin);
assertEquals(oin.readInt(), 123456);
assertEquals(oin.readUTF(), "如果你還沒能找到讓自己熱愛的事業(yè)晚胡,繼續(xù)尋找灵奖,不要放棄");
oin.close();
} catch (IOException e) {
e.printStackTrace();
}
});
try {
es.shutdown();
while (!es.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
// nothing to do
}
} catch (Exception e) {
e.printStackTrace();
}
文件字符流
文件字符流關注文件的讀取和寫入,使用默認的 utf-8 來編碼
{
FileWriter fw = new FileWriter("/tmp/test.txt");
assertEquals(fw.getEncoding(), "UTF8");
System.out.println(fw.getEncoding());
fw.write("初學者的心態(tài)估盘;擁有初學者的心態(tài)是件了不起的事情");
fw.flush();
fw.close();
}
{
FileReader fr = new FileReader("/tmp/test.txt");
assertEquals(fr.getEncoding(), "UTF8");
StringBuilder sb = new StringBuilder();
for (int ch = fr.read(); ch != -1; ch = fr.read()) {
sb.append((char) ch);
}
assertEquals(sb.toString(), "初學者的心態(tài)瓷患;擁有初學者的心態(tài)是件了不起的事情");
fr.close();
}
緩沖字符流
采用裝飾者模式,裝飾在其他字符流上遣妥,增加緩存功能擅编,提高讀寫性能。Files
提供了緩沖字符流的構(gòu)造箫踩,可以指定編碼
BufferedWriter
在 Writer
的基礎上读处,新增了如下接口:
-
newLine
: 寫入一個換行符
BufferedReader
在 Reader
的基礎上鲜戒,新增了如下接口:
-
readLine
: 讀取一個行隆圆,如果沒有新的行吹菱,返回 null -
lines
: 返回一個java.util.stream.Stream
,支持 java 8 的流式處理
{
// BufferedWriter bw = new BufferedWriter(new FileWriter("/tmp/test.txt"));
BufferedWriter bw = Files.newBufferedWriter(Paths.get("/tmp/test.txt"), Charsets.UTF_8);
bw.write("窮則獨善其身吱韭,達則兼濟天下");
bw.newLine();
bw.write("玉不琢、不成器鱼的,人不學理盆、不知義");
bw.newLine();
bw.close();
}
{
// BufferedReader br = new BufferedReader(new FileReader("/tmp/test.txt"));
BufferedReader br = Files.newBufferedReader(Paths.get("/tmp/test.txt"), Charsets.UTF_8);
assertEquals(br.readLine(), "窮則獨善其身,達則兼濟天下");
assertEquals(br.readLine(), "玉不琢凑阶、不成器猿规,人不學、不知義");
assertEquals(br.readLine(), null);
br.close();
}
{
// BufferedReader br = new BufferedReader(new FileReader("/tmp/test.txt"));
BufferedReader br = Files.newBufferedReader(Paths.get("/tmp/test.txt"), Charsets.UTF_8);
assertThat(br.lines().collect(Collectors.toList()), equalTo(List.of(
"窮則獨善其身宙橱,達則兼濟天下",
"玉不琢姨俩、不成器,人不學师郑、不知義"
)));
br.close();
}
StreamReaderWriter
InputStreamReader
和 OutputStreamWriter
能將字節(jié)流轉(zhuǎn)化字符流环葵,還可以指定編碼
{
OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("/tmp/test.txt"), "utf-8");
ow.write("你究竟是想一輩子賣糖水,還是希望獲得改變世界的機遇");
ow.flush();
ow.close();
}
{
InputStreamReader rw = new InputStreamReader(new FileInputStream("/tmp/test.txt"), "utf-8");
StringBuilder sb = new StringBuilder();
for (int ch = rw.read(); ch != -1; ch = rw.read()) {
sb.append((char) ch);
}
assertEquals(sb.toString(), "你究竟是想一輩子賣糖水宝冕,還是希望獲得改變世界的機遇");
rw.close();
}
字符串流
字符串構(gòu)建的流
{
StringWriter sw = new StringWriter();
sw.write("學而不思則罔张遭,思而不學則殆");
assertEquals(sw.getBuffer().toString(), "學而不思則罔,思而不學則殆");
sw.close();
}
{
StringReader sr = new StringReader("一年之計在于春地梨,一日之計在于晨");
StringBuilder sb = new StringBuilder();
for (int ch = sr.read(); ch != -1; ch = sr.read()) {
sb.append((char) ch);
}
assertEquals(sb.toString(), "一年之計在于春菊卷,一日之計在于晨");
}
LineNumberReader
LineNumberReader
支持行號的字符流
LineNumberReader
在 Reader
的基礎上缔恳,新增了如下接口:
-
setLineNumber
: 設置開始的文件行號,默認是 1 -
getLineNumber
: 獲取當前的文件行號
{
BufferedWriter bw = new BufferedWriter(new FileWriter("/tmp/test.txt"));
bw.write("富貴不能淫\n貧賤不能移\n威武不能屈\n此之謂大丈夫\n");
bw.close();
}
{
LineNumberReader lr = new LineNumberReader(new BufferedReader(new FileReader("/tmp/test.txt")));
List<String> lines = new LinkedList<>();
for (String line = lr.readLine(); line != null; line = lr.readLine()) {
lines.add(lr.getLineNumber() + " " + line);
}
assertThat(lines, equalTo(List.of(
"1 富貴不能淫", "2 貧賤不能移", "3 威武不能屈", "4 此之謂大丈夫"
)));
}
回退字符流
可回退字符流內(nèi)部維護了一個固定大小的緩沖區(qū)(可通過構(gòu)造函數(shù)配置 buffer 的大小)洁闰,允許將字符回退到緩沖區(qū)歉甚,如果超過了緩沖區(qū)大小,會拋出異常
PushbackReader
在 Reader
的基礎上新增了如下接口:
-
unread
: 回退一個字符 -
unread(cbar[])
: 將 buffer 中的數(shù)據(jù)回退到流的緩沖區(qū) -
unread(char[], offset, length)
: 從 buffer 的 offset 處回退 length 個字節(jié)到流緩沖區(qū)
PushbackReader pr = new PushbackReader(new StringReader("蚍蜉撼大樹,可笑不自量"), 10);
char[] buf = new char[5];
assertEquals(pr.read(buf), 5);
assertArrayEquals(buf, "蚍蜉撼大樹".toCharArray());
pr.unread(buf);
assertEquals(pr.read(buf), 5);
assertArrayEquals(buf, "蚍蜉撼大樹".toCharArray());
// 超過 buffer 的大小扑眉,拋出 IOException
assertThrows(IOException.class, () -> pr.unread("01234567890".toCharArray()));
管道字符流
PipedReader
和 PipedWriter
通過調(diào)用 connect
方法建立連接纸泄,往 PipedWriter
寫入,能從 PipedReader
讀取襟雷,這種管道模式是一對一的刃滓,對一個管道流建立兩次連接會拋出異常
PipedWriter
在 Writer
的基礎上提供如下接口:
-
connect
: 與一個PipedReader
建立連接,如果已經(jīng)建立連接耸弄,將拋出異常
PipedReader
在 Reader
的基礎上提供如下接口:
-
connect
: 與一個PipedWriter
建立連接咧虎,如果已經(jīng)建立連接,將拋出異常
ExecutorService es = Executors.newCachedThreadPool();
PipedReader pr = new PipedReader();
PipedWriter pw = new PipedWriter();
pr.connect(pw);
es.execute(() -> {
try {
BufferedWriter bw = new BufferedWriter(pw);
bw.write("活著就是為了改變世界计呈,難道還有其他原因嗎");
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
});
es.execute(() -> {
try {
BufferedReader br = new BufferedReader(pr);
assertEquals(br.readLine(), "活著就是為了改變世界砰诵,難道還有其他原因嗎");
br.close();
} catch (Exception e) {
e.printStackTrace();
}
});
try {
es.shutdown();
while (!es.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
// nothing to do
}
} catch (Exception e) {
e.printStackTrace();
}