乐趣区

关于java:java-IO流操作

什么是 IO 流?

Java 中 I / O 操作次要是指应用 java.io 包下的内容,进行输出、输入操作。输出也叫做读取数据,输入也叫做作写出数据。

输入输出(IO):
输入输出是指计算机同任何外部设备之间的数据传递。

在 IO 流里,输入输出分为 4 步:格式化 / 解析,缓冲,编码转换和传递。
格式化 / 解析:在外部数据表示(以字节为单位)与内部数据表示(以字符为单位)之间进行双向转换。例如一个 2 字节的整数 10002,就须要 5 个字符来示意。

缓冲:用于在格局 / 解析与传递之间缓存字符序列。对于输入,较短的字符序列格式化之后并不马上输入,而是保留在缓冲区里,待累积到肯定规模之后再传递到外部设备。相同,从外部设备读入的大量数据也是先放在缓冲区,而后逐渐取出实现输出。默认时,IO 流的输入输出都是通过缓冲的,也能够让 IO 流工作在无缓冲模式下。

编码转换:是将一种字符表达式转换成另一种字符表达式。如果格式化产生的字符表达式与内部字符表达式不同(输入时),或者内部表达式与 IO 流能解析的表达式不同(输出时),就必须进行编码转换。如多字节编码与宽字符编码之间的转换等。少数状况下并不需要进行编码转换。

传递:次要是与外部设备进行通信。输入时,传递负责将通过格式化、缓冲即编码转换后的字符序列发送到外部设备;输出时,则负责将外部设备抽取数据,为其后进行的编码转换、缓冲及解析提供字符序列。

IO 流的分类:

依据数据的流向分为:

  • 输出流:把数据从其余设施上读取到内存中的流,只能进行读操作。
  • 输入流:把数据从内存 中写出到其余设施上的流,只能进行写操作。

依据数据的类型分为:

  • 字节流:以字节为单位,读写数据的流。
  • 字符流:以字符为单位,读写数据的流。

字节流和字符流的区别:

  • 读写单位不同:字节流以字节为单位,字符流以字符为单位
  • 解决对象不同:字节流能解决所有类型的数据(如图片、avi 等),而字符流只能解决字符类型的数据。
  • 字节流:一次读入或读出是 8 位二进制。
  • 字符流:一次读入或读出是 16 位二进制。

分类之后对应的超类(超类也就是父类的意思)

输出流 输入流
字节流 字节输出流 InputStream 字节输入流 OutputStream
字符流 字符输出流 Reader 字符输入流 Writer

注:
由这四个类的子类名称根本都是以其父类名作为子类名的后缀。

字节输出流 InputStream:

  • InputStream 是所有的字节输出流 的父类,它是一个抽象类。
  • ByteArrayInputStreamStringBufferInputStreamFileInputStream 是三种根本的介质流,它们别离从 Byte 数组StringBuffer、和 本地文件 中读取数据。
  • PipedInputStream 是从与其它线程共用的管道中读取数据。
  • ObjectInputStream 和所有FilterInputStream 的子类都是装璜流(装璜器模式的配角)。
FileInputStream fis = new FileInputStream("xxx.txt");// 创立流对象    
int b;
while((b = fis.read()) != -1) { // 字节输出流对象 fis 一次读一个字节 并赋值给 b  判断 b 是不是 -1
    System.out.println(b);  
}
fis.close();

字节输入流 OutputStream:

  • OutputStream 是所有的字节输入流 的父类,它是一个抽象类。
  • ByteArrayOutputStreamFileOutputStream 是两种根本的介质流,它们别离向 Byte 数组、和 本地文件 中写入数据。
  • PipedOutputStream 是向与其它线程共用的管道中写入数据。
  • ObjectOutputStream 和所有FilterOutputStream 的子类都是装璜流。
FileOutputStream fos = new FileOutputStream("yyy.txt"); 
fos.write(100);     // 写出的是一个 int 数, 然而到文件上的是一个字节, 会主动去除前三个 8 位
fos.write(99);      // 此时文件 yyy.txt 中是 dc
fos.close();

留神:

1)输入流输入数据在创立输入流对象的时候,如果不存在文件,就创立一个;如果存在就清空该文件数据,而后写入数据。
2)如果想在文件外面追加写入就用 new FileOutputStream(String pathName,true)这个构造方法。

字符输出流:

public int read(): 读取单个字符, 并返回成 int,如果已达到流的开端,则返回 -1
public int read(char[] cbuf):将字符读入数组,返回读取的字符数,如果已达到流的开端,则返回 -1

public static void main(String[] args) throws IOException {FileReader fr = new FileReader("xxx.txt");  // 创立字符输出流对象
    int c;
    
    while((c = fr.read()) != -1) {  // 通过我的项目默认的码表一次读取一个字符
        System.out.print((char)c);  // 将 c 强制类型转换成 char
    }
    fr.close();}

字符输入流:

public void write(int c):写入单个字符。
public void write(char[] cbuf):写入字符数组。
public abstract void write(char[] cbuf,int off, int len):写入字符数组的某一部分。cbuf – 字符数组,off – 开始写入字符处的偏移量,len – 要写入的字符数。
public void write(String str):写入字符串。
public void write(String str,int off, int len):写入字符串的某一部分。str – 字符串,off – 绝对初始写入字符的偏移量,len – 要写入的字符数。

节点流:
间接与数据源相连,读入或读出。

罕用的节点流:

  • 父 类:InputStreamOutputStreamReaderWriter
  • 文 件:FileInputStreamFileOutputStreanFileReaderFileWriter 文件进行解决的节点流
  • 数 组:ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter 对数组进行解决的节点流(对应的不再是文件,而是内存中的一个数组)
  • 字符串:StringReaderStringWriter 对字符串进行解决的节点流
  • 管 道:PipedInputStreamPipedOutputStreamPipedReaderPipedWriter 对管道进行解决的节点流

解决流:
解决流和节点流一块应用,在节点流的根底上,再套接一层,套接在节点流上的就是解决流。

罕用的解决流:

  • 缓冲流:BufferedInputStreanBufferedOutputStreamBufferedReaderBufferedWriter 减少缓冲性能,防止频繁读写硬盘。
  • 转换流:InputStreamReaderOutputStreamReader实现字节流和字符流之间的转换。
  • 数据流:DataInputStreamDataOutputStream 等 - 提供将根底数据类型写入到文件中,或者读取进去。

转换流:
InputStreamReaderOutputStreamWriterInputStreamOutputStream作为参数,实现从字节流到字符流的转换。

序列流:
序列流能够把多个字节输出流整合成一个, 从序列流中读取数据时, 将从被整合的第一个流开始读, 读完一个之后持续读第二个, 以此类推。

1)整合两个输出流 SequenceInputStream(InputStream s1, InputStream s2);

public static void demo2() throws FileNotFoundException, IOException {FileInputStream fis1 = new FileInputStream("a.mp3");
    FileInputStream fis2 = new FileInputStream("b.mp3");
    SequenceInputStream sis = new SequenceInputStream(fis1, fis2);
    FileOutputStream fos = new FileOutputStream("c.mp3");
    // 歌曲串烧,c.mp3 外面有 a.mp3 和 b.mp3 两首歌

    int b;
    while((b = sis.read()) != -1) {fos.write(b);
    }

    sis.close();        //sis 在敞开的时候, 会将构造方法中传入的流对象也都敞开
    fos.close();}

2)整合多个输出流 SequenceInputStream(Enumeration<? extends InputStream> e)

public static void main(String[] args) throws IOException {FileInputStream fis1 = new FileInputStream("a.txt");
    FileInputStream fis2 = new FileInputStream("b.txt");
    FileInputStream fis3 = new FileInputStream("c.txt");

    Vector<FileInputStream> v = new Vector<>();     // 创立汇合对象
    v.add(fis1);                        // 将流对象存储进来
    v.add(fis2);
    v.add(fis3);

    Enumeration<FileInputStream> en = v.elements();
    SequenceInputStream sis = new SequenceInputStream(en);  // 将枚举中的输出流整合成一个
    FileOutputStream fos = new FileOutputStream("d.txt");

    int b;
    while((b = sis.read()) != -1) {fos.write(b);
    }

    sis.close();
    fos.close();}
退出移动版