17 IO流

252 阅读12分钟

1 IO流

IO就是inpit和output的简写,是输入和输出的含义,而所谓的IO流就是输入输出流,指读写数据时像流水一样从一端流到另一端。

IO流可以分为三类:

  • 从读写数据的基本单位来分,有字节流和字符流:字节流是以字节为单位进行数据读写的流,可以读写任意类型的文件;字符流是以字符为单位进行数据读写的流,只能读写文本文件。

  • 从读写数据的方向来分,有输入流和输出流:输入流指从文件中读取数据内容到程序中;输出流指将程序中的数据内容写入到文件中。

  • 从流的角色来分,有节点流和处理流:节点流指直接和输入输出源直接对接的流;处理流指需要建立在节点流的基础之上的流。

IO流的体系结构如下:

02 IO流的体系图.png

2 FileWriter类

FileWriter类主要用于将文本内容写入文本文件中,其中FileWriter类常用的方法有:

方法声明功能介绍
FileWriter(String fileName)根据参数文件名构造对象
FileWriter(String fileName,boolean appened)已追加的方式根据参数文件名构造对象
void writer(int c)写入单个字符
void writer(char[] c,int off,int Len)将字符数组中从下标off开始的len个字符写入文件
void writer(char[] c)将字符数组中全部字符写入文件
void flush()刷新流
void close()关闭流对象并释放相关资源

代码实例:

import java.io.FileWriter;
import java.io.IOException;
public class FileWriterTest {
    public static void main(String[] args) {
        FileWriter fileWriter=null;
        try {
            fileWriter=new FileWriter("java.txt");
            fileWriter.write("66");
            char[] chars=new char[]{'j','a','v','a'};
            fileWriter.write(chars,1,2);
            fileWriter.write(chars);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(fileWriter!=null){
                    fileWriter.close();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

3 FileReader类

Filereader类用于从文本文件中读取文本数据内容,其常用的方法有:

方法声明功能介绍
FileReader(String fileName)根据参数文件名构造对象
int read()读取单个字符并返回,当返回-1时表示读到末尾
int read(char[] ch,int offset,int len)从输入流中读取最多len个字符的数据写入到字符数组中,返回读取到的字符个数,返回-1表示读到末尾
int red(char[] ch)从输入流中读取字符数组长度个字符写入到数组,返回读取到的字符个数,返回-1表示读到末尾
void close()关闭流对象并释放相关资源

实例代码:

import java.io.FileReader;
import java.io.IOException;

public class FileReaderTest {
    public static void main(String[] args) {
        FileReader fileReader=null;
        try {
            fileReader=new FileReader("java.txt");
            char c=(char)fileReader.read();
            System.out.println("读取到单个字符是:"+c);
            char[] ch=new char[8];
            fileReader.read(ch);
            System.out.println("字符数组读取到的数据是:");
            for(char a:ch){
                System.out.println(a);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if(fileReader!=null){
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
        }


    }
}

4 FileOutputStream类

FileOutputStream类用于将图像数据之类的原始字节流写入到输出流中,常用方法有:

方法声明功能介绍
FileOutputStream(String fileName)根据参数文件名构造对象
FileOutputStream(String fileName,boolean appened)已追加的方式根据参数文件名构造对象
void writer(int c)将指定字节写入此文件输出流
void writer(byte[] c,int off,int Len)将字节数组中从下标off开始的len个字节写入文件输出流
void writer(byte[] c)将字节数组中全部字节写入文件输出流
void flush()刷新流
void close()关闭流对象并释放相关资源

5 FileInputStream类

FileInputStream类主要用于输入流中以字节流的方式读取图像数据。常用方法有:

方法声明功能介绍
FileInputStream(String fileName)根据参数文件名构造对象
int read()读取单个字节数据并返回,当返回-1时表示读到末尾
int read(byte[] ch,int offset,int len)从输入流中读取最多len个字节的数据写入到字节数组中,返回读取到的字节个数,返回-1表示读到末尾
int red(byte[] ch)从输入流中读取字节数组长度个字符写入到数组,返回读取到的字节个数,返回-1表示读到末尾
void close()关闭流对象并释放相关资源
int available()获取输入流所关联的文件大小

编程实现两个文件之间的拷贝功能,具体代码如下:

文件字符流实现文件拷贝(文本文件)

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyTest {
    public static void main(String[] args) {
        FileReader fr=null;
        FileWriter fw=null;
        try {
            fr=new FileReader("java.txt");
            fw=new FileWriter("python.txt");
            int res=0;
            while ((res=fr.read())!=-1){
                fw.write(res);
            }
            System.out.println("拷贝文件成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if(null!=fw){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(null!=fr){
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

文件字节流实现文件的拷贝(视频或图像等文件)

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyTest {
    public static void main(String[] args) {
        FileInputStream fis=null;
        FileOutputStream fos=null;
        try {
            fis=new FileInputStream("java.png");
            fos=new FileOutputStream("python.png");
            /*
            方式一:以单个字节为单位进行拷贝,读取一个字节写入一个
            缺点:当文件很大时,效率会非常的低
            int res=0;
            while ((res=fis.read())!=-1){
                fos.write(res);
            }*/
            /*
            方式二:准备和文件一样大小的缓冲区,一次性将数据读进缓冲区,再从缓冲区一次性写入
            缺点:当文件非常大时,物理内存可能无法分配这么大的缓冲区
            int len= fis.available();
            byte[] br=new byte[len];
            fis.read(br);
            fos.write(br);*/
            /*
            方式三:准备一个适当的缓冲区,分多次将文件拷贝
            
             */
            byte[] br=new byte[1024];
            int res=0;
            while ((res= fis.read())!=-1){
                fos.write(br,0,res);
            }
            System.out.println("拷贝成功");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(null!=fos){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(null!=fis){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
        
    

    }
}

6 BufferedOutputStream类

BufferedOutputStream类主要用于描述缓冲输出流,此时不用为写入的每个字节调用底层系统,其常用方法有:

方法声明功能介绍
BufferedOutputStream(OutputStream out)根据参数指定引用构造对象
BufferedOutputStream(OutputStream out,int size)根据参数指定的引用和缓冲区大小构造对象
void writer(int c)将指定字节写入此文件输出流
void writer(byte[] c,int off,int Len)将字节数组中从下标off开始的len个字节写入文件输出流
void writer(byte[] c)将字节数组中全部字节写入文件输出流
void flush()刷新流
void close()关闭流对象并释放相关资源

7 BufferedInputStream类

BufferedInputStream类主要描述缓冲输入流,其常用方法有:

方法声明功能介绍
BufferedInputStream(InputStream in)根据参数指定引用构造对象
int read()读取单个字节数据并返回,当返回-1时表示读到末尾
int read(byte[] ch,int offset,int len)从输入流中读取最多len个字节的数据写入到字节数组中,返回读取到的字节个数,返回-1表示读到末尾
int red(byte[] ch)从输入流中读取字节数组长度个字符写入到数组,返回读取到的字节个数,返回-1表示读到末尾
void close()关闭流对象并释放相关资源
BufferedInputStream(InputStream in,int size)根据参数引用和缓冲区大小构造对象

8 BufferedWriter类

BufferedWriter类主要用于写入单个字符、字符数组以及字符串到输出流中,其常用方法有:

常用方法功能介绍
BufferedWriter(Writer out)根据参数指定引用构造对象
BufferedWriter(Writer out,int size)根据参数指定引用和缓冲区大小构造对象
void writer(int c)写入单个字符到输出流
void writer(char[] ch,int off,int len)将字符数组ch中从下标off开始的len个字符写入输出流
void writer(char[] ch)将字符数组中所有内容写入到输出流
void writer(String s,int off,int len)将字符串中下标从off开始的len个字符写入到输出流
void writer(String s)将字符串内容写入到输出流
void newLine()写入行分隔符到输出流中
void flush()刷新流
void close()关闭流对象并释放所有相关资源

9 BufferedReader类

BufferedReader类主要从输入流中读取单个字符、字符数组以及字符串,其常用方法有:

方法声明功能介绍
BufferedReader(Reader r)根据参数引用构造对象
BufferedReader(Reader r,int size)根据参数引用和缓冲区大小构造对象
int read()从输入流读取单个字符,读取到末尾,返回-1
int read(char[] ch,int off,int len)从输入流中读取len个字符放入字符数组下标从off开始的位置。读到末尾,返回-1
int read(char[] ch)从输入流中读满整个字符数组
String readLine()读取一行字符串并返回,返回null表示读到末尾
void close()关闭流对象及相关资源

10 PrintStream类

PrintStream类主要用于更加方便的打印各种数据类容,其常用方法:

方法声明功能介绍
PrinStream(OutputStream out)根据参数引用构造对象
void print(String s)将参数指定的字符串内容打印出来
void println(String s)打印字符串后换行
void flush()刷新流
void close()关闭输出流对象及相关资源

11 PrintWriter类

PrintWriter类用于将对象的格式化形式打印到文本输出流中,其常用方法:

方法声明功能介绍
PrintWriter(Writer out)根据参数引用构造对象
void print(String s)打印参数指定的字符串内容
void println(String s)打印字符串内容后换行
void flush()刷新流
void close()关闭流对象及相关资源

案例:不断提示用户输入要发送的内容,当发送的内容为“bye”则结束,否则将用户输入内容写入到文本文件中

具体代码:

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ChatTest {
    public static void main(String[] args) {
        BufferedReader br=null;
        PrintStream ps=null;
        try {
            br=new BufferedReader(new InputStreamReader(System.in));
            ps=new PrintStream(new FileOutputStream("java.txt",true));
            boolean flag=true;
            while (flag){
                System.out.println("请"+(flag?"张三":"李四")+"输入要发送的内容:");
                String s=br.readLine();
                if("bye".equals(s)){
                    System.out.println("聊天结束");
                    break;
                }
                Date d=new Date();
                SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                ps.println(sf.format(d)+(flag?"张三说:":"李四说:")+s);
                flag=!flag;
            }
            ps.println();
            ps.println();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(null!=ps){
                ps.close();
            }
            if(null!=br){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

12 OutputStreamWriter类

OutputStreamWriter类实现从字符流到字节流的转换,其常用方法有:

常用方法功能介绍
OutputStreamWriter(OutputStream out)根据参数引用构造对象
OutputStreamWriter(OutputStream out,String charset)根据参数引用和编码构造对象
void write(String str)写入参数指定的字符串
void flush()刷新流
void close()关闭输出流及释放资源

13 InputStreamReader类

InputStreamReader类用于从字节流到字符流的转换,其常用方法:

方法声明功能介绍
InputStreamReader(InputStream in)根据参数引用构造对象
InputStreamReader(InputStream in,String charset)根据参数引用和编码构造对象
int read(char[] cf)读取字符数据到字符数组
void close()关闭输出流及释放资源

14 DataOutputStream类和DataInputStream类

DataOutputStream类主要以适当的方式将基本数据类型写入到输出流,其常用方法:

方法声明功能介绍
DataOutputStream(OutputStream out)根据参数引用构造对象
void writeInt(int v)将参数指定的整数一次性写入到输出流,优先写入高字节
void close()用于关闭文件输出流及释放资源

DataInputStream类主要从输入流中读取基本数据类型的数据,其常用方法:

方法声明功能介绍
DataInputStream(InputStream out)根据参数引用构造对象
int readInt()从输入流中一次性读取一个整数数据并返回
void close()用于关闭文件输出流及释放资源

15 ObjectOutputstream类和ObjectInputstream类

ObjectOutputstream类主要用于将一个对象的所有内容整体写入到输出流中,但是只能支持实现java.io.Serializable接口的对象写入流中,类通过实现java.io.Serializable接口来启用序列化功能。

序列化是指将一个对象需要存储的信息有效组织成字节序列的转化过程。

ObjectOutputstream常用方法:

方法声明功能介绍
ObjectOutputstream(OutputStream out)根据参数引用构造对象
void writeObject(Object ob)将参数对象写入到输出流中
void close()用于关闭输出流及释放资源

ObjectInputstream类主要用于从输入流中一次性将对象整体读取出来,这也是反序列化,反序列化是指将有效组织的字节序列恢复为一个对象的转化过程。

ObjectInputstream常用方法:

方法声明功能介绍
Object Inputstream(OutputStream out)根据参数引用构造对象
void readObject()从输入流中读取一个对象并返回,但无法通过返回值判断是否读到末尾
void close()用于关闭输入流及释放资源

序列化版本号:序列化机制通过运行时判断类的serialVersionUID来验证版本一致性。在进行反序列化时,jvm会把传来的字节流中得serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则出现序列化版本不一致的异常。

transient关键字:transient关键字,用来表示一个域不是该对象序列化的部分。当一个对象进行序列化时,transient关键字修饰的成员变量不包括在序列化部分之中,非transient修饰的成员变量都会被序列化。

当希望多个对象写入到文件,通常建议将多个对象放入到一个集合中,然后将集合放入到输出流中,此时只需调用一次readObject方法就可以将整个集合的数据读取出来,这样就避免了通过返回值进行判断是否到达文件末尾

16 RandomAccessFile类

RandomAccessFile类主要支持对随机访问文件的读写操作,其常用方法:

方法声明功能介绍
RandomAccessFile(String name,String mode)根据参数指定的名称和模式构造对象
int read()读取单个字节数据
void seek(long pos)从文件的开头开始测量文件指针偏移量
void write(int b)写入参数指定的单个字节
void close()关闭流并释放相关资源

实例代码

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
    public static void main(String[] args) {
        RandomAccessFile rm=null;
        try {
            rm=new RandomAccessFile("java.txt","rw");
            System.out.println("读取到的单个字符"+(char)rm.read());
            rm.seek(3);
            rm.write(66);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(null!=rm){
                try {
                    rm.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        }

}