IO流

IO:

  I:Input

  O:Output

通过IO可以完成文件的读和写

IO流的分类

  第一种分类:按照流的方向分类

    以内存为参照物,

      往内存中去叫做输入流,读

      从内存中出去叫做输出流,写

  第二种分类:按照读取数据的方式不同分类

    字节流:按照字节的方式读取数据,一次读取1个字节(byte)

    字符流:按照字符的方式读取数据,一次读取一个字符

java中所有的流都在:java.io.*中

java IO流的四大家族

java.io.InputStream:字节输入流

java.io.OutputStream:字节输出流

 

java.io.Reader:字符输入流

java.io.Writer:字符输出流

以上四个类都是抽象类(abstract class)

注意:

  所有的流都实现了java.in.Closeable接口,都是可关闭的,都有close()方法,流是一个

  管道,用完之后一定要关闭,不然会耗费资源,所有的输出流都实现了java.io.Flushable接口

  都有flush方法,输出流在最终输出之后一定要记得flush刷新一下,这个刷新表示,将管道

  当中剩余未输出的数据强行输出(清空管道),若没有flush可能导致数据丢失

flush()是输出流特有的,close()是所有流都有的

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

文件专属:

  java.io.FileInputStream

  java.io.FileOutputStream

  java.ioFileReader

  java.io.FileWriter

转换流(字节流转换成字符流)

  java.io.InputStreamReader

  java.io.OutputStreamWriter

缓冲流

  java.io.BufferedReader

  java.io.BufferedWriter

  java.io.BufferedInputStream

  java.io.BufferedOutputStream

缓冲流的构造器可以传入一个流,这个被传入的流叫做节点流,缓冲流则称为包装流

数据流

  java.io.DateInputStream

//创建数据专属的字节输出流
DateOutputStream dos = new DateOutputStream(new FileOutputStream(要输出的件路径));
//写数据
byte b = 100short s = 2int i = 1long l = 188float f = 9.8double d = 98878;
boolean sex = truechar c = 'd'//
dos.writeByte(b);//把数据以及数据的类型一并写入到文件当中
dos.writeShort(s);
dos.writeInt(i);
dos.writeLong(l);
//刷新
dos.flush();
//关闭,关闭最外层
dos.close();

  java.io.DateOutputStream

这是个数据字节输入流,DateOutputStream写的文件只能使用DateInputStream去读,并且读

的时候要知道写入的顺序,读的顺序和写的顺序一致,才能正常取出数据

DateInputStream dis = new DateInputStream(new FileInputStream(要读的文件路径));
//开始读
byte b = dis.readByte();
short s = dis.readShort();
//关闭流
dis.close();

 

标准流

  java.io.PrintWriter

  java.io.PrintStream

标准的字节输出流,默认输出到控制台,标准数据流不需要关闭,可以改变标准数据流的

输出方向,让他不在指向控制台,而是指向你所写的文件名

Printstream printStream = new PrintStream(文件名);
System.setOut(printSteam);
//在输出
System.out.println("fdierow");
System.out.println("sheofweo");
//以上内容不会在控制台上输出

 

对象流专属(用于序列化对象)

  java.io.ObjectInputStream(序列化对象)

//创建java对象
Student s = new Student(111,zh);
//序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStresam("文件名"))
//序列化对象
oos.writeObject(s);
//刷新
oos.flush();
//关闭
oos.close();

序列化多个对象

List<User> userList = new ArrayList<>();
userList.add(new User(1,"dsahf"));
userList.add(new User(2,"lisi"));
userList.add(new User(3,"hfsio"));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("users"));
//刷新
oos.flush();
//关闭
oos.close();

类必须实现Serializable接口,才能参与序列化和反序列化,Serializable接口是一个标志接口

  java.io.ObjectOutputStream(反序列化对象)

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("文件名"));
//开始反序列化,读
Object obj = ois.readObject();
//反序列化回来是一个学生对象,所以会调用学生对象的toString方法
System.out.println(obj);
ois.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("users"));
//Object obj = ois.readObject();
//System.out.println(obj instanceof List);
List<User> userList = (List<User>)ois.readObject();
for(User user : userList){
    System.out.println(user);
}
ois.close();

transient关键字表示游离的,不参与序列化

private transient String name;//name不参与序列化操作

序列化版本号发生改变,进行序列化和反序列化时出现异常:java.io.InvalidClassException

java通过什么来区分类?

  首先通过类名进行比对,如果类名不一样,肯定不是同一个类,如果类名一样就会通过

  序列化版本号进行区分,凡是实现了Serializable接口的类都默认会有序列化版本号,这种自动生成

  的序列化版本号会带来一些问题,一旦类的代码确定后,不能进行后续的修改,因为只要修改

  必然会生成全新的序列化版本号,这个时候jvm就会认为这是一个全新的类,因此我们应该手动

  给一个类添加固定不变的序列化版本号

IO和Properties联合使用

//新建一个输入流对象
FileReader reader = new FileReader("文件名");
//新建一个Map集合
Properties pro = new Properties();
//调用Properties对象的load方法将文件中的数据加载到Map集合中
pro.load(reader);//文件中的数据顺着管道加载到Map集合中,其中=左边为key,=右边为value
//通过key来获取value呢?
String username = pro.getProperty("username")
System.out.println(username);
//程序不用修改,只需要修改文件内容就可以获得新的内容

经常改变的数据可以单独放到一个文件中,使用程序动态读取,将来只需要修改这个文件内容,java代码不需要改动

不需要重新编译,服务器不需要重新启动就能拿到动态信息

类似于以上机制的文件叫做配置文件,配置文件格式:key=value

File类

常用方法

//创建一个file对象
File f1 = new File("D:\\file");;
//判断是否存在
System.out.println(f1.exists());
//如果D:\\file不存在,则以文件的形式创建出来
if(!f1.exists){//会有异常
//以文件形式新建
    //f1.createNewFile();
    //以目录的形式创建
    //f1.mkdir();
}
//可以创建多重目录吗
File2 f2 = new File("D:\\a\\b\\c\\d\\e\\f");
if(f2.exists()){
//以多重目录新建
    f2.mkdir();
}

File f3 = new File("D:\\coure\\f\\学习方法.txt");
//获取文件的父路径
String parentPath = f3.getParent();
System.out.println(parenPath);

File parentFile = f3.getParentFile();
System.out.println("获取绝对路径" + parentfile
.getAbsolutePath());

 

FileInputStream

文件字节输入流

FileInputStream fis = new FileInputStream(文件路径);

在此过程中会出现异常,需要捕捉异常,此时try…catch的finally就可以用于关闭流,关闭流的

前提是流不是空的

开始读

int i = fis.read();

调用read()方法,返回对应数字,但读到文件末尾,再读的时候,读取不到任何数据,返回-1,

可以使用循环来读取,但是一次读取一个字节,这样太麻烦,能不能一次读取多个字节?可以

int read(byte[] b):一次最多读取b.length个字节,提高效率

//要读取的文件含有6个字符
byte[] bytes = new byte[4];
//这个方法的返回值是:读取到的字节数量(不是字节本身)
int readCount = fis.read(bytes);
System.out.println(readCount);//4

执行过程:

  首先会读取四个字节的字符

  然后把剩下的两个字节的字符读取,此时读取到两个字符,但是会把前面的两个字符覆盖掉

读取到的字符放在byte[]中,如何把byte数组编程String输出,所有调用java.lang包下的String类的

构造方法传入一个byte数组进去,但是这样会输出数字中的所有元素转换成字符串,没有达到

想要的效果,应该调用String(byte[] bytes,int offset,int length),第二个参数为起始位置

第三个参数为长度

FileOutputStream

文件字节输出流,写

fos = new FileOutputStream("myfile");(1)
fos = new FileOutputStream("文件路径",boolean类型);(2//开始写
byte[] bytes = {97,98,99,100};
//将byte数组全部写出
for.write(bytes);
//将byte[]数组一部分写出
fos.write(bytes,0,2);
//写完之后,一定要刷新
fos.flush();
FileInputStream和FileOutputStream
public class Demo1 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fs = new FileOutputStream("src/com/IO流/测试文件2",true);
        byte[] b = {100,101,102,109};
        fs.write(b);
        fs.flush();
        fs.close();

        FileInputStream fi = new FileInputStream("src/com/IO流/测试文件2");
        byte[] by = new byte[8];
        int len = fi.read(by);
        System.out.println(new String(by,0,len));

    }
}
public class Demo2 {
    public static void main(String[] args) throws IOException {
        FileInputStream fi = new FileInputStream("src/com/IO流/test");
        FileOutputStream fo = new FileOutputStream("src/com/IO流/test1");

        byte[] b = new byte[9];
        int readCount = 0;
        while ((readCount = fi.read(b)) != -1){
            fo.write(b,0,readCount);
        }
    }
}
FileReader和FileWriter
public class Demo3 {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("src/com/IO流/test");
        char[] b = new char[4];
        int len = 0;
        while ((len = fr.read(b)) != -1){
            System.out.println(new String(b,0,len));
        }

        FileWriter fw = new FileWriter("src/com/IO流/test2");
        char[] c = {'a','b'};
        fw.write(c);
        fw.flush();
        fw.close();
    }
}
public class Demo4 {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("src/com/IO流/a");
        FileReader fr = new FileReader("src/com/IO流/b");

        char[] c = new char[1024*1024];
        int len = 0;
        while ((len = fr.read(c)) != -1){
            fw.write(c,0,len);
        }

        fw.flush();
        fw.close();
        fr.close();
    }
}
缓存流
public class Demo5 {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("src/com/IO流/我");
        BufferedReader br = new BufferedReader(fr);
        String s = null;
        int i = 1;
        while ((s = br.readLine()) != null){
            System.out.println("第" + i + "行:" + s);
            i++;
        }
        br.close();
    }
}
完整的代码片段
String s = jt.getText();
                FileInputStream fi = null;
                try {
                    fi = new FileInputStream(s);
                } catch (FileNotFoundException fileNotFoundException) {
                    fileNotFoundException.printStackTrace();
                }
                byte[] b = new byte[1024*1024];
                int len = 0;
                while (true){
                    try {
                        if (!((len = fi.read(b)) != -1)) {
                            break;
                        }else {
                            ja.setText(new String(b,0,len));
                        }
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }

                }
                try {
                    fi.close();
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }