Java I/O流

1 什么是I/O流

输入输出都相对于内存,内存作为参照物
在这里插入图片描述
有多种分类方式:

一种方式是按照流的方向进行分类:
以内存作为参照物,
往内存中去,叫做输入(Input)。或者叫做读(Read)。
从内存中出来,叫做输出(Output)。或者叫做写(Write)。

另一种方式是按照读取数据方式不同进行分类:
有的流是按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位。
这种流是万能的,什么类型的文件都可以读取。包括:文本文件,图片,声音文件,视频文件等…
假设文件file1.txt,采用字节流的话是这样读的:
a中国bc张三fe
第一次读:一个字节,正好读到’a’
第二次读:一个字节,正好读到’中’字符的一半。
第三次读:一个字节,正好读到’中’字符的另外一半。

有的流是按照字符的方式读取数据的,一次读取一个字符,这种流是为了方便读取
普通文本文件而存在的,这种流不能读取:图片、声音、视频等文件。只能读取纯
文本文件,连word文件都无法读取。
假设文件file1.txt,采用字符流的话是这样读的:
a中国bc张三fe
第一次读:'a’字符('a’字符在windows系统中占用1个字节。)
第二次读:'中’字符('中’字符在windows系统中占用2个字节。)

综上所述:流的分类
输入流、输出流
字节流、字符流

2 java IO流这块有四大家族

java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流
java.io.Reader 字符输入流
java.io.Writer 字符输出流
四大家族的首领都是抽象类。(abstract class)
java.io.Closeable接口,都是可关闭的,都有close()方法
流毕竟是一个管道,这个是内存和硬盘之间的通道,用完之后一定要关闭,不然会耗费(占用)很多资源。养成好习惯,用完流一定要关闭。
stream结尾为字节流 Reader Writer 字符流

所有的输出流都实现了:
java.io.Flushable接口,都是可刷新的,都有flush()方法。养成一个好习惯,输出流在最终输出之后,一定要记得flush()刷新一下。这个刷新表示将通道/管道当中剩余未输出的数据强行输出完(清空管道!)刷新的作用就是清空管道。注意:如果没有flush()可能会导致丢失数据。

3 java.io包下需要掌握的流有16个

文件专属:
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(掌握)

4 FileInputStream 终极版

int read(byte[] b)
一次最多读取 b.length 个字节。减少硬盘和内存的交互,提高程序的执行效率。往byte[]数组当中读。
FileInputStream类的其它常用方法:
int available():返回流当中剩余的没有读到的字节数量
long skip(long n):跳过几个字节不读。

Idea 默认当前路径是 Project的根目录

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Test04 {
    public static void main(String[] args) {
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream("D:\\armadillo-9.900.3\\LICENSE.txt");
            byte[] bytes = new byte[1000];
            int readcount=0;
            while ((readcount=fileInputStream.read(bytes))!=-1){
                System.out.println(new String(bytes,0,readcount));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileInputStream!=null){
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Test04 {
    public static void main(String[] args) {
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream("D:\\armadillo-9.900.3\\LICENSE.txt");
            int available = fileInputStream.available(); //不适合较大的文件 数组容量有限
            byte[] bytes = new byte[available];
            int read = fileInputStream.read(bytes);
            System.out.println(new String(bytes));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileInputStream!=null){
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

5.FileOutputStream

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test05 {
    public static void main(String[] args) {
        FileOutputStream fileOutputStream = null;
        try {
//            fileOutputStream = new FileOutputStream("abc.txt",true); //不存在自动新建
//            byte[] bytes = {110,98,87,99};
//            fileOutputStream.write(bytes);
//            fileOutputStream.write(bytes,0,2);//如何追加写入?
            fileOutputStream = new FileOutputStream("ccc.txt",true);
            String s="错误信息请联系。。";
            byte[] bytes = s.getBytes();
            fileOutputStream.write(bytes);
            fileOutputStream.write(bytes);
            fileOutputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

6.文件的复制

package com.fangun;

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

public class Test06 {
    public static void main(String[] args) {
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream=null;
        try {
            fileInputStream = new FileInputStream("D:\\armadillo-9.900.3\\LICENSE.txt");
//            int available = fileInputStream.available();
//            byte[] bytes = new byte[available];
//            int read = fileInputStream.read(bytes);
//            fileOutputStream = new FileOutputStream("D:\\code.txt");
//            fileOutputStream.write(bytes);
//            fileOutputStream.flush();
            //一边读一边写
            fileOutputStream=new FileOutputStream("D:\\code001.txt");
            byte[] bytes = new byte[1024 * 1024];
            int read=0;
            while ((read=fileInputStream.read(bytes))!=-1){
                fileOutputStream.write(bytes,0,read);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try { //注意这里分开catch
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

7 FileReader 与 FileWriter

复制普通文本文件

package com.fangun;

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

public class Test09 {
    public static void main(String[] args) {
        FileReader fileReader=null;
        FileWriter fileWriter=null;
        try {
            fileReader= new FileReader("D:\\code.txt");
            fileWriter = new FileWriter("D:\\code001.txt");
            char[] chars = new char[4];
            int readvalue = 0;
            while ((readvalue=fileReader.read(chars))!=-1){
                    fileWriter.write(chars,0,readvalue);
                    fileWriter.flush();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fileReader!=null){
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileWriter!=null){
                try {
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

8 BufferReader与BufferWriter

带有缓冲区的流,可以不用手动构建byte char 数组。当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流。外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流。FileReader就是一个节点流。BufferedReader就是包装流/处理流

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\code.txt")));

9 数据流

DataInputStream DataOutputStream

10 标准的输出流

实现日志记录功能:
PrintStream printStream 指向输出流


import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Logger {
    public static void log(String s){
        try {
            PrintStream printStream = new PrintStream(new FileOutputStream("log001.txt",true)); 
            System.setOut(printStream);
            Date date = new Date();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String format = simpleDateFormat.format(date);
            System.out.println(format+s);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

11 File 类

1、File类和四大家族没有关系,所以File类不能完成文件的读和写。
2、File对象代表什么?
文件和目录路径名的抽象表示形式。
C:\Drivers 这是一个File对象
C:\Drivers\Lan\Realtek\Readme.txt 也是File对象。
一个File对象有可能对应的是目录,也可能是文件。
File只是一个路径名的抽象表示形式。
3、需要掌握File类中常用的方法
~~
public class FileTest01 {
public static void main(String[] args) throws Exception {
// 创建一个File对象
File f1 = new File(“D:\file”);

    // 判断是否存在!
    System.out.println(f1.exists());

    // 如果D:\file不存在,则以文件的形式创建出来
    /*if(!f1.exists()) {
        // 以文件形式新建
        f1.createNewFile();
    }*/

    // 如果D:\file不存在,则以目录的形式创建出来
    /*if(!f1.exists()) {
        // 以目录的形式新建。
        f1.mkdir();
    }*/

    // 可以创建多重目录吗?
    File f2 = new File("D:/a/b/c/d/e/f");
    /*if(!f2.exists()) {
        // 多重目录的形式新建。
        f2.mkdirs();
    }*/

    File f3 = new File("D:\\course\\01-开课\\学习方法.txt");
    // 获取文件的父路径
    String parentPath = f3.getParent();
    System.out.println(parentPath); //D:\course\01-开课
    File parentFile = f3.getParentFile();
    System.out.println("获取绝对路径:" + parentFile.getAbsolutePath());

    File f4 = new File("copy");
    System.out.println("绝对路径:" + f4.getAbsolutePath()); // C:\Users\Administrator\IdeaProjects\javase\copy
}
}

12 java.IO 实现目录全部内容复制

package com.fangun;

import java.io.*;

public class CopyAll {
    public static void main(String[] args) {
        File src = new File("D:\\Downloads\\armadillo-9.900.3");
        File des = new File("E:\\");
        copy(src,des);
    }

    private static void copy(File src, File des) {
        if (src.isFile()){
            FileInputStream fileInputStream=null;
            FileOutputStream fileOutputStream=null;
            try {
                fileInputStream = new FileInputStream(src);
                String s = (des.getAbsolutePath().endsWith("\\") ? des.getAbsolutePath() : des.getAbsolutePath() + "\\") + src.getAbsolutePath().substring(3);
                File file = new File(s);
                if (!(file.exists())){
                    boolean newFile = file.createNewFile();
                }
                fileOutputStream = new FileOutputStream(s);
                byte[] bytes = new byte[1024 * 1024];
                int readCount=0;
                while ((readCount=fileInputStream.read(bytes))!=-1){
                    fileOutputStream.write(bytes);
                    fileOutputStream.flush();
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (fileInputStream!=null){
                    try {
                        fileInputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fileOutputStream!=null){
                    try {
                        fileOutputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return;
        }
        File[] files = src.listFiles();
        for (File file:files){
            if (file.isDirectory()){
                String s = (des.getAbsolutePath().endsWith("\\") ? des.getAbsolutePath() : des.getAbsolutePath() + "\\") + file.getAbsolutePath().substring(3);
                File file1 = new File(s);
                if (!(file1.exists())){
                    boolean mkdirs = file1.mkdirs();//创建父子目录
                }
            }
            copy(file,des);
        }
    }
}

13 java的序列化与反序列化

1、java.io.NotSerializableException:
Student对象不支持序列化!!!!

2、参与序列化和反序列化的对象,必须实现Serializable接口。

3、注意:通过源代码发现,Serializable接口只是一个标志接口:
public interface Serializable {
}
这个接口当中什么代码都没有。
那么它起到一个什么作用呢?
起到标识的作用,标志的作用,java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊待遇。
Serializable这个标志接口是给java虚拟机参考的,java虚拟机看到这个接口之后,会为该类自动生成
一个序列化版本号。

4、序列化版本号有什么用呢?
java.io.InvalidClassException:
com.bjpowernode.java.bean.Student;
local class incompatible:
stream classdesc serialVersionUID = -684255398724514298(十年后),
local class serialVersionUID = -3463447116624555755(十年前)
java语言中是采用什么机制来区分类的?
第一:首先通过类名进行比对,如果类名不一样,肯定不是同一个类。
第二:如果类名一样,再怎么进行类的区别?靠序列化版本号进行区分。

小鹏编写了一个类:com.bjpowernode.java.bean.Student implements Serializable
胡浪编写了一个类:com.bjpowernode.java.bean.Student implements Serializable
不同的人编写了同一个类,但“这两个类确实不是同一个类”。这个时候序列化版本就起上作用了。
对于java虚拟机来说,java虚拟机是可以区分开这两个类的,因为这两个类都实现了Serializable接口,
都有默认的序列化版本号,他们的序列化版本号不一样。所以区分开了。(这是自动生成序列化版本号的好处)

请思考?
这种自动生成序列化版本号有什么缺陷?
这种自动生成的序列化版本号缺点是:一旦代码确定之后,不能进行后续的修改,
因为只要修改,必然会重新编译,此时会生成全新的序列化版本号,这个时候java
虚拟机会认为这是一个全新的类。(这样就不好了!)

最终结论:
凡是一个类实现了Serializable接口,建议给该类提供一个固定不变的序列化版本号。
这样,以后这个类即使代码修改了,但是版本号不变,java虚拟机会认为是同一个类。

14 java IO 与 Properties联合使用

IO+Properties的联合应用。
非常好的一个设计理念:
以后经常改变的数据,可以单独写到一个文件中,使用程序动态读取。
将来只需要修改这个文件的内容,java代码不需要改动,不需要重新
编译,服务器也不需要重启。就可以拿到动态的信息。

类似于以上机制的这种文件被称为配置文件。
并且当配置文件中的内容格式是:
key1=value
key2=value
的时候,我们把这种配置文件叫做属性配置文件。

java规范中有要求:属性配置文件建议以.properties结尾,但这不是必须的。
这种以.properties结尾的文件在java中被称为:属性配置文件。
其中Properties是专门存放属性配置文件内容的一个类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值