Java 基础(十)字节流

字节流-InputStream 和 OutputStream

上篇文章咱们讲了字符流的基本操做,而且经过阅读源码咱们知道,字符流就是基于字节流作的实现——一次读取两个字节组成一个字符。java

InputStream

此抽象类是表示字节输入流的全部类的超类。数组

须要定义 InputStream 子类的应用程序必须老是提供返回下一个输入字节的方法。bash

方法名 方法描述
available() 返回此出入流下一个方法调用能够不受阻塞地今后输入流读取估计字节数
close() 关闭此输入流并释放与该流相关联的全部系统资源
mark(int readlimit) 在此输入流中标记当前的位置
markSupported() 此时此输入流是否支持 mark 和 reset 方法
read() 从输入流中读取数据的下一个字节
read(byte[] b) 从输入流中读取必定数量的字节,并将其存储在缓冲区数组b 中。
reset() 将此流从新定位到最后一次对此输入流调用 mark 方法时的位置
skip(long n) 跳过和丢弃此输入流数据的 n 个字节

OutputStream

此抽象类是表示输出字节流的全部类的超类。输出流接受输出字节并将这些字节发送到某个接收器。ide

须要定义 OutputStream 子类的应用程序必须始终提供至少一种可写入一个输出字节的方法。学习

方法名 方法描述
close() 关闭此出入流并释放与此流有关的全部系统资源
flush() 刷新此输出流并强制写出全部缓冲的输出字节
write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流
write(int b) 将指定字节写入此输出流

FileInputStream 和 FileOutputStream

仍是以以前那个文件读写的 demo 为例,咱们先看一下字节流怎么玩的~ui

try {
        // 建立读取流和写入流
        FileInputStream fis = new FileInputStream("raw.txt");
        FileOutputStream fos = new FileOutputStream("target.txt");
        // 读取单个字符,自动往下读
        byte[] buf = new byte[1024];
        int len;
        while ((len = fis.read(buf)) != -1) {
            fos.write(buf, 0, len);
        }
        fis.close();
        fos.close();
    } catch (IOException e) {
        e.printStackTrace();
}复制代码

使用 I/O 复制图片

这个操做和上面的代码同样,注意图片是二进制数据,只能使用字节流读取,不能使用字符流哦。this

字节流缓冲区

这个和字符流缓冲区基本没差了,直接贴代码吧~spa

try {
        // 建立读取流和写入流
        FileInputStream fis = new FileInputStream("raw.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);
        FileOutputStream fos = new FileOutputStream("target.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        // 读取单个字符,自动往下读
        byte[] buf = new byte[1024];
        int len;
        while ((len = bis.read(buf)) != -1) {
            bos.write(buf, 0, len);
        }
        bis.close();
        bos.close();
    } catch (IOException e) {
        e.printStackTrace();
}复制代码

字节流拷贝video 等大文件

  • 除文本文件以外必须使用字节流
  • 文件比较大的必须使用缓冲区提高效率

代码就补贴了,同上。code

自定义字节流缓冲区

这个和自定义字符流缓冲区同样,实现思想就再也不赘述了,不记得的同窗请翻上一篇笔记。对象

直接贴代码吧,没什么特别的。

class MyBufferedImputStream {
    private InputStream in;
    private byte[] buf = new byte[1024 * 8];
    private int pos = 0;
    private int count = 0;

    public MyBufferedImputStream(InputStream in) {
        this.in = in;
    }

    // 从缓冲区一次读一个字节
    public int read() throws IOException {
        // 经过in对象读取硬盘上的数据,存储在buf
        if (count == 0) {
            count = in.read(buf);
            if (count < 0)
                return -1;
            byte b = buf[pos];
            count--;
            pos++;
            return b;
        } else if (count > 0) {
            byte b = buf[pos];
            pos++;
            count--;
            return b;
        }
        return -1;
    }

    //关闭流
    public void myClose() throws IOException {
        in.close();
    }
}复制代码

读取键盘录入

这个好像超纲了,Android 并不须要读取键盘录入。至于 EditText 是怎么读取键盘录入的,咱们之后学习 EditText 源码的时候再慢慢研究。

Java 里面读取键盘录入主要用的是InputStream in = System.in;,有须要的小伙伴自行研究吧。

转换流 InputStreamReader 和 OutputStreamWriter

java中须要转换流就会使用到转换流,使用到了 InputStreamReader/OutputStreamWriter。

咱们前面也说了 FileReader 继承自InputStreamReader,内部构造方法 new FileInputStream(),所以,咱们知道字符流就是字节流使用了转换流。

仍是写一下代码吧,顺便讲一下上面提到的键盘录入

//获取键盘录入对象
InputStream in = System.in;
//转换
InputStreamReader isr = new InputStreamReader(in);
//提升效率
BufferedReader bur = new BufferedReader(isr);
String line;
try {
    while ((line = bur.readLine()) != null) {
        if (line.equals("over"))
            break;
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}复制代码

没什么意思,写入转换流也是同样的操做,我就不写了。

流操做的规律

  • 读取大文件记得用字*流缓冲区提升效率
  • 读取文本文件优先使用字符流、其他一律用字节流
  • 文件读写操做通常都是使用 FileInput(Output)Stream。