> 文档中心 > 适合小小白入门的JavaIO文章,学完即可上手

适合小小白入门的JavaIO文章,学完即可上手


IO概述

基本概念

首先我们需要理解的是什么是IO,从字面意思上来看,IO取的是Input和Output的首字母,也就是输入和输出的意思了,即数据的传输。这里的输入和输出是相对于内存等存储设备来说的,流向内存等存储设备是输入,流出内存等存储设备是输出!(IO又称IO流)

关于IO对进程的影响以及IO的同步和异步等本文不做介绍

IO的分类

知道了IO的基本概念后,对IO做一个分类,方便理解和使用。

根据数据的流向分:输入流和输出流

  • 输出流:数据从内存等存储设备写到其他设备上
  • 输入流:数据从其他设备上读取到内存等存储设备上

根据处理数据流的类型分:字符流和字节

  • 字符流:数据流以字符为单位进行传输
  • 字节流:数据流以字节为单位进行传输

根据数据流的功能分:节点流和处理流

  • 节点流:在某一个特定节点进行数据读写,直接连接数据源
  • 处理流:对一个已存在的流进行连接和封装,通过所封装的流的功能调用实现数据读写,不直接连接数据源

基本介绍

字节流

我们都知道在计算机中所有的内容都是以二进制数字的形式存储的,也就是可以看作字节(计算机信息技术用于计量存储容量的一种计量单位,一个字节存储8位无符号数,储存的数值范围为0-255)。那么,从这里来看,我们传输任何数据都是可以以字节流进行的。

字节输出流

字节输出流是OutputStream,它是java.io.OutputStream抽象类,它定义了字节输出流中的有些基本的方法,其子类会有更加详细的具体功能的实现。下面介绍它的接种常见方法:

  • public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
  • public void flush() :刷新输出流,使缓存数据被写出来。
  • public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
  • public void write(byte[] b, int off, int len) :写 len字节指定字节数组中的偏移 off开始到输出流。
  • public abstract void write(int b) :将指定的字节写入该输出流中。

close()方法是必须要调用的,因为IO流不能自动关闭,需要手动调用该方法以释放占用的资源

该抽象类有很多子类,下面介绍一个入门级且很常用的子类:FileOutputStream
适合小小白入门的JavaIO文章,学完即可上手

FilterOutputStream

文件输出流是File或FileDescriptor数据写入输出流。其目的是将数据写到文件中。

构造方法

  • FileOutputStream(File file) :创建一个文件输出流写入指定的 File对象表示的文件。
  • FileOutputStream(File file, boolean append) :创建一个文件输出流写入指定的 File对象表示的文件。
  • FileOutputStream(String name): 创建一个文件输出流,用指定的名称写入文件。
  • FileOutputStream(String name, boolean append) :创建一个文件输出流,用指定的名称写入文件。

当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件。如果有这个文件,会清空这个文件的数据。

常用方法

  • void close() :关闭此文件输出流并释放与此流关联的任何系统资源。
  • void write(byte[] b) :写 b.length字节从指定的字节数组来此文件输出流。
  • void write(byte[] b, int off, int len) :写 len字节指定字节数组中的起始偏移 off此文件输出流。
  • void write(int b) :将指定的字节写入该文件输出流中。
  • public FileOutputStream(File file, boolean append): 创建文件输出流以写入由指定的 File对象表示的文件。
  • public FileOutputStream(String name, boolean append): 创建文件输出流以指定的名称写入文件。

代码实例

import org.junit.Test;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;public class OutPutStreamDemo1 {    public static void main(String[] args) throws IOException { //创建操作文件输出流对象 OutputStream outputStream = new FileOutputStream("(你自己的文件位置)\\test.txt"); //向文件写入内容 outputStream.write(97); outputStream.write(98); outputStream.write(99); //关闭输出流 outputStream.close();    }    @Test    public void outFile01() throws Exception { //创建操作文件输出流对象 OutputStream out = new FileOutputStream("(你自己的文件位置)\\test.txt"); //写内容 byte[] b = "test".getBytes(); out.write(b); //关闭 out.close();    }    @Test    public void outFile02() throws Exception { //创建操作文件输出流对象 OutputStream out = new FileOutputStream("(你自己的文件位置)\\test.txt"); //写内容 byte[] b = "abcde".getBytes(); //write 第一个参数开始位置 索引 //      第二个参数 从开始位置几个字符 out.write(b,2,2); //关闭 out.close();    }    //追加操作    @Test    public void outFile03() throws Exception { //创建操作文件输出流对象 //可以实现追加 OutputStream out = new FileOutputStream("(你自己的文件位置)\\test.txt",true);  //写内容 byte[] b = "append".getBytes(); //write 第一个参数开始位置 索引 //      第二个参数 从开始位置几个字符 //out.write(b,0,6); out.write(b,2,2); //关闭 out.close();    }}

字节输入流

字节输入流是InputStream,它是java.io.InputStream抽象类,它定义了字节输入流中的有些基本的方法,其子类会有更加详细的具体功能的实现。下面介绍它的接种常见方法:

  • void close() :关闭此输入流并释放与流关联的任何系统资源。
  • abstract int read() :从输入流读取下一个数据字节。
  • int read(byte[] b) :读取一定数量的字节从输入流并存入缓冲区阵列 b。
  • int read(byte[] b, int off, int len) :读到 len字节从输入流读入字节数组数据。

close()方法是必须要调用的,因为IO流不能自动关闭,需要手动调用该方法以释放占用的资源

该抽象类有很多子类,下面介绍一个入门级且很常用的子类:FileInputStream
适合小小白入门的JavaIO文章,学完即可上手

FileInputStream

FileInputStream从文件系统中的文件获得输入的字节

构造方法

  • FileInputStream(File file) : 连接到实际的文件创建一个FileInputStream,文件在文件系统的 File对象 file命名。
  • FileInputStream(String name) :连接到实际的文件创建一个FileInputStream,文件由文件系统中的路径名 name命名。

常用方法

  • void close() :关闭此文件输入流并释放与流关联的任何系统资源。
  • int read() :从这个输入流读取一个字节的数据。
  • int read(byte[] b) :读到 b.length从输入流到字节数组数据字节。
  • int read(byte[] b, int off, int len) :读到 len从输入流到字节数组数据字节。

代码实例

import org.junit.Test;import java.io.*;public class InPutStreamDemo1 {    public static void main(String[] args) throws Exception { //创建操作文件输入流对象 InputStream inputStream = new FileInputStream("F:\\study\\程序员学习\\尚硅谷\\尚硅谷-大数据大神班2021(JD)\\阶段一\\1.javase&mysql\\02Javase-王泽\\05-JavaSE-Map和文件与IO\\test.txt"); //读取文件内容 int read = inputStream.read(); System.out.println((char) read); //关闭 inputStream.close();    }    @Test    public void readFile01() throws Exception { //创建操作文件输入流对象 InputStream inputStream = new FileInputStream("F:\\study\\程序员学习\\尚硅谷\\尚硅谷-大数据大神班2021(JD)\\阶段一\\1.javase&mysql\\02Javase-王泽\\05-JavaSE-Map和文件与IO\\test.txt"); //定义变量 int b; //循环判断读取 while((b = inputStream.read())!=-1) {     System.out.println((char)b); } //关闭 inputStream.close();    }    @Test    public void readFile02() throws Exception { //创建操作文件输入流对象 InputStream inputStream = new FileInputStream("F:\\study\\程序员学习\\尚硅谷\\尚硅谷-大数据大神班2021(JD)\\阶段一\\1.javase&mysql\\02Javase-王泽\\05-JavaSE-Map和文件与IO\\test.txt"); //定义变量,保存数据 int len; //字节数组 byte[] b = new byte[1024]; //循环读取 while((len = inputStream.read(b))!=-1) {     System.out.println(new String(b)); } //关闭 inputStream.close();    }}

字符流

前面介绍的字节流可以实现所有形式的文件的读写,不过对于中文字符,当我们使用字节流的时候,因为一个中文字符占用多个字节存储,所以它可能会显示不完整的字符。为了解决这样一种问题,Java中使用专门的字符流来读取中文字符,处理文本文件。

字符流是以字符为单位进行数据的读写

字符输入流

字符输入流是Reader,它是所有的输入字符流的父类,它是一个抽象类,它定义了字节输入流中的有些基本的方法,其子类会有更加详细的具体功能的实现。下面介绍它的接种常见方法:

  • public void close():关闭此流并释放与此流相关联的任何系统资源
  • public int read(): 从输入流读取一个字符
  • public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组中

该抽象类有很多子类,下面介绍一个入门级且很常用的子类:FileReader

FileReader类

FileReader 类是用来读取字符文件。构造时使用系统默认的字符编码和默认字节缓冲区。

字符编码:IDEA默认的是UTF-8,Windows系统的中文编码默认是GBK
字节缓冲区:指的是用来临时存储字节数据的一个字节数组

构造方法

  • FileReader(File file): 创建一个新的 FileReader ,创建要读取的File对象
  • FileReader(String fileName): 创建一个新的 FileReader ,指定读取文件的名称

常用方法

  • public int read(): 从输入流读取一个字符
  • public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组中

代码实例

import org.junit.Test;import java.io.*;public class ReaderDemo {    @Test    public void demo1() throws Exception { Reader reader = new FileReader("你自己的文件位置\\test.txt"); //字符数组读取 char[] cbuf = new char[1024]; int len; while((len=reader.read(cbuf))!=-1) {     System.out.println(new String(cbuf,0,len)); } reader.close();    }    @Test    public void demo2() throws Exception { // 使用文件名称创建流对象 Writer fw = new FileWriter("你自己的文件位置\\test.txt"); // 字符串转换为字节数组 char[] chars = "test".toCharArray(); // 写出字符数组 fw.write(chars); // test // 关闭资源 fw.close();    }}

字符输出流

字符输入流是Writer,它是所有的输出字符流的父类,它是一个抽象类,它定义了字节输出流中的有些基本的方法,其子类会有更加详细的具体功能的实现。下面介绍它的接种常见方法:

  • void write(int c):写入单个字符
  • void write(char[] cbuf) :写入字符数组
  • abstract void write(char[] cbuf, int off, int len) :写入字符数组的某一部分,off数组的开始索引,len写的字符个数
  • void write(String str) :写入字符串
  • void write(String str, int off, int len) :写入字符串的某一部分,off字符串的开始索引,len写的字符个数
  • void flush() :刷新该流的缓冲
  • void close() : 关闭此流,但要先刷新它

该抽象类有很多子类,下面介绍一个入门级且很常用的子类:FileWriter

FileWriter类

FileWriter类是用来写出字符到文件的类。构造时使用系统默认的字符编码和默认字节缓冲区。

字符编码:IDEA默认的是UTF-8,Windows系统的中文编码默认是GBK
字节缓冲区:指的是用来临时存储字节数据的一个字节数组

构造方法

  • FileWriter(File file): 创建一个新的 FileWriter,确定读取的File对象。
  • FileWriter(String fileName): 创建一个新的 FileWriter,确定读取的文件名称。

当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream

常用方法

  • void write(int c):写入单个字符
  • void write(char[] cbuf) :写入字符数组
  • abstract void write(char[] cbuf, int off, int len) :写入字符数组的某一部分,off数组的开始索引,len写的字符个数
  • void write(String str) :写入字符串
  • void write(String str, int off, int len) :写入字符串的某一部分,off字符串的开始索引,len写的字符个数
  • void flush() :刷新该流的缓冲,刷新后,写入才生效
  • void close() : 关闭流,如果不关闭则数据只是被保存到缓冲区,并没有保存到文件,也可以用使用刷新的方法

代码示例

import org.junit.Test;import java.io.File;import java.io.FileWriter;import java.io.IOException;public class WriterDemo {    @Test    public void test1() throws IOException { // 使用File对象创建流对象 File file = new File("a.txt"); FileWriter fw1 = new FileWriter(file); // 使用文件名称创建流对象 FileWriter fw2 = new FileWriter("b.txt"); System.out.println(fw1); System.out.println(fw2);    }    @Test    public void test2() throws IOException { // 使用文件名称创建流对象 FileWriter fw = new FileWriter("test1.txt"); fw.write(65); // 写出第1个字符 fw.write('b'); // 写出第2个字符 fw.write(30000); // 写出第3个字符,中文编码表中30000对应一个汉字 //fw.close(); //如果不关闭,则数据只是被保存到缓冲区,并没有保存到文件(也可以用flush) fw.flush();//用flush    }    @Test    public void test3() throws IOException { // 使用文件名称创建流对象 FileWriter fw = new FileWriter("test2.txt"); FileWriter fw1 = new FileWriter("test3.txt"); // 字符串转换为字节数组 char[] chars = "test测试".toCharArray(); // 写出字符数组 fw.write(chars); // 写出从索引1开始,2个字节 fw1.write(chars,1,2); fw.close(); //如果不关闭,则数据只是被保存到缓冲区,并没有保存到文件(也可以用flush) fw1.close(); //如果不关闭,则数据只是被保存到缓冲区,并没有保存到文件(也可以用flush)    }    @Test    public void test4() throws IOException { // 使用文件名称创建流对象 FileWriter fw = new FileWriter("test4.txt");  // 字符串 String str = "test字符串"; // 写出字符数组 fw.write(str); fw.close(); //如果不关闭,则数据只是被保存到缓冲区,并没有保存到文件(也可以用flush)    }  }

节点流

前面所提到的字符流和字节流都是节点流,他们都是直接作用于文件的流,除此之外,节点流一些,介绍如下:

  • 文件进行处理的节点流:FileInputStream FileOutputStrean FileReader FileWriter
  • 对字符串进行处理的节点流: StringReader StringWriter
  • 对数组进行处理的节点流:ByteArrayInputStream ByteArrayOutputStreamCharArrayReader CharArrayWriter
  • 对管道进行处理的节点流:PipedInputStream PipedOutputStream PipedReaderPipedWriter

处理流

处理流是在节点流的基础上又包了一层,然后对其进行操作。其主要目的是基于节点流进行操作,增强功能和性能。下面介绍三种常用处理流:

  • 缓冲流:增加缓冲功能,避免频繁读写硬盘。
  • 转换流:实现字节流和字符流之间的转换。
  • 数据流:提供将基础数据类型写入到文件中,或者读取出来.

缓冲流

缓冲流,也叫高效流,它是通过对I/O进行缓冲,从而提升了性能,使其更加高效。所谓缓冲,是给I/O增加了缓冲区,通过缓冲区可以允许Java的I/O一次不只操作一个字符,提高了读写的效率 。

按照数据类型分类:

  • 字节缓冲流:BufferedInputStream,BufferedOutputStream
  • 字符缓冲流:BufferedReader,BufferedWriter
字节缓冲流

构造方法

  • public BufferedInputStream(InputStream in) :创建一个缓冲输入流
  • public BufferedOutputStream(OutputStream out): 创建一个缓冲输出流

字节缓冲流的使用和字节流是基本一致的(如下图),只不过效率完全不一样。缓冲流相对于普通流来说,效率大大提高了。(文章过长,这里不做代码证明了)
适合小小白入门的JavaIO文章,学完即可上手
适合小小白入门的JavaIO文章,学完即可上手

字符缓冲流

构造方法

  • public BufferedReader(Reader in) :创建一个缓冲输入流
  • public BufferedWriter(Writer out): 创建一个缓冲输出流

当对于前面的字节缓冲流,字符缓冲流新增了两个特有的方法(其他的基本方法与普通流也是一致的)

  • BufferedReader:public String readLine(): 读一行文字
  • BufferedWriter:public void newLine(): 写一行行分隔符,由系统属性定义符号

代码示例

import org.junit.Test;import java.io.*;public class Buffered {    @Test    public void test1() throws IOException { // 创建流对象 BufferedReader br = new BufferedReader(new FileReader("out.txt")); // 定义字符串,保存读取的一行文字 String line  = null; // 循环读取,读取到最后返回null while ((line = br.readLine())!=null) {     System.out.print(line); } // 释放资源 br.close();    }    @Test    public void test2() throws IOException { // 创建流对象 BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt")); // 写出数据 bw.write("test"); // 写出换行 bw.newLine(); bw.write("缓冲流"); bw.newLine(); // 释放资源 bw.close();    }}

转换流

众所周知,计算机是以二进制数存储信息的,但是我们所看到的都是二进制数转换后的文字信息,这其中就涉及了字节到字符的转换操作,这就是我们要讨论的转换流。

按照数据的流向分类:

  • OutputStreamWriter类:将字符转为对应的字节
  • InputStreamReader类:读取字节,将其转为对应的字符
InputStreamReader类

它是Reader的子类,实现了字节流转为字符流的转换操作。

字符集可以指定,不指定使用默认的

构造方法

  • InputStreamReader(InputStream in): 创建一个使用默认字符集的字符流。
  • InputStreamReader(InputStream in, String charsetName): 创建一个指定字符集的字符流。

代码实例

import java.io.FileInputStream;import java.io.InputStreamReader;public class TestDemo {    public static void main(String[] args) throws Exception { // 定义文件路径,文件为gbk编码 String FileName = "你自己文件的位置\\test.txt"; // 创建流对象,默认UTF8编码 InputStreamReader isr = new InputStreamReader(new FileInputStream(FileName)); // 创建流对象,指定GBK编码 InputStreamReader isr2 = new InputStreamReader(new FileInputStream(FileName) , "GBK"); // 定义变量,保存字符 int read; // 使用默认编码字符流读取,乱码 while ((read = isr.read()) != -1) {     System.out.print((char)read); } isr.close(); // 使用指定编码字符流读取,正常解析 while ((read = isr2.read()) != -1) {     System.out.print((char)read);// 大家好 } isr2.close();    }}
OutputStreamWriter类

它是Reader的子类,实现了字符流转为字节流的转换操作。

字符集可以指定,不指定使用默认的

构造方法

  • OutputStreamWriter(OutputStream in): 创建一个使用默认字符集的字符流。
  • OutputStreamWriter(OutputStream in, String charsetName): 创建一个指定字符集的字符流。

代码实例

import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;public class TestDemo2 {    public static void main(String[] args) throws IOException { // 定义文件路径 String FileName = "你自己的文件\\out.txt"; // 创建流对象,默认UTF8编码 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(FileName)); // 写出数据 osw.write("DSyyds"); // 保存为6个字节 osw.close(); // 定义文件路径 String FileName2 = "你自己的文件\\out2.txt"; // 创建流对象,指定GBK编码 OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream(FileName2),"GBK"); // 写出数据 osw2.write("大数据"); osw2.close();    }}

数据流

前面的内容所设计的都是字符和字节,那针对于Java语言的基本数据类型和String的数据,上面两种流显然是不适用的,因此引入了数据流来解决这个问题。

按照数据流的方向分类:

  • DataInputStream类:数据输入流
  • DataOutputStream类:数据输出流
DataInputStream类

数据输入流,它是让应用程序读取原始java数据类型从底层输入流中的一个独立于机器的方式。

构造方法

  • DataInputStream(InputStream in) :创建一个输入流InputStream使用指定的标。

代码实例

import org.junit.Test;import java.io.*;public class IoStreamDemo1 {    //读操作    @Test    public void readDataStream() throws Exception { //创建读数据流,把普通流包起来 DataInputStream dataInputStream = new DataInputStream(new FileInputStream("game.dat")); //读内容 String name = dataInputStream.readUTF(); char gender = dataInputStream.readChar(); //打印 System.out.println(name+","+gender); //数据流关闭 dataInputStream.close();    }}
DataOutputStream类

数据输出流,它可以让一个应用java写的原始数据类型在一个便携式的方式输出

构造方法

  • DataOutputStream(OutputStream out) :创建一个新的数据输出流,将数据写入到指定的基本输出流中。

代码实例

import org.junit.Test;import java.io.*;public class IoStreamDemo1 {    //写操作    @Test    public void writeDataStream() throws Exception { //定义写入不同类型值 String name = "jack"; char gender = '男'; //创建写数据流,把普通流包起来 DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream("game.dat")); //写入内容 dataOutputStream.writeUTF(name); dataOutputStream.writeChar(gender); //数据流关闭 dataOutputStream.close();    }}

开发者涨薪指南 适合小小白入门的JavaIO文章,学完即可上手 48位大咖的思考法则、工作方式、逻辑体系儿童百科