IO流---Java自学

文件就是保存数据的地方
文件流:文件在程序中是以流的形式来操作的
java程序(内存)------>文件磁盘(输入流)
java程序(内存)<------文件磁盘(输出流)
流:数据在数据源(文件)和程序(内存)之间经历的路径

//演示创建文件
public class FileCreat {
    public static void main(String[] args) {
        
    }
    //方式1 new File(String pathname) 根据路径构建一个File对象

    public void creadte1(){
        String filePath = "d:\\file\\file1.txt";
        File file = new File(filePath);
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //方式2 new File(File parent,String child) 根据父目录文件+子路径构建
    //d:\\file\\file2.txt
    @Test
    public void create2(){
        File file = new File("d:\\");
        String fileName = "file2.txt";
        //这里的file对象,在java程序中,只是一个对象
        File file1 = new File(file, fileName);
        try {
            //把对象写入磁盘
            file.createNewFile();
            System.out.println("创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //方式3 new File(File parent,String child) 根据父目录+子路径构建

    public void create3(){
        String parentPath = "d:\\";
        //String parentPath = "d:/";
        String filePath = "file3.txt";
        File file = new File(parentPath, filePath);
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

常用的文件操作

获取文件的相关信息

public class FileInformation {
    public static void main(String[] args) {

    }

    //获取文件信息
    @Test
    public void info(){
        //创建文件对象
        File file = new File("d:/file3.txt");

        //调用相应的方法,得到对应信息
        System.out.println("文件名字=" + file.getName());
        System.out.println("绝对路径=" + file.getAbsolutePath());
        System.out.println("文件父级目录=" + file.getParent());
        System.out.println("文件大小(子节)=" + file.length());
        System.out.println("文件是否存在=" + file.exists());
        System.out.println("是不是一个文件=" + file.isFile());
        System.out.println("是不是一个目录=" + file.isDirectory());
    }
}

目录的操作和文件删除
mkdir创建一级目录
mkdirs创建多级目录
delete删除空目录或文件

public class Directory_ {
    public static void main(String[] args) {

    }
    //判断d:file3.txt是否存在,如果存在就删除

    public void m1(){
        String filePath = "d:/file3.txt";
        File file = new File(filePath);
        if(file.exists()){
            if(file.delete()){
                System.out.println("删除成功");
            }else {
                System.out.println("删除失败");
            }
        }else {
            System.out.println("文件不存在");
        }
    }
    //判断d:\demo2是否存在,存在就删除
    //在java中 目录也被当作文件

    public void m2(){
        String filePath = "d:/demo02";
        File file = new File(filePath);
        if(file.exists()){
            if(file.delete()){
                System.out.println("删除成功");
            }else {
                System.out.println("删除失败");
            }
        }else {
            System.out.println("目录不存在");
        }
    }

    //判断d:/demo/a/b/c目录是否存在,如果存在就提示已存在,否则就创建
    @Test
    public void m3(){
        String filePath = "d:/demo/a/b/c";
        File file = new File(filePath);
        if(file.exists()){
            System.out.println(filePath + "目录存在");
        }else {
            if(file.mkdirs()) {
                System.out.println("目录创建成功");
            }else {
                System.out.println("目录创建失败");
            }
        }
    }
}

流的分类
按操作数据单位不同分为:字节流(二进制文件),字符流(文本文件)
按数据流的流向分为:输入流,输出流
按流的角色不同分为:节点流,处理流/包装流

抽象基类字节流字符流
输入流InputStreamReader
输入流OutputStreamWriter

它们都是抽象类,要使用要用实际子类
由这四个类派生出的子类名称都是以其父类名作为子类名的后缀

字节流
FileInputStream
import org.junit.Test;

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

//演示FileInPutStream的使用(子节输入流 文件-->程序)
public class FileInPutStream_ {
    public static void main(String[] args) {

    }
    //读取文件 单个子节的读取 效率较低
    //@Test
    public void readFile01(){
        String filePath = "d:/hello.txt";
        int readData = 0;
        FileInputStream fileInputStream = null;
        try {
            //创建FileInputStream对象,用于读取文件
            fileInputStream = new FileInputStream(filePath);
            //读取一个字节数据,如果没有输入可用,此方法将阻止
            //如果返回-1,表示读取完毕
            while( (readData = fileInputStream.read())!=-1) {
                System.out.println((char)readData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭文件,释放资源
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //读取文件 字节数组
    @Test
    public void readFile02(){
        String filePath = "d:/hello.txt";
        //字节数组
        byte[] buf = new byte[8];//一次读取8个字节
        int readLength = 0;
        FileInputStream fileInputStream = null;
        try {
            //创建FileInputStream对象,用于读取文件
            fileInputStream = new FileInputStream(filePath);
            //读取b.length字节数据,此方法将阻塞,指导某些输入可用;
            //如果返回-1,表示读取完毕
            //如果读取正常,返回实际读取的字节数
            while( (readLength = (fileInputStream.read(buf))) !=-1) {
                //显示
                System.out.println(new String(buf,0,readLength));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭文件,释放资源
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
FileOutputStream
import org.junit.Test;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class FileOutputStream01 {
    public static void main(String[] args) {

    }

    //使用FileOutputStream将数据写到文件中
    //若文件不存在则创建该文件(前提是目录必须存在)
    @Test
    public void writeFile(){

        //创建FileOutputStream对象
        String filePath = "d:/a.txt";
        FileOutputStream fileOutputStream = null;
        try {
            //得到一个对象

            //说明:new FileOutputStream(filePath)创建方式,是覆盖
            //new FileOutputStream(filePath,true) 写入内容是追加

            fileOutputStream = new FileOutputStream(filePath);
            //写入一个字节
            //fileOutputStream.write('H');
            //写入字符串
            String str = "hello,world";
            //str.getBytes() 可以把字符串转换成字节数组
           // fileOutputStream.write(str.getBytes());
            //write(byte[] b,int off,int len)将 len 字节从位于偏移量 off的指定字节数组写入此文件输出流
            //off 起始位置 len字节数组长度
            fileOutputStream.write(str.getBytes(),1,3);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
拷贝文件
完成文件拷贝
思路分析
1.创建文件输入流  将文件读入到程序
2.创建文件的输出流 将读取到的文件数据输出到指定文件
3.在完成程序时,读取部分数据就写入到文件里面,使用循环操作
文件字符流

FileReader相关方法
1.new FileReader(File/String)
2.read:每次读取单个字符,返回该字符,如果到文件末尾返回-1
3.read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1
相关API
1.new String(char[])将char[]转换成String
2.new String(char[],off,ien):将char[]的指定部分转换成String

FileWriter相关方法
1.new FileWriter(File/String):覆盖模式
2.new FileWriter(File/String,true):追加模式
3.write(int):写入单个字符
4.write(char[]):写入指定数组
5.write(char[],off,len):写入指定数组的指定部分
6.write(string):写入整个字符串
7.write(string,off,len):写入字符串的指定部分
相关API
String类:toCharArray:将String转换成char[]
注意
FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件

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

public class FileReader_ {
    public static void main(String[] args) {
          String filePath = "d:/story.txt";
        //1.创建FileReader对象
          FileReader fileReader = null;
        int data = 0;

        int readLength = 0;
        char[] buf = new char[8];
        try {
            fileReader = new FileReader(filePath);
            //单个字符读取
//            while((data = fileReader.read()) != -1){
//                System.out.print((char)data);
//            }
            //多个字符读取,返回的是实际读取到的字符数
            //如果返回-1,说明到文件结束
            while((readLength = fileReader.read(buf)) != -1){
                System.out.print(new String(buf,0,readLength));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fileReader != null){
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
FileWriter
import java.io.FileWriter;
import java.io.IOException;

public class FileWriter_ {
    public static void main(String[] args) {
        String filePath = "d:/not.txt";
        //1.创建一个FileWriter对象
        FileWriter fileWriter = null;
        char[] chars = {'a','b','c'};
        try {
            fileWriter = new FileWriter(filePath);
            //1.写入单个字符
            fileWriter.write('H');
            //2.写入指定数组write(char[])
            fileWriter.write(chars);
            //3.write(char[],off,len)
            fileWriter.write("你好,北京".toCharArray(),0,2);
            //4.wirte(string):写入整个字符串
            fileWriter.write("你好北京~");
            //5.write(string,off,len)
            fileWriter.write("上海深圳",0,2);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //对于FileWriter,一定要关闭流,或者flush才能真正的把数据写入到文件
            try {
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("程序结束");
    }
}

节点流和处理流

1.节点流可以从一个特定的数据源读写数据,如FileReader,FileWriter
2.处理流(也叫包装流)是“连接”在已经存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,也更加灵活,如CufferedReader,BufferedWriter(让节点流更加强大)

节点流和处理流的区别和联系

1.节点流是底层流/低级流,直接跟数据源相接
2.处理流(包装流)包装节点流,既可以消除不同节点流的现实差异,也可以提供更方便的方法来完成输入输出
3.处理流,使用了修饰器设计模式,不会直接与数据源相连接

处理流的功能主要体现在以下两个方面

1.性能的提高:主要以增加缓冲的方式来提高输入输出的效率
2.操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便

BufferedReader

1.属于字符流,是按照字符来读取数据的
2.关闭处理流,只需要关闭外层流即可
3.读取文本文件

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

public class BufferdReader_ {
    public static void main(String[] args) throws Exception{
        String filePath = "d:/story.txt";
        //创建bufferReader
        BufferedReader bufferedReader = new BufferedReader(new FileReader((filePath)));
        //读取
        String line;//按行读取
        //说明
        //1.bufferedReader.readLine()是按行读取文件
        //2.当返回null时,表示文件读取完毕
        while((line = bufferedReader.readLine()) != null){
            System.out.println(line);
        }
        //关闭流,只需要关闭BuffererdReader,因为底层会自动去关闭 节点流
        bufferedReader.close();
    }
}
BufferedWriter
import java.io.BufferedWriter;
import java.io.FileWriter;

public class BufferedWriter_ {
    public static void main(String[] args) throws Exception{
        String filePath = "d:/a.txt";
        //创建一个BufferedWriter
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
        //BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));  追加的方式
        bufferedWriter.write("hi!");
        //插入一个和系统相关的换行符
        bufferedWriter.newLine();
        bufferedWriter.write("hi!");
        //关闭外层流即可
        bufferedWriter.close();

    }
}
BufferedInputStream,BufferedOutputStream

对象流-ObjectInputStream and ObjectOutputStream

序列化和反序列化
1.序列化就是在保存数据时,保存数据的值数据类型(例如保存int 100)
2.反序列化就是在恢复数据时,恢复数据的值数据类型
3.需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
Serializable//这是一个标记接口
Externalizable//该接口有方法需要实现

ObjectOutputStream

提供了序列化功能

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

public class Obj_ {
    public static void main(String[] args) throws Exception{
        //序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
        String filePath = "d:/data.dat";

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));

        //序列化数据到 d:\\data.dat
        oos.write(100);//int -> Interger(实现了 Serializable)
        oos.writeBoolean(true);//boolean -> Boolean
        oos.writeChar('a');//char -> Character
        oos.writeDouble(8.8);//double -> Double
        oos.writeUTF("你好北京");//String
        //保存一个dog对象
        oos.writeObject(new Dog("旺财",10));
        oos.close();
        System.out.println("数据保存完毕(序列化形式)");
    }
}

//如果需要序列化某个对象的类,实现Serializable
class Dog implements Serializable {
    private String name;
    private int age;

    public Dog(String name, int age) {
        this.name = name;
        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));

        //读取
        //读取(反序列化)的顺序需要和保存数据(序列化)的顺序一致,这个包里也需要有这个类

        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());
        Object dog = ois.readObject();
        //dog的编译类型是Object
        System.out.println("运行类型=" + dog.getClass());
        System.out.println(dog); // 底层Obj -> Dog
        //细节
        //1.如果我们希望调用Dog的方法,需要向下转型
        //2.还需要将Dog类,拷贝到可以引用的地方
        Dog doge2 = (Dog)dog;
        System.out.println(doge2.getName());
        //关闭外层流即可
        ois.close();
    }
}
注意事项

1.读写顺序一致
2.要求实现序列化或反序列化,需要 实现Serializable
3.序列化的类中建议添加SerialVersionUID,为了提高版本兼容性
4.序列化对象时,默认将里面所有的属性都进行序列化,但除了static或transient修饰的成员
5.序列化对象时,要求里面属性的类型也需要实现序列化接口
6.序列化具备可继承性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值