java io 流

java io 流

io 流總覽

io.png

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ù)類型的讀取和寫入消恍,采用裝飾者模式,能裝飾在其他流上

DataOutputStreamOutputStream 的基礎上新增了如下接口:

  • writeBoolean: 寫入一個 boolean 值
  • writeByte: 寫入一個字節(jié)
  • writeShort: 寫入一個短整型
  • writeInt: 寫入一個整型
  • writeLong: 寫入一個長整型
  • writeFloat: 寫入一個浮點型
  • writeDouble: 寫入一個雙精度浮點型
  • writeChar: 寫入一個字符
  • writeUTF: 寫入一個 unicode 字符串

DataInputStreamInputStream 的基礎上新增了如下接口:

  • 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ū)大小取董,會拋出異常

PushbackInputStreamInputStream 的基礎上新增了如下接口:

  • 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é)流

PipedInputStreamPipedOutputStream 通過調(diào)用 connect 方法建立連接无宿,往 PipedOutputStream 寫入茵汰,能從 PipedInputStream 讀取,這種管道模式是一對一的孽鸡,對一個管道流建立兩次連接會拋出異常

PipedOutputStreamOutputStream 的基礎上提供如下接口:

  • connect: 與一個 PipedInputStream 建立連接蹂午,如果已經(jīng)建立連接栏豺,將拋出異常

PipedInputStreamInputStream 的基礎上提供如下接口:

  • 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)造箫踩,可以指定編碼

BufferedWriterWriter 的基礎上读处,新增了如下接口:

  • newLine: 寫入一個換行符

BufferedReaderReader 的基礎上鲜戒,新增了如下接口:

  • 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

InputStreamReaderOutputStreamWriter 能將字節(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 支持行號的字符流

LineNumberReaderReader 的基礎上缔恳,新增了如下接口:

  • 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ū)大小,會拋出異常

PushbackReaderReader 的基礎上新增了如下接口:

  • 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()));

管道字符流

PipedReaderPipedWriter 通過調(diào)用 connect 方法建立連接纸泄,往 PipedWriter 寫入,能從 PipedReader 讀取襟雷,這種管道模式是一對一的刃滓,對一個管道流建立兩次連接會拋出異常

PipedWriterWriter 的基礎上提供如下接口:

  • connect: 與一個 PipedReader 建立連接,如果已經(jīng)建立連接耸弄,將拋出異常

PipedReaderReader 的基礎上提供如下接口:

  • 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();
}

鏈接

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市捌显,隨后出現(xiàn)的幾起案子茁彭,更是在濱河造成了極大的恐慌,老刑警劉巖扶歪,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件理肺,死亡現(xiàn)場離奇詭異,居然都是意外死亡善镰,警方通過查閱死者的電腦和手機妹萨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來炫欺,“玉大人乎完,你說我怎么就攤上這事∑仿澹” “怎么了树姨?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長桥状。 經(jīng)常有香客問我帽揪,道長,這世上最難降的妖魔是什么辅斟? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任台丛,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘挽霉。我一直安慰自己防嗡,他們只是感情好,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布侠坎。 她就那樣靜靜地躺著蚁趁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪实胸。 梳的紋絲不亂的頭發(fā)上他嫡,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機與錄音庐完,去河邊找鬼钢属。 笑死,一個胖子當著我的面吹牛门躯,可吹牛的內(nèi)容都是我干的淆党。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼讶凉,長吁一口氣:“原來是場噩夢啊……” “哼染乌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起懂讯,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤荷憋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后褐望,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體勒庄,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年瘫里,在試婚紗的時候發(fā)現(xiàn)自己被綠了实蔽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡减宣,死狀恐怖盐须,靈堂內(nèi)的尸體忽然破棺而出玩荠,到底是詐尸還是另有隱情漆腌,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布阶冈,位于F島的核電站闷尿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏女坑。R本人自食惡果不足惜填具,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧劳景,春花似錦誉简、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至筋量,卻和暖如春烹吵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背桨武。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工肋拔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人呀酸。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓凉蜂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親七咧。 傳聞我的和親對象是個殘疾皇子跃惫,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 一、IO流的概念 Java的IO流是實現(xiàn)輸入/輸出的基礎艾栋,它可以方便地實現(xiàn)數(shù)據(jù)的輸入/輸出操作爆存,在Java中把不同...
    Android進階與總結(jié)閱讀 1,747評論 0 7
  • Java.io 包幾乎包含了所有操作輸入、輸出需要的類蝗砾。所有這些流類代表了輸入源和輸出目標先较。Java.io 包中的...
    Marlon666閱讀 188評論 0 0
  • 1.流的分類 (1)輸入輸出流輸入輸出是針對程序運行的內(nèi)存而言的輸入流的基類:InputStream,Reader...
    ql2012jz閱讀 574評論 0 3
  • 本篇文章主要圍繞字符編碼展開悼粮,為了能夠更好地講述這一主題闲勺,我將從字節(jié)流操作中文數(shù)據(jù)開始。 字節(jié)流操作中文數(shù)據(jù) 假設...
  • 標準輸入輸出扣猫,文件的操作菜循,網(wǎng)絡上的數(shù)據(jù)流,字符串流申尤,對象流癌幕,zip文件流等等,java中將輸入輸出抽象稱為流昧穿,就好...
    navy_legend閱讀 703評論 0 0