JAVA笔记(18)--- IO流 精讲

Posted 猿头猿脑的王狗蛋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA笔记(18)--- IO流 精讲相关的知识,希望对你有一定的参考价值。

FileInputStream-FileOutputStream:


1.构造方法:

new ( "文件的 绝对路径/相对路径" ) ;

//注意构造方法的参数是字符串类型

//绝对路径为带磁盘目录的,如:C:\\java-prictice\\javaseplus\\text

//相对路径:(IDEA默认当前路径:当前模块的根)+相对路径

//通过“电脑”复制文件位置的时候,要在上边的那个路径的后面+ “\\具体文件名”,否则此路径只是代表你看到界面的上一个目录;

//把路径粘贴到构造方法里的时候,IDEA工具会自动把“ \\ ”转换为“ \\\\ ”,实际上,把“ \\\\ ”改为“ / ”也是正确的;

FileInputStream 引用文件,代表将此文件作为读的对象;

FileOutputStream 引用文件,代表将此文件作为写的对象(输出在此文件中),若此文件不存在,则会自动创建;

2.常用方法:

1)FileInputStream . read ( bytes数组 ) //读取流的字节,并将读取的字节放到byte数组里,返回读取字节个数(int)[ 若读到文件末尾,则返回-1 ]

2)FileInputStream . available ( int ) //返回流当前未读取的字节个数

3)FileInputStream . skip ( int )  //跳过几个字节不读

3.注意:

1)为方便 finally语句中对流的关闭,所以一般在try外边声明空指针引用,在try里边new流对象;

2)声明的byte数组长度不宜过长,因为内存中很难找到一条特别长的连续空间;

3)每个流不能一起(并列)关闭,避免出现异常导致有些流无法关闭;

4.拷贝文件:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//File字节流拷贝
public class FileInputStreamTest {
    public static void main(String[] args) {
        //声明 FileInputStream 引用为空
        FileInputStream fis=null;
        //声明 FileOutputStream 引用为空
        FileOutputStream fos=null;
        //拷贝的重要操作(抛出异常的部分)放到try-catch里
        try {
            //创建文件字节输入流
            fis=new FileInputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debug.txt");
            //创建文件字节输出流
            fos=new FileOutputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debugFISCopy.txt",true);
            //创建长度为100的数组bytes,元素类型为byte(字节)
            byte [] bytes=new byte[100];
            //声明“读取字节个数”的变量
            int readCount;
            //读取fis的“bytes.length”个字节,同时判断是否退出循环
            //循环退出条件:读取字节个数为 -1
            while ((readCount=fis.read(bytes))!=-1){
                //将此时bytes里装的字节写入fos对象里
                fos.write(bytes,0,readCount);
            }
            //刷新输出流
            fos.flush();
        } catch (FileNotFoundException e) {//用IDEA工具生成
            e.printStackTrace();
        } catch (IOException e) {//用IDEA工具生成
            e.printStackTrace();
        } finally {//fis与fos分开关闭,避免彼此的影响
            if (fis!=null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos!=null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
 

 

FileReader-FileWriter:


1.构造方法:

FileReader  构造方法参考 《FileInputStream-FileOutputStream》

FileWriter   构造方法:

//此流的writer方法,会将写的字符覆盖整个文本(原文件中的字符会被删除,然后录入写的字符)
FileWriter fileWriter1=new FileWriter("C:\\\\Program Files\\\\Git\\\\bin");
//此流的writer方法,会将写的字符添加到文本后面(原文件中的字符不变)
FileWriter fileWriter2=new FileWriter("C:\\\\Program Files\\\\Git\\\\bin",true);

2.常用方法:

参照 《FileInputStream-FileOutputStream》与下面的《拷贝文件》;

3.注意:

字节流拷贝文件时,数组声明为byte类型,那用字符流时,自然就声明为char类型;

字符流绑定的文件格式只能是“ . txt ” 格式;

4.拷贝文件:

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
//File字符流拷贝
public class FileWriteTest {
    public static void main(String[] args) {
        FileReader in=null;
        FileWriter out=null;
        try {
            in=new FileReader("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debug.txt");
            out=new FileWriter("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debugFWCopy.txt",true);
            char [] chars=new char[3];
            int readCount;
            while ((readCount=in.read(chars))!=-1){
                out.write(chars,0,readCount);
            }
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (in!=null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out!=null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 

BufferedReader-BufferedWriter:


1.BufferedReader,BufferedWriter,都是自带缓冲的流,换句话说,不需要提供数组,也可以拷贝文本;

2.构造方法:

BufferedReader 参数:字符输入流(FileRead)

BufferedWriter  参数:字符输出流(FileWriter)

InputStreamReader 参数:字节输入流(FileInputStream)//将字节输入流转换为字符输出流

OutputStreamWriter 参数:字节输出流(FileOutputStream)//将字节输出流转换为字符输出流

综上,可以这么写:

BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debug.txt")));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debugBRCopy.txt",true)));

3.常用方法:

BufferedReader . readLine ( ) //读取流当前行

BufferedWriter . write ( ) //写入流当前行

4.拷贝文件代码:

import java.io.*;
//Buffered字符流拷贝
public class BufferedReadTest {
    public static void main(String[] args) {
        BufferedReader br=null;
        BufferedWriter bw=null;
        try {
            br=new BufferedReader(new InputStreamReader(new FileInputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debug.txt")));
            bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debugBRCopy.txt",true)));
            String read;
            while ((read=br.readLine())!=null){
                bw.write(read);
              	//让文本一行一行的写出来
                bw.write("\\n");
            }
            bw.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bw!=null){
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

 

DataOutputStream-DataInputStream:


1.DataOutputStream,DataInputStream 都是数据专属流,这个流可以将数据连同数据的类型一并写入文件;

2.注意:

DataOutputStream 写的文件,只能用 DataInputStream 去读,并且读的时候,读的顺序必须和写的顺序一样,才可以正常取出数据;

专属流读和写的文件都不是普通文档(用记事本看不到正常信息);

3.“读写”训练:

import java.io.*;
public class DataOutputStreamTest {
    public static void main(String[] args) {
        DataOutputStream dos=null;
        DataInputStream dis=null;
        try {
            dos=new DataOutputStream(new FileOutputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\DOS.txt",true));
            dis=new DataInputStream(new FileInputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\DOS.txt"));
            byte b=100;
            short s=200;
            int i=300;
            long l=400l;
            float f=500.0f;
            double d=600.0;
            boolean sex=true;
            char c=\'c\';
            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();
            System.out.println(dis.readByte());
            System.out.println(dis.readShort());
            System.out.println(dis.readInt());
            System.out.println(dis.readLong());
            System.out.println(dis.readFloat());
            System.out.println(dis.readDouble());
            System.out.println(dis.readBoolean());
            System.out.println(dis.readChar());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (dis!=null){
                try {
                    dis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (dos!=null){
                try {
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
点击查看输出结果
100
200
300
400
500.0
600.0
true
c

Process finished with exit code 0

 

PrintStream:


1.PrintStream 属于标准字节输出流,默认输出到控制台上;

2.举个栗子:

import java.io.PrintStream;
public class pra{
    public static void main(String[] args) {
        PrintStream ps=System.out;
        ps.println("输出到控制台上");
    }
}

运行结果:
------------------------
输出到控制台上

Process finished with exit code 0

3.改变 PrintStream 的输出方向:

  import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class PrintStreamTest {
    public static void main(String[] args) {
        //向日志中导入msg字符串
        Logger.log("调用了 System 的 gc() ,建议启动垃圾回收器");
        Logger.log("调用了 UserSystem 的 book()");
        Logger.log("用户尝试登录,验证失败");
    }
}
//日志类
class Logger {
    public static void log(String msg) {//获取字符串msg
        //声明空引用
        PrintStream printStream=null;
        try {
            //printStream流 绑定此文件
            printStream = new PrintStream(new FileOutputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\log.txt",true));
            //改变System.out的输出方向(输出的东西会进入printStream流)
            System.setOut(printStream);
            //获取此时刻时间
            Date nowTime =new Date();
            //自定义时间格式
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
            //将nowTime转换为我们的自定义格式,然后将msg字符串拼接上,最后输出
            System.out.println(sdf.format(nowTime)+" : "+msg);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

4.注意:标准输出流不需要手动 clsoe 流;

 

File 类:


1.概述:File 类与IO流四大家族无继承关系,所以File类不能完成文件的读与写;

2.构造方法:new ( " 路径 " ) ;

3.常用方法:

引用 . createNewFile ( ) //在指定位置创建一个空文件(成功就返回true,如果已存在就不创建,然后返回false)

引用 . mkdir ( ) // 在指定位置创建一个文件夹

引用 . mkdirs ( ) // 在指定位置创建一个多重文件夹

 

引用 . exists ( ) // 判断文件或文件夹是否存在

引用 . isFile ( ) // 判断是否是一个文件,返回 boolean

引用 . isDirectory ( ) // 判断是否是一个目录,返回 boolean

 

引用 . getAbsolutePath ( ) // 获取文件的绝对路径,与文件是否存在没关系

引用 . getParent ( ) // 返回此文件路径的父路径(String),如果此路径名没有指定父目录,则返回null

引用 . getName ( ) //  获取文件或文件夹的名称,不包含上级路径

引用 . length ( ) // 返回此文件大小(字节)

引用 . lastModified ( ) // 获取文件最后一次被修改的时间

引用 . listFiles ( ) // 返回当前目录下的所有子文件(返回值类型为 FIle数组) 

 

ObjectInputStream-ObjectOutputStream:


此体系知识请参考《上边的》

结合栗子理解:

  import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class ObjectInputStreamTest {
    public static void main(String[] args) throws Exception{//将所有异常抛出
        //ObjectOutputStream 绑定Cars文件(若无则新建)
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("Cars"));
        //ObjectInputStream 绑定已存在的Cars文件
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("Cars"));
        //创建专门装Car的集合cars
        List<Car> cars=new ArrayList<>();
        //向cars集合中添加元素
        cars.add(new Car(1,"大众"));
        cars.add(new Car(2,"法拉利"));
        cars.add(new Car(3,"丰田"));
        //将集合cars写入oos绑定文件中(反序列化)
        oos.writeObject(cars);
        //读取ois绑定文件中的所有对象(序列化),并强转为List<Car>类型,最后将所有对象装到carsList集合中
        List<Car> carsList= (List<Car>) ois.readObject();
        //遍历carsList集合
        for (Car car:carsList) {
            System.out.println(car);
        }
        oos.flush();
        oos.close();
        ois.close();
    }
}
class Car implements Serializable{
    private static final long serialVersionUID = -2630683108946058933L;
    private int no;
    private String brand;
    public Car() {
    }
    public Car(int no, String model) {
        this.no = no;
        this.brand = model;
    }
    public int getNo() {
        return no;
    }
    public void setNo(int no) {
        this.no = no;
    }
    public String getModel() {
        return brand;
    }
    public void setModel(String model) {
        this.brand = model;
    }
    @Override
    public String toString() {
        return "Car{" +
                "no=" + no +
                ", model=\'" + brand + \'\\\'\' +
                \'}\';
    }
}

控制台输出结果:
---------------------------
Car{no=1, model=\'大众\'}
Car{no=2, model=\'法拉利\'}
Car{no=3, model=\'丰田\'}

Process finished with exit code 0

 

序列化 / 反序列化:


1.概述:

2.自定义的类需要实现 Serializable 接口,才支持序列化和反序列化;

3.序列化版本号:

实现了 Serializable 接口的类,系统会为其自动生成一个序列化版本号,但是最好咱们手动生成版本号举个栗子:

import java.io.Serializable;
class Car implements Serializable{
    private static final long serialVersionUID = 8342087006090942735L;
}

java虚拟机识别一个类,首先看类名,其次看序列化版本号;

4.被 transient 关键字修饰的属性不参与序列化:

private transient String name;

 

IO+Properties:


1.优点:

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

2.当配置文件中的内容格式为:

key1=value 

key2=value

我们把这种配置文件叫做属性配置文件

3.注意:

java 规范中有要求:属性配置文件建议以 “ . properties ”结尾;这种以 ”. properties “结尾的文件在java中被称为:属性配置文件;

Properties 是专门存放属性配置文件内容的一个类;

4.栗子老师:

import java.io.FileReader;
import java.util.Properties;
public class IOProperties {
    public static void main(String[] args) throws Exception{
        //FileReader绑定文件
        FileReader reader=new FileReader("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\IOPropertiesTest.txt");
        Properties pro=new Properties();
        //将FileReader绑定文件载入Pro集合
        pro.load(reader);
        //通过key获取value
        System.out.println(pro.getProperty("username"));
        System.out.println(pro.getProperty("password"));
        System.out.println(pro.getProperty("data"));
        System.out.println(pro.getProperty("不存在的key,会输出 null"));
    }
}

运行结果:
-----------------------------
a01
123456a01
null
null

Process finished with exit code 0

 

随笔:


节点流:本身作为包装流的构造方法的参数;

包装流:包装流的构造方法的参数是节点流;

 

以上是关于JAVA笔记(18)--- IO流 精讲的主要内容,如果未能解决你的问题,请参考以下文章

高薪程序员&面试题精讲系列22之说说Java的IO流,常用哪些IO流?

java缓冲字符字节输入输出流:java.io.BufferedReaderjava.io.BufferedWriterjava.io.BufferedInputStreamjava.io.(代码片段

Java笔记(22):IO流(04)

Java 学习笔记 - IO篇:常见的IO流Stream以及相互关系

Java笔记:Java 流(Stream)文件(File)和IO

Java学习笔记之:Java 流