JavaSE复习总结之IO流

IO流概述

输入/输出处理是程序设计中非常重要的环节, 如从键盘或传感器读入数据、 从文件中读取数据或向文件中写入数据、 从网络中读取或写入数据等。 Java 把这些不同类型的输入、 输出抽象为 “流” , 所有的输入/输出以流的形式进行处理。I表示Input,O表示Output,通过IO可以完成硬盘文件的读和写。

IO流的分类

  • 按照流的方向进行分类:
    以内存作为参照物
    往内存中去,叫做输入(Input)。或者叫做读(Read)
    从内存中出来,叫做输出(Output)。或者叫做写(Write)
  • 按照读取数据方式不同进行分类
    有的流是按照字节的方式读取数据,一次读取1个字节byte。这种流称为字节流
    有的流是按照字符的方式读取数据的。这种流称为字符流
    在这里插入图片描述

在java中只要“类名”以Stream结尾的都是字节流。以“Reader/Writer”结尾的都是字符流

Java中常用的流

文件专属:
	java.io.FileInputStream
	java.io.FileOutputStream
	java.io.FileReader
	java.io.FileWriter
转换流:(将字节流转换成字符流)
	java.io.InputStreamReader
	java.io.OutputStreamWriter
缓冲流专属:
	java.io.BufferedReader
	java.io.BufferedWriter
	java.io.BufferedInputStream
	java.io.BufferedOutputStream
数据流专属:
	java.io.DataInputStream
	java.io.DataOutputStream
标准输出流:
	java.io.PrintWriter
	java.io.PrintStream
对象专属流:
	java.io.ObjectInputStream
	java.io.ObjectOutputStream

InputStream 和 OutputStream 继承结构图:
在这里插入图片描述

返回值类型 方法名 描述
void close() 关闭此流并释放与该流关联的所有系统资源
abstract int read() 从输入流读取下一个数据字节.再读的时候读取不到任何数据返回-1
int read(byte[] b) 从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中
int read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入字节数组
void flush() 刷新此输出流并强制写出所有缓冲的输出字节
void write(byte[] b) 将 b.length 个字节从指定的字节数组写入此输出流
void write(byte[] b, int off, int len) 将指定字节数组中从偏移量 off 开始的 len 个字节写入此输出流
abstract void write(int b) 将指定的字节写入此输出流

Reader 和 Writer 继承结构图:

在这里插入图片描述

返回值类型 方法名 描述
abstract void close() 关闭该流
int read() 读取单个字符
int read(char[] cbuf) 将字符读入数组
abstract int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分
Writer append(char c) 将指定字符追加到此 writer
abstract void flush() 刷新此流
void write(char[] cbuf) 写入字符数组
abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分
void write(int c) 写入单个字符
void write(String str) 写入字符串
void write(String str, int off, int len) 写入字符串的某一部分
  • 所有的流都实现了java.io.Closeable接口,都是可关闭的,都有close()方法。用完之后一定要关闭,不然会耗费(占用)很多资源。
  • 所有的输出流都实现了java.io.Flushable接口,都是可刷新的,都有flush()方法。养成一个好习惯,输出流在最终输出之后,一定要记得flush()刷新一下。

File类

File 类是 java.io 包中唯一代表磁盘文件和目录的类。 File类和四大家族没有关系,所以File类不能完成文件的读和写。

File类的构造方法

  • File(String filename); filename 是文件名字或绝对路径
  • File(String directoryPath,String filename); directoryPath 是文件的绝对路径
  • File(File f,String filename); f 是代表一个目录的文件对象
File dir = new File("D:/java/tt/");//创建目录
File file = new File("D:/java/tt/file.txt");//创建文件
File file = new File(dir,"file1.txt");//在dir目录下创建文件
File file = new File("D:/java/tt/","file2.txt");//在tt目录下创建文件

File类常用方法

返回类型 方法名 描述
boolean exits( ) 判断文件是否存在
boolean createNewFile() 以文件形式新建
boolean mkdir() 以目录的形式新建
boolean mkdirs() 多重目录的形式新建
boolean delete( ) 删除 File 对象对应的文件或目录
boolean isFile( ) 判断文件是否是文件
boolean isDirectory( ) 判断文件是否是目录
boolean canRead( ) 判断文件是否可读
boolean canWrite( ) 判断文件是否可写
long length( ) 获取文件的长度 (单位时字节)
long lastModified() 获取文件最后一次修改时间,返回从1970年到现在的总毫秒数
String getName( ) 获取文件的名字
String getPath( ) 返回 File 对象对应的路径
String getAbsolutePath( ) 获取文件的绝对路径
String getParent( ) 获取文件的父目录
String[] list( ) 列出指定目录的全部内容,只列出名称
File[ ] listFiles( ) 返回包含 File 对象所有子文件和子目录的 File 数组

文件流

文件流主要分为

  • 文件字节输入流 java.io.FileInputStream
  • 文件字节输出流 java.io.FileOutputStream
  • 文件字符输入流 java.io.FileReader
  • 文件字符输出流 java.io.FileWriter

FileInputStream

1、文件字节输入流,万能的,任何类型的文件都可以采用这个流来读。
2、字节的方式,完成输入的操作,完成读的操作(硬盘 → 内存)

扫描二维码关注公众号,回复: 13782456 查看本文章
public class FileInputStreamTest {
    
    
    public static void main(String[] args) {
    
    
        FileInputStream fis = null;
        try {
    
    
            fis = new FileInputStream("chapter23/src/tempfile3");
            // 准备一个byte数组,一次最多读取4个字节
            byte[] bytes = new byte[4];
            int readCount = 0;
            //is.read(bytes)的返回值是:读取到的字节数量,不是字节本身
            while((readCount = fis.read(bytes)) != -1) {
    
    
            	//将字节数组全部转换成字符串
                System.out.print(new String(bytes, 0, readCount));
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
     //在finally语句块当中确保流一定关闭
            if (fis != null) {
    
    
                try {
    
    
                    fis.close();//关闭流
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
}

FileInputStream类的其它常用方法:

  • int available():返回流当中剩余的没有读到的字节数量
  • long skip(long n):跳过几个字节不读。

FileOutputStream

字节的方式,完成输出的操作,完成写的操作(内存 → 硬盘)

public class FileOutputStreamTest {
    
    
    public static void main(String[] args) {
    
    
        FileOutputStream fos = null;
        try {
    
    
            //文件不存在的时候会自动新建!
            // 这种方式谨慎使用,这种方式会先将原文件清空,然后重新写入。
            //fos = new FileOutputStream("D:\\IO\\why\\b.txt");
            // 以追加的方式在文件末尾写入。不会清空原文件内容。
            fos = new FileOutputStream("D:\\IO\\why\\b.txt", true);
            byte[] bytes = {
    
    97, 98, 99, 100};
            // 将byte数组全部写出
            fos.write(bytes); // abcd
            // 将byte数组的一部分写出
            fos.write(bytes, 0, 2); // 再写出ab
            String s = "我是输出流";
            // 将字符串转换成byte数组。
            byte[] bs = s.getBytes();
            fos.write(bs);
            fos.flush();// 写完之后,最后一定要刷新
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //关闭流(代码省略)
        }
    }
}

FileReader

文件字符输入流,只能读取普通文本。读取文本内容时,比较方便快捷。

public class FileReaderTest {
    
    
    public static void main(String[] args) {
    
    
        FileReader reader = null;
        try {
    
    
            //创建文件字符输入流
             reader = new FileReader("D:\\IO\\why\\b.txt");
            //开始读
            char[] chars = new char[4]; // 一次读取4个字符
            int readCount = 0;
            while((readCount = reader.read(chars)) != -1) {
    
    
                System.out.print(new String(chars,0,readCount));
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //关闭流(代码省略)
        }
    }
}

FileWriter

文件字符输出流,负责写。只能输出普通文本

public class FileWriterTest {
    
    
    public static void main(String[] args) {
    
    
        FileWriter out = null;
        try {
    
    
            out = new FileWriter("D:\\IO\\why\\c.txt", true);
            char[] chars = {
    
    '我','是','中','国','人'};
            out.write(chars); //将我是中国人写入到文件
            out.write(chars, 2, 3);//将中国人写入到文件
            out.write("我是一名java软件工程师!");
            out.write("\n");// 写出一个换行符。
            out.write("hello world!");
            out.flush();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //关闭流(代码省略)
        }
    }
}

缓冲流

缓冲流主要是为了提高效率而存在的,减少物理读取次数,缓冲流主要有:

  • 字符输入缓冲流:java.io.BufferedReader
  • 字符输出缓冲流:java.io.BufferedWriter
  • 字节输入缓冲流:java.io.BufferedInputStream
  • 字节输出缓冲流:java.io.BufferedOutputStream

BufferedReader

带有缓冲区的字符输入流。 使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组,自带缓冲。

public class BufferedReaderTest {
    
    
    public static void main(String[] args) throws Exception{
    
    

        FileReader reader = new FileReader("D:\\IO\\why\\a.txt");
        // 当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流
        // 外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流
        // FileReader就是一个节点流BufferedReader就是包装流/处理流。
        BufferedReader br = new BufferedReader(reader);
        // 读一行但不带换行符
        //String firstLine = br.readLine();
        String s = null;
        while((s = br.readLine()) != null){
    
    
            System.out.print(s);
        }
        // 对于包装流来说,只需要关闭最外层流就行,里面的节点流会自动关闭
        br.close();
    }
}

BufferedWriter

带有缓冲的字符输出流

public class BufferedWriterTest {
    
    
    public static void main(String[] args) throws Exception{
    
    
        // 带有缓冲区的字符输出流
        BufferedWriter out = new BufferedWriter(new FileWriter("copy"));
        // 开始写
        out.write("hello world!");
        out.write("\n");
        out.write("hello kitty!");
        // 刷新
        out.flush();
        // 关闭最外层
        out.close();
    }
}

转换流

转换流主要有两个 InputStreamReader 和 OutputStreamWriter

  • InputStreamReader 主要是将字节流输入流转换成字符输入流
  • OutputStreamWriter 主要是将字节流输出流转换成字符输出流
//字节输入流
FileInputStream in = new FileInputStream("Copy02.java");
//通过转换流转换(InputStreamReader将字节流转换成字符流)
InputStreamReader reader = new InputStreamReader(in);
//字节输出流
FileOutputStream out = new FileOutputStream("copy", true);
//通过转换流转换(OutputStreamWriter将字节流转换成字符流)
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(out);

标准输出流

标准输出流主要包含两个:

  • PrintStream
  • PrintWriter

PrintStream

System.out 其实对应的就是 PrintStream,默认输出到控制台,我们可以重定向它的输出,可以定向到文件,也就是执行 System.out.println(“hello”)不输出到屏幕,而输出到文件

public class PrintStreamTest {
    
    
    public static void main(String[] args) throws Exception{
    
    
		//默认输出到控制台
        System.out.println("hello world!");
        //标准输出流不再指向控制台,指向“log”文件。
        PrintStream printStream = new PrintStream(new FileOutputStream("log"));
        //修改输出方向,将输出方向修改到"log"文件。
        System.setOut(printStream);
        //再输出
        System.out.println("hello world");
        System.out.println("hello kitty");
        System.out.println("hello zhangsan");
	    //标准输出流不需要手动close()关闭
    }
}

PrintWriter

PrintWriter printWriter = new PrintWriter(new FileWriter("D:\\IO\\why\\f.txt"));
printWriter.print("我是printWriter");
printWriter.flush();
printWriter.close();

数据流

数据流包含两个:

  • 数据字节输入流:java.io.DataInputStream
  • 数据字节输出流:java.io.DataOutputStream

DataOutputStream

这个流可以将数据连同数据的类型一并写入文件
注意:这个文件不是普通文本文档

public class DataOutputStreamTest {
    
    
    public static void main(String[] args) throws Exception{
    
    
        // 创建数据专属的字节输出流
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("data"));
        byte b = 100;
        short s = 200;
        int i = 300;
        long l = 400L;
        float f = 3.0F;
        double d = 3.14;
        boolean sex = false;
        char c = 'a';
        // 把数据以及数据的类型一并写入到文件当中
        dos.writeByte(b); 
        dos.writeShort(s);
        dos.writeInt(i);
        dos.writeLong(l);
        dos.writeFloat(f);
        dos.writeDouble(d);
        dos.writeBoolean(sex);
        dos.writeChar(c);
        dos.flush();//刷新
        dos.close();//关闭最外层流
    }
}

DataInputStream

DataOutputStream写的文件,只能使用DataInputStream去读。并且读的时候你需要提前知道写入的顺序。读的顺序需要和写的顺序一致。才可以正常取出数据

public class DataInputStreamTest01 {
    
    
    public static void main(String[] args) throws Exception{
    
    
    	//创建数据输入流
        DataInputStream dis = new DataInputStream(new FileInputStream("data"));
        // 开始读,读的顺序需要和写的顺序一致
        byte b = dis.readByte();
        short s = dis.readShort();
        int i = dis.readInt();
        long l = dis.readLong();
        float f = dis.readFloat();
        double d = dis.readDouble();
        boolean sex = dis.readBoolean();
        char c = dis.readChar();
        System.out.println(b);
        System.out.println(s);
        System.out.println(i + 1000);
        System.out.println(l);
        System.out.println(f);
        System.out.println(d);
        System.out.println(sex);
        System.out.println(c);
        dis.close();
    }
}

对象流

对象流可以将 Java 对象转换成二进制写入磁盘,这个过程通常叫做序列化,并且还可以从磁盘读出完整的 Java 对象,而这个过程叫做反序列化。对象流主要包括ObjectInputStream 和 ObjectOutputStream

ObjectOutputStream

  • 参与序列化和反序列化的对象,必须实现Serializable接口
public class Student implements Serializable {
    
    
    // IDEA工具自动生成序列化版本号。
    //private static final long serialVersionUID = -7998917368642754840L;
    // 建议将序列化版本号手动的写出来。不建议自动生成
    private static final long serialVersionUID = 1L; // java虚拟机识别一个类的时候先通过类名,如果类名一致,再通过序列化版本号。
    private int no;
    private String name;

    public Student(int no, String name) {
    
    
        this.no = no;
        this.name = name;
    }
   /*setter and getter 方法*/
   /*toString()方法*/
}

序列化对象

public class ObjectOutputStreamTest {
    
    
    public static void main(String[] args) throws Exception{
    
    
        // 创建java对象
        Student s = new Student(1111, "张三");
        // 创建对象输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("students"));
        // 序列化对象
        oos.writeObject(s);
        // 刷新
        oos.flush();
        // 关闭
        oos.close();
    }
}

ObjectInputStream

反序列化对象

public class ObjectInputStreamTest {
    
    
    public static void main(String[] args) throws Exception{
    
    
    	//创建对象输入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("students"));
        // 开始反序列化,读
        Object obj = ois.readObject();
        // 反序列化回来是一个学生对象,所以会调用学生对象的toString方法。
        System.out.println(obj);
        ois.close();
    }
}

IO+Properties的联合应用

经常改变的数据,可以单独写到一个文件中,使用程序动态读取。将来只需要修改这个文件的内容,java代码不需要改动,不需要重新编译,服务器也不需要重启。就可以拿到动态的信息。
类似于以上机制的这种文件被称为配置文件。
并且当配置文件中的内容格式是:
key1=value
key2=value

public class IoPropertiesTest {
    
    
    public static void main(String[] args) throws Exception{
    
    
        /*
        Properties是一个Map集合,key和value都是String类型。
        想将userinfo文件中的数据加载到Properties对象当中。
         */
        // 新建一个输入流对象
        FileReader reader = new FileReader("chapter23/userinfo.properties");
        // 新建一个Map集合
        Properties pro = new Properties();
        // 调用Properties对象的load方法将文件中的数据加载到Map集合中
        // 文件中的数据顺着管道加载到Map集合中,其中等号=左边做key,右边做value
        pro.load(reader); 
        // 通过key来获取value呢?
        String username = pro.getProperty("username");
        System.out.println(username);
        String password = pro.getProperty("password");
        System.out.println(password);
        String data = pro.getProperty("data");
        System.out.println(data);
        String usernamex = pro.getProperty("usernamex");
        System.out.println(usernamex);
    }
}

猜你喜欢

转载自blog.csdn.net/m0_60117382/article/details/123771667