JavaIO流

目录

1 IO流

1.1介绍

1.2流的分类

1.3IO体系图

2 文件

2.1文件的创建(三种方法)

2.2文件的操作

2.3mkdirs和mkdir方法

3 文件输入/输出

3.1FileInputStream和FileOutputStream

3.2FileReader和FileWriter

close和flush的区别

3.3ObjectInputStream和ObjectOutputStream 

4 节点流和处理流 

4.1介绍

4.2区别和联系

4.3BufferedReader和BufferedWriter

4.4BufferedInputStream和BufferedOutputStream 

5 数据输入/输出流

5.1DataInputStream和DataOutputStream

5.2代码实现

6 转换流

6.1InputStreamReader和OutputStreamWriter

6.2代码实现


1 IO流

1.1介绍

        java中I/O的操作主要是靠java.io包下面的类和接口来实现的,进入输入,输出操作.输入也可以叫做读取数据,输出也可以叫做写入数据.

1.2流的分类

  • 按照数据流向分为输入流(InputStream)和输出流(OutputStream)。
  • 按照数据类型分为字节流(Byte Stream)和字符流(Character Stream)。
  • 按照流的角色不同分为包装流和节点流

1.3IO体系图

在这里插入图片描述

2 文件

2.1文件的创建(三种方法)

public class FlieCreate01 {
    public static void main(String[] args) {
        File file = new File("D:\\word.txt");
        if(file.exists()){
            file.delete();
            System.out.println("文件已删除");
        }else{
            try{
                file.createNewFile();
                System.out.println("文件已建立");
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
public class FileCreate02 {
    public static void main(String[] args) {
        //父目录的根目录+子路径
        File file = new File("D:\\");
        String fileName="word2.txt";
        File word2 = new File(file,fileName);

        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class FileCreate03 {
    public static void main(String[] args) {
        //根据new(String parent,String child)  父目录+子路径
        String parentPath="D:\\";
        String fileName="word3.txt";
        File file = new File(parentPath, fileName);

        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2文件的操作

public class Demo {
    public static void main(String[] args) {
        File file = new File("D:\\a.txt");
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("是否是文件"+file.isFile());
        System.out.println("是否被隐藏"+file.isHidden());
        System.out.println("文件是否存在"+file.exists());
        System.out.println("文件的字节长度"+file.length());
        System.out.println(file.mkdirs());
        System.out.println("文件的绝对路径"+file.getAbsolutePath());
        System.out.println("文件是否可读"+file.canRead());
        System.out.println("文件的名字是"+file.getName());
        System.out.println("父路径为"+file.getParent());
    }
}

 运行结果如下:

2.3mkdirs和mkdir方法

查阅API可知两者都是:创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录。返回值为boolean类型。

mkdirs可以创建多级目录而mkdir只能创建单个目录。

可以配合 public File[] listFiles() 方法进行使用,用来遍历目录。

3 文件输入/输出

3.1FileInputStream和FileOutputStream

        二者都用来操作磁盘文件,如果用户的文件读取需求比较简单,则可以使用FileInputStream,该类继承在InputStream,FileInputStream和FileOutputStream有着相同的参数构造方法,创建一个FileOutputStream对象时,可以指定不存在的文件名,但此文件不能是一个已被其他程序打开的文件,下面实例就是使用FileInputStream和FileOutputStream实现文件的读取和写入功能的。

public class Demo1 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\test.txt");
        byte[] bytes="我有一个小毛驴,我从来也不骑".getBytes();
        fileOutputStream.write(bytes);
        fileOutputStream.close();

        byte[] bytes1 = new byte[8];
        FileInputStream fileInputStream = new FileInputStream("D:\\test.txt");
        int cnt=fileInputStream.read(bytes1);
        System.out.println("文件中的信息是:"+new String(bytes1,0,cnt));
        fileInputStream.close();
    }
}

 程序运行后会向D盘根目录下的test.txt文件写入一段文字,并且在控制台输出。

说明

        虽然Java在程序结束时会自动关闭所有打开的流,但是当使用完流后,显式的关闭所有打开的流是一个好习惯,一个被打开的流有可能会用尽系统资源,这却决于平台和实现,如果没有将打开的流关闭,当另一个程序试图打开另一个流时,可能会得不到需要的资源。

3.2FileReader和FileWriter

        使用 FileReader和FileWriter对应了FileInputStream和FileOutputStream,FileReader顺序读取文件,只要不关闭流,每次调用read方法就顺序的读取了源中剩余内容,直到源末尾

public void readFile() {
        System.out.println("~~~readFile ~~~");
        String filePath = "e:\\story.txt";
        FileReader fileReader = null;
 
        int readLen = 0;
        char[] buf = new char[8];
        //1. 创建FileReader对象
        try {
            fileReader = new FileReader(filePath);
            //循环读取 使用read(buf), 返回的是实际读取到的字符数
            //如果返回-1, 说明到文件结束
            while ((readLen = fileReader.read(buf)) != -1) {
                System.out.print(new String(buf, 0, readLen));
            }
 
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileReader != null) {
                    fileReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

close和flush的区别

          简单来说,close包含flush功能,但是flush具备刷新完,还可以继续写操作,close执行完了就流关闭了,不能再写入,所以,不能用close来代替flush。 查看close的源码可得

@SuppressWarnings("try")
    public void close() throws IOException {
        try (OutputStream ostream = out) {
            flush();
        }
    }

3.3ObjectInputStream和ObjectOutputStream 

①  功能:提供了对基本类型或对象类型的序列化和反序列化的方法;

②  ObjectOutputStream 提供 序列化功能;

③   ObjectInputStream 提供 反序列化功能。

//ObjectOutStream_类
public class ObjectOutStream_ {
    public static void main(String[] args) throws Exception {
        //序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
        String filePath = "D:\\data.dat";
 
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
 
        //序列化数据到 e:\data.dat
        oos.writeInt(100);// int -> Integer (实现了 Serializable)
        oos.writeBoolean(true);// boolean -> Boolean (实现了 Serializable)
        oos.writeChar('a');// char -> Character (实现了 Serializable)
        oos.writeDouble(9.5);// double -> Double (实现了 Serializable)
        oos.writeUTF("abc");//String
        //保存一个dog对象
        oos.writeObject(new Dog("旺财", 10));
        oos.close();
        System.out.println("数据保存完毕(序列化形式)");
 
 
    }
}
//如果需要序列化某个类的对象,实现 Serializable
public class Dog implements Serializable {
    private String name;
    private int age;
   
 
    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }
 
    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
}
// ObjectInputStream_类
public class ObjectInputStream_ {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
 
        //指定反序列化的文件
        String filePath = "D:\\data.dat";
 
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
 
        //1. 读取(反序列化)的顺序需要和你保存数据(序列化)的顺序一致
        //2. 否则会出现异常
 
        System.out.println(ois.readInt());
        System.out.println(ois.readBoolean());
 
        System.out.println(ois.readChar());
        System.out.println(ois.readDouble());
        System.out.println(ois.readUTF());
 
 
        //dog 的编译类型是 Object , dog 的运行类型是 Dog
        Object dog = ois.readObject();
        System.out.println("运行类型=" + dog.getClass());
        System.out.println("dog信息=" + dog);//底层 Object -> Dog
 
        //这里是特别重要的细节:
 
        //1. 如果我们希望调用Dog的方法, 需要向下转型
        //2. 需要我们将Dog类的定义,放在到可以引用的位置
        Dog dog2 = (Dog)dog;
        System.out.println(dog2.getName()); //旺财..
 
        //关闭流, 关闭外层流即可,底层会关闭 FileInputStream 流
        ois.close();
 
 
    }
}
 

注意事项 

1.读写顺序要一致

2.要求序列化对象实现Serializable

3.序列化对象中建议添加SerialVersionUID,可以提高兼容性

4.被transient修饰的成员不会被序列化或反序列化

4 节点流和处理流 

4.1介绍

1)节点流可以从一个特定的数据源【数据源就是存放数据的地方】读写数据,如FileReader、FileWriter;

2)处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,也更加灵活,如BufferedReader、BufferedWriter。

4.2区别和联系

(1)节点流是底层流/低级流,直接跟数据源相接;

(2)处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来实现输入输出;

(3)处理流(包装流)对节点流进行包装,使用了 修饰器设计模式,不会直接于数据源相连。

4.3BufferedReader和BufferedWriter

下面代码演示用BufferedReader和BufferedWriter拷贝文件

public class Demo {
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new FileReader("D:\\a.txt"));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("D:\\b.txt"));
        String a="";
        while((a=bufferedReader.readLine())!=null){
        //bufferedReader.readLine()的返回值是一个字符串所以判断条件是null
        //而read()的返回值是int,判断条件是是否为-1
            bufferedWriter.write(a);
            bufferedWriter.newLine();
        }
        bufferedReader.close();
        bufferedWriter.close();
    }
}

4.4BufferedInputStream和BufferedOutputStream 

BufferedInputStream是字节流,在创建BufferedInputStream时,会创建内部缓冲区数组。 

public class BufferedCopy02 {
    public static void main(String[] args) {
 
        String srcFilePath = "D:\\a.java";
        String destFilePath = "D:\\a3.java";
 
        //创建BufferedOutputStream对象BufferedInputStream对象
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
 
        try {
            //因为 FileInputStream  是 InputStream 子类
            bis = new BufferedInputStream(new FileInputStream(srcFilePath));
            bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
 
            //循环的读取文件,并写入到 destFilePath
            byte[] buff = new byte[1024];
            int readLen = 0;
            //当返回 -1 时,就表示文件读取完毕
            while ((readLen = bis.read(buff)) != -1) {
                bos.write(buff, 0, readLen);
            }
 
            System.out.println("文件拷贝完毕~~~");
 
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
 
            //关闭流 , 关闭外层的处理流即可,底层会去关闭节点流
            try {
                if(bis != null) {
                    bis.close();
                }
                if(bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
 
        }
 
 
    }
}

5 数据输入/输出流

5.1DataInputStream和DataOutputStream

        DataInputStream和DataOutputStream允许应用程序以与机器无关的方式从底层输入流中读取基本Java数据类型,不必再关心是哪个字节。

        分别通过DataOutputStream类的writeUTF(),writeDouble(),riteInt()和writeBoolean()方法向指定的word.txt文件中写入不同类型的数据,并通过DataInputStream类相应方法输出到控制台

5.2代码实现

public class DataDemo {
    public static void main(String[] args) {
        File file = new File("D:\\word.txt");
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);
            dataOutputStream.writeUTF("使用UTF方法写入数据");
            dataOutputStream.writeDouble(19.5);
            dataOutputStream.writeInt(10);
            dataOutputStream.writeBoolean(true);
            dataOutputStream.close();

            FileInputStream fileInputStream = new FileInputStream(file);
            DataInputStream dataInputStream = new DataInputStream(fileInputStream);
            System.out.println("readUTF()读取数据:"+dataInputStream.readUTF());
            System.out.println("readDouble()读取数据:"+dataInputStream.readDouble());
            System.out.println("readInt():"+dataInputStream.readInt());
            System.out.println("readBoolean()读取数据:"+dataInputStream.readBoolean());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

6 转换流

6.1InputStreamReader和OutputStreamWriter

(1)InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成(转换)Reader(字符流);

(2)OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流);

(3)当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换为字符流;

(4)可以在使用时指定编码格式(比如utf-8、gbk、gb2312、ISO8859-1等)

6.2代码实现

/**
 * 演示使用 InputStreamReader 转换流解决中文乱码问题
 * 将字节流 FileInputStream 转成字符流  InputStreamReader, 指定编码 gbk/utf-8
 */
public class InputStreamReader_ {
    public static void main(String[] args) throws IOException {
 
        String filePath = "D:\\test.txt";
        //解读
        //1. 把 FileInputStream 转成 InputStreamReader
        //2. 指定编码 gbk
        //InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");
        //3. 把 InputStreamReader 传入 BufferedReader
        //BufferedReader br = new BufferedReader(isr);
 
        //将2 和 3 合在一起
        BufferedReader br = new BufferedReader(new InputStreamReader(
                                                    new FileInputStream(filePath), "gbk"));
 
        //4. 读取
        String s = br.readLine();
        System.out.println("读取内容=" + s);
        //5. 关闭外层流
        br.close();
 
    }
 
 
}
/**
 * 演示 OutputStreamWriter 使用
 * 把FileOutputStream 字节流,转成字符流 OutputStreamWriter
 * 指定处理的编码 gbk/utf-8/utf8
 */
public class OutputStreamWriter_ {
    public static void main(String[] args) throws IOException {
        String filePath = "D:\\test.txt";
        String charSet = "utf-8";
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), charSet);
        osw.write("hi, 哈哈哈");
        osw.close();
        System.out.println("按照 " + charSet + " 保存文件成功~");
 
 
    }
}

 

 

 

 

 

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值