Java I/O流

最近打算把Java网络编程相关的知识深刻一下(IO、NIO、Socket编程、Netty)java

Java的I/O创建于流之上。输入流读取数据、输出流写入数据编程

输入输出流

输入流

输入流InputStream的API以下:网络

public abstract int read() throws IOException;//-1 到 255
public int read(byte b[]) throws IOException 
public int read(byte b[], int off, int len) throws IOException
public long skip(long n) throws IOException
public int available() throws IOException
public void close() throws IOException

read()方法返回的其实是一个无符号byte(Java中没有无符号byte类型, 就直接用int做为返回值了)性能

read方法返回-1时表明已经读完数据(若是是网络通讯的话就表明对端不会再发送数据)编码

输出流

输出流OutputStreamAPI以下:加密

// OutputStream接口定义的几个方法
public abstract void write(int b) throws IOException;
public void write(byte b[]) throws IOException 
public void write(byte b[], int off, int len) throws IOException
public void flush() throws IOException
public void close() throws IOException

write(int) 方法实际写入的是int的低8位(一个字节)code

尽可能不要使用write(int), 由于每次发送一个字节效率不高(每一个TCP报文都至少有40个字节的网络传输开销, 每次传输数据太少的话信道利用率不高)对象

flush() 将缓冲区中的内容刷到底层输出流blog

关闭流

流对应了底层的文件句柄和端口, 因此使用完成以后必定要关闭接口

下面是常见的一种关闭流的写法(把流的关闭放在finally语句块中),可是可太复杂了!!!

FileInputStream in = null;
  try {
    in = new FileInputStream("/tmp/axt.t");
    //
  } catch (FileNotFoundException e) {
    //
  } finally {
    if (in != null){
      try {
        in.close();
      } catch (IOException e) {
        //
      }
    }
  }

简洁一些的写法

try(FileInputStream in = new FileInputStream("/tmp/a.txt")){
   // do somethind
} catch (Exception e) {
   //
}

由于Java会对try块中申明的全部AutoCloseable类型的对象自动调用close()方法,不须要手动调用!

过滤器流

过滤器流其实是对流功能的加强,使用的是装饰模式。

装饰模式

装饰模式就是在原有的基础上增长了一些新的功能,经过组合实现。

下为过滤器流类结构--装饰模式的体现

过滤器流的做用

下面这段代码对FileInputStream 使用了 BufferedInputStream 和 DataInputStream 进行包裹

使得用户能够直接读取字符, 且是从Java缓冲区中获取(若是缓冲中没有可用数据,再尝试从底层输入流读取)

FileInputStream in = new FileOutputStream("/tmp/a.txt");
in = new BufferedInputStream(in);
in = new DataInputStream(in);
in.readChar();

过滤器流还能够实现解压(ZIPInputStream)、Base64解码(Base64InputStream)等,也能够自定义过滤器流以实现特定功能)

缓冲流

缓冲流做为过滤器流中的一种, 在网络通讯场景下使用缓冲有利于提高发送和接受数据的效率。

因此在发送数据时咱们应该使用BufferedOutputStream, 这样写数据时会先写入到java的缓冲区中, 缓冲区满或者调用flush方法时才会真正的发送数据,可以提高性能(提高信道利用率)

OutputStream out = new FileOutputStream("/tmp/a.txt");
 BufferedOutputStream outputStream = new BufferedOutputStream(out);
 out.write(1);
 out.flush();

数据流

缓冲流做为过滤器流中的一种,提供直接读写Java基本类型的API

OutputStream out = new FileOutputStream("/tmp/a.txt");
 DataOutputStream  dataOutputStream = new DataOutputStream(out);
 dataOutputStream.writeChar('c'); //写字符
 dataOutputStream.writeUTF("ssss"); //写字符串

阅读器和书写器

提供读写字符的API(若是只是ASCII编码, 直接使用字节流便可)

书写器

OutputStreamWriter 提供直接读取字符和字符串的能力

OutputStream out = new FileOutputStream("/tmp/a.txt"); //底层字节流
Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
writer.write("哈哈哈");

缓冲书写器

BufferedWriter 提供一层写缓冲(做用类同字节流的BufferedOutputStream)

Demo

OutputStream out = new FileOutputStream("/tmp/a.txt"); //底层字节流
        Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);//书写器(编码)
        writer = new BufferedWriter(writer, 1000);//缓冲书写器
        for (int i = 0; i < 128; i ++){
            writer.write(i); 
        }
        writer.write("哈哈哈哈哈");//写汉字, utf-8编码可见,若是是ascii编码会乱码
        writer.flush(); //这里其实不用flush, close以前会flush,可是最好有。
        writer.close(); //close流, 释放底层资源。

总结

整体分红两类 字节流 和字符流, 字符流是仅对字节流的装饰(或者说字符流的底层就是字节流)

过滤器流:对基础流增长一些额外的功能 若是缓冲、压缩、加密等

缓冲流:读写数据中间加一层缓冲区,提高数据传输效率。

相关文章
相关标签/搜索