IO流

数据流的方向可以分为:输入流,输出流。输入和输出是针对内存来说的,从内存中出来就是输出,到内存中去就是输入。

读取数据的方式可以分为:字符流,字节流。字节流按照字节的方式的读取,字符流按照字符的方式读取,也就是一次读取两个字节,因为java中一个字符占两个字节。

那么什么情况下使用字节流?当读取图片、声音、视屏等二进制文件的时候,不过如果是纯文本的时候也是可以用字节流的!字节流万能的。

当读取纯文本的时候用字符流!那么读Word文档要用什么?Word文档不光有文字还有格式,所以不是纯文本,要用字节流。

Java中所有字节流都以Stream结尾,所有的字符流都含有Reader或者Writer

InputStreamReader、OutputStreamWriter 属于转换流,字节流转字符流

FileInputStream

文件字节输入流,按照字节方式读取文件。在D盘新建文件IOTest.txt,内容为abcde123456789

package iotest;

import java.io.FileInputStream;

/**
 * Created by Arenas on 2016/10/28.
 */
public class IOTest01 {

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

        FileInputStream fis = new FileInputStream("D:/IOTest.txt");
        //available()返回流中剩余的估计字节数
        System.out.println(fis.available()); //14
        System.out.println(fis.read());     //97
        System.out.println(fis.available());//13
        //跳过两个字节
        fis.skip(2);
        System.out.println(fis.read()); //100

        fis.close();
    }

}

FileOutputStream

package iotest;

import java.io.FileOutputStream;

/**
 * Created by Arenas on 2016/10/28.
 */
public class IOTest02 {

    public static void main(String[] args){
        FileOutputStream fos = null;
        try{
            //直接添加,会覆盖原有内容
            //如果该文件不存在,则会创建一个文件
//            fos = new FileOutputStream("D:/IOTest.txt");
            //以追加的方式添加到文件中
            fos = new FileOutputStream("D:/IOTest.txt" , true);
            String str = "Hello World!";
            //将String转换成byte数组
            byte[] bytes = str.getBytes();
            //将btyes中数据全部写入
//            fos.write(bytes);
            fos.write(bytes , 3 , 2);//去掉前面三个,从第四个开始数两个数写入,也就是追加lo
            //推荐最后为了将数据完整的写入硬盘,执行flush()
            fos.flush();//强制写入
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                if (fos != null)
                    fos.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

 字节流的文件的复制粘贴

package iotest;

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

/**
 * Created by Arenas on 2016/10/28.
 */
public class IOTest04 {
    public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("D:/iopic.jpg");
        FileOutputStream fos = new FileOutputStream("D:/newiopic.jpg");
        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) != -1){
            fos.write(bytes , 0 , length);
        }
        fis.close();
        fos.close();
    }
}

FileReader

package iotest;

import java.io.FileReader;

/**
 * Created by Arenas on 2016/10/28.
 * java.lang.Object
 继承者 java.io.Reader
    继承者 java.io.InputStreamReader 转换流:字节流--->字符流
        继承者 java.io.FileReader 文件字符输入流
 */
public class IOTest05 {
    public static void main(String[] args){
        FileReader reader = null;
        try{
            reader = new FileReader("D:/IOTest.txt");
            char[] chars = new char[512];//1kb,因为是读字符,所以用char而不是byte
            int length;
            while ((length = reader.read(chars)) != -1){
                System.out.println(new String(chars , 0 , length));
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                if (reader != null)
                    reader.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

字符流的文件复制和粘贴

package iotest;

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

/**
 * Created by Arenas on 2016/10/28.
 * 注意只能操作纯文本
 */
public class IOTest06 {
    public static void main(String[] args) throws Exception{
        FileReader reader = new FileReader("D:/IOTest.txt");
        FileWriter writer = new FileWriter("D:/newIOTest.txt");
        char[] chars = new char[512];
        int length;
        while ((length = reader.read(chars)) != -1)
            writer.write(chars , 0 , length);
        writer.flush();
        reader.close();
        writer.close();
    }
}

 BufferedReader

package iotest;

import java.io.BufferedReader;
import java.io.FileReader;

/**
 * Created by Arenas on 2016/10/29.
 * BufferedReader
 */
public class IOTest07 {
    public static void main(String[] args) throws Exception{
        //根据流出现的位置,又可以分为包装流(处理流)、节点流
        //比如这里fileReader是一个节点流,bufferedReader是一个处理流,相当于在管子外面套了缓存区
        FileReader fileReader = new FileReader("D:/剪刀手爱德华.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String str;
        while ((str = bufferedReader.readLine()) != null)
            System.out.println(str);//readLine()方法读取一行,但是行尾不带换行符!!所以要换行需要println()
        bufferedReader.close();//这里关闭只要关闭最外面的包装流,这里有一个装饰者模式
    }
}

关于节点流和包装流

package iotest;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;

/**
 * Created by Arenas on 2016/10/29.
 */
public class IOTest08 {
    public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("D:/IOTest.txt");//文件字节输入流
        InputStreamReader isr = new InputStreamReader(fis);//将字节流转换成字符流
        BufferedReader reader = new BufferedReader(isr);
        //这里fis相对于isr来说,fis是节点流,isr是包装流
        //而isr相对于reader来说,isr又是节点流,reader是包装流
        //所以包装流和节点流是相对来说的
    }
}

DataInputStream/DataOutputStream

package iotest;

import java.io.DataOutputStream;
import java.io.FileOutputStream;

/**
 * Created by Arenas on 2016/10/30.
 * DataOutputStream,数据字节输出流,这是一个比较特殊的流
 * 可以将内存中 int i = 10 写到文件中,但是写进去的不是字符串,而是二进制数据,并且是带类型的!!!
 */
public class IOTest09 {
    public static void main(String[] args) throws Exception{
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("D:/IOTest.txt"));
        dos.writeByte(1);
        dos.writeBoolean(false);
        dos.writeInt(3);
        dos.writeDouble(3.3);
        dos.writeFloat(3.4f);

        dos.flush();
        dos.close();
    }
}

文件的数据直接打开是乱码,要用对应的DataInputStream来读

package iotest;

import java.io.DataInputStream;
import java.io.FileInputStream;

/**
 * Created by Arenas on 2016/10/30.
 */
public class IOTest11 {
    public static void main(String[] args) throws Exception{
        DataInputStream dis = new DataInputStream(new FileInputStream("D:/IOTest.txt"));
        //这里去读取数据的顺序必须跟写进去的顺序相同,不能多读,不然会抛出java.io.EOFException
        byte b = dis.readByte();
        boolean flag = dis.readBoolean();
        int i = dis.readInt();
        int i1 = dis.readInt();
        double d = dis.readDouble();
//        float f = dis.readFloat();
        System.out.println(b);
        System.out.println(flag);
        System.out.println(i);
        System.out.println(i1);//1074423398 d和i1都错了 虽然d是对应的正确的类型!!
        System.out.println(d);//1.9035983735196154E185
//        System.out.println(f);

        dis.close();
    }
}

PrintStream/PrintWriter

package iotest;

import java.io.FileOutputStream;
import java.io.PrintStream;

/**
 * Created by Arenas on 2016/10/30.
 * java.io.PrintStream;标准的输出流,默认打印到控制台
 * java.io.PrintWriter;以字符的方式
 */
public class IOTest10 {
    public static void main(String[] args) throws Exception{
        //默认打印到控制台
        PrintStream printStream = System.out;
        printStream.println("Hello World!");
        //改变输出方向setOut,输出到IOTest.txt中
        System.setOut(new PrintStream(new FileOutputStream("D:/IOTest.txt")));
        System.out.println("must tear down the wall");
    }
}

ObjectInputStream/ObjectOutputStream

package iotest;

import java.io.Serializable;

/**
 * Created by Arenas on 2016/10/30.
 * Serializable这个接口内没有任何方法,只是起到一个标识的作用,称做标识接口,像这样的接口还有java.lang.Cloneable
 * JVM看到标识接口会对他特殊待遇
 */
public class User implements Serializable {

    private String name;

    public User(String name){
        this.name = name;
    }

    @Override
    public String toString() {
        return "User -- > name = " + name;
    }
}
package iotest;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

/**
 * Created by Arenas on 2016/10/30.
 * java.io.ObjectInputStream;将硬盘中的数据反序列化到JVM内存中
 * java.io.ObjectOutputStream;序列化Java对象到硬盘
 */
public class IOTest12 {
    public static void main(String[] args) throws Exception{
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:/IOTest.txt"));
        User user = new User("kobe");//要传输的对象必须序列化!否则会抛出异常
        oos.writeObject(user);
        oos.flush();
        oos.close();
    }
}
package iotest;

import java.io.FileInputStream;
import java.io.ObjectInputStream;

/**
 * Created by Arenas on 2016/10/30.
 */
public class IOTest13 {
    public static void main(String[] args) throws Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:/IOTest.txt"));
        Object o = ois.readObject();//注意在反序列化的时候User.java这个文件不能删,因为在readObject的时候要创建对象,创建对象需要类
        System.out.print(o);//User -- > name = kobe
        ois.close();
    }
}

 serialVersionUID

 之前有说到User在反序列化时是不能删的,如果删掉改变User呢?比如在User中加条private int age;属性,这个时候反序列化就会抛出异常

Exception in thread "main" java.io.InvalidClassException: iotest.User; local class incompatible: stream classdesc serialVersionUID = 4408450428999604713, local class serialVersionUID = 6602202455712956108

因为反序列化时会重新编译User,得到serialVersionUID跟流里面的User的serialVersionUID不同。这是由于在User实现serializable接口的时候,JVM会提供一个“特殊待遇”----给该类加上一个属性static final long serialVersionUID = 232313231L;在改变User后,由于User重新编译,JVM会重新分配一个序列化版本号。

所以,这里可以自己加上serialVersionUID这条属性,不让系统自动生成。那么不管该类如何变,序列化版本号都不会改变了。

package iotest;

import java.io.Serializable;

/**
 * Created by Arenas on 2016/10/30.
 * Serializable这个接口内没有任何方法,只是起到一个标识的作用,称做标识接口,像这样的接口还有java.lang.Cloneable
 * JVM看到标识接口会对他特殊待遇
 */
public class User implements Serializable {
    //自己加上版本号
    static final long serialVersionUID = 2323123123L;
    private String name;
    //增加一条属性
    private int age;

    public User(String name){
        this.name = name;
    }

    //改变toString方法
    @Override
    public String toString() {
        return "User -- > name = " + name + " , age = " + age;
    }
}

再运行IOTest13会得到:User -- > name = kobe , age = 0。没有产生类的兼容性问题

如果需要某个属性不参加序列化,那么就加上transient关键字修饰,如

private transient String name;

再运行IOTest13反序列化会得到

User -- > name = null , age = 0

File

文件和目录路径名的抽象表示形式。也就是说文件夹和文件都是一个File

package iotest;

import java.io.File;

/**
 * Created by Arenas on 2016/10/31.
 * 递归找出所有子文件
 */
public class FileTest01 {
    public static void main(String[] args)throws Exception{
        File file = new File("D:/Android");
        findAllFile(file);
    }

    public static void findAllFile(File file){
        //当是文件的时候就返回
        if (file.isFile())
            return;
        //当是目录的时候就遍历所有文件
        File[] files = file.listFiles();
        for (File f : files){
            System.out.println(f.getAbsolutePath());
            findAllFile(f);
        }
    }
}
原文地址:https://www.cnblogs.com/i-love-kobe/p/6007189.html