java的文件操作【流】

本文主要讲述java的文件操作

一. 创建文件

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

    }

    // 创建文件方式一:
    // String filePath = "F:\\韩顺平java基础笔记\\java图片\\new01.txt";
    @Test
    public void create01(){
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\new01.txt";
        File file = new File(filePath);
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    // 创建文件方式二:
    // File parentFile = new File("F:\\韩顺平java基础笔记\\java图片\\");
    // String fileName = "new02.txt";
    // File file = new File(parentFile, fileName);
    @Test
    public void create02(){
        File parentFile = new File("F:\\韩顺平java基础笔记\\java图片\\");
        String fileName = "new02.txt";
        // 这里的file对象,在java程序中,只是一个对象
        File file = new File(parentFile, fileName);
        try {
            // 真正创建文件的方法file.createNewFile();
            file.createNewFile();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }

    }

    // 创建方式三:
    // String parentFile = "F:\\韩顺平java基础笔记\\java图片\\";
    // String fileName = "new03.txt";
    // File file = new File(parentFile, fileName);
    @Test
    public void create03(){
        String parentFile = "F:\\韩顺平java基础笔记\\java图片\\";
        String fileName = "new03.txt";
        File file = new File(parentFile, fileName);
        try {
            file.createNewFile();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
}

方式2和方式3的区别是:路径信息一个是由文件对象表示,另一个是字符串表示。

注意:file.createFile(),才是真正创建了文件对象。

二. 输入流和输出流

1)字节输入输出流

FileInputStream图示:

vip

FileOutputStream图示:

vip

使用FileInputStream读取文件【文件如果有中文,则使用字节输入流可能会乱码】

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

    }

    // 使用read(),单个字节读取文件
    @Test
    public void readFile01(){
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\hello.txt";
        FileInputStream fileInputStream = null;
        int readData = 0;
        try {
            fileInputStream = new FileInputStream(filePath);
            while((readData = fileInputStream.read()) != -1){
                System.out.print((char) readData);
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                fileInputStream.close();
            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }
    }

    // 使用read(byte[] arr),用字节数组读取文件
    @Test
    public void readFile02(){
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\hello.txt";
        FileInputStream fileInputStream = null;
        int readLen = 0;
        byte[] bytes = new byte[5];
        try {
            fileInputStream = new FileInputStream(filePath);
            while((readLen = fileInputStream.read(bytes)) != -1){
                // 注意这里创建字符串的new String(bytes,0,readLen),按照每次读取的长度,创建字符串
                // 以免重复数据进入
                System.out.print(new String(bytes,0,readLen));
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                fileInputStream.close();
            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }
    }
}

使用FileOutputStream写入文件

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

    }

    @Test
    public void writeFile(){
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\a.txt";
        FileOutputStream fileOutputStream = null;
        try {
            // 创建方式1:fileOutputStream = new FileOutputStream(filePath);【内容会覆盖】
            // 创建方式2:fileOutputStream = new FileOutputStream(filePath,true);【追加内容】
//            fileOutputStream = new FileOutputStream(filePath);
            fileOutputStream = new FileOutputStream(filePath,true);
            // 写入一个字节
//            fileOutputStream.write('H');
            // 写入字符串
//            String str = "hello java";
//            fileOutputStream.write(str.getBytes());
            // 指定写入的字符串
            String str = "hello world";
            fileOutputStream.write(str.getBytes(),0,5);

        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }

    }
}

使用FileInputStream和FileOutputStream进行文件拷贝

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

    @Test
    // 将F:\韩顺平java基础笔记\java图片路径下的图片,拷贝到F:\韩顺平java基础笔记
    public void filesCopy (){
        // 首先创建输入流InputStream读取路径的文件
        String parentPath = "F:\\韩顺平java基础笔记\\java图片\\desk.jpg";
        String targetPath = "F:\\韩顺平java基础笔记\\desk.jpg";
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;
        byte[] bytes = new byte[10];
        int readLen = 0;
        try {
            inputStream = new FileInputStream(parentPath);
            outputStream = new FileOutputStream(targetPath);
            while ((readLen = inputStream.read(bytes)) != -1){
                outputStream.write(bytes,0,readLen);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

注意:字节流的默认字符集是UTF-8

2)字符输入输出流

FileReader输入流图示:

vip

FileWriter输出流图示:

vip

使用FileReader读取文件【不会乱码】

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

    }

    @Test
    public void ReadFile01(){
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\hello.txt";
        FileReader fileReader = null;
        int readData = 0;
        try {
            fileReader = new FileReader(filePath);
            // readData = fileReader.read() 单字节的读取文件
            while ((readData = fileReader.read()) != -1){
                System.out.print((char) readData);
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            if(fileReader != null){
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }

    @Test
    public void ReadFile02(){
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\hello.txt";
        FileReader fileReader = null;
        int readLen = 0;
        char[] chars = new char[10];
        try {
            fileReader = new FileReader(filePath);
            // readLen = fileReader.read(chars) 按照chars字符数组的长度,读取文件
            while ((readLen = fileReader.read(chars)) != -1){
                // 实际内容,与readLen有关,因此new String(chars,0,readLen)
                System.out.print(new String(chars,0,readLen));
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            if(fileReader != null){
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }
}

使用FileWriter写文件

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

    }

    @Test
    public void WriteFile(){
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\hello.txt";
        FileWriter fileWriter = null;
        char[] chars = {'h','e','l','l','o'};
        try {

//            fileWriter = new FileWriter(filePath); // 默认是覆盖方式
            fileWriter = new FileWriter(filePath,true); // 追加方式
            // 写入单个字符
//            fileWriter.write('H');
            // 写入字符数组
//            fileWriter.write(chars);
            // 写入字符数组的指定部分
//            fileWriter.write(chars,0,3);
            // 写入字符串
//            fileWriter.write("韩顺平教育java");
            // 写入字符串的指定部分
            fileWriter.write("你好生活,银魂",0,4);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fileWriter != null){
                try {
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

注意:字符流的默认字符集是UTF-8

三. 处理流

节点流Vs处理流

 vip

处理流是节点流的包装,处理流的功能比节点流更加丰富,但是实质上处理流的功能是在节点流基础上扩展的。

例如 BufferedReader源码:【其他处理流,创建原理等同】

 

由于多态性质,Reader可以存放字符输入流Reader的任意子类,提高了流的功能性。

1)字符处理流

BufferedReader图示:

vip

BufferedWriter图示:

vip

使用BufferedReader读取文件:

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

    }

    @Test
    public void BufferReadFile(){
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\a.txt";
        BufferedReader bufferedReader = null;
        String nextLine = null;
        try {
            // BufferedReader的成员变量中有Reader in
            // 带有Reader类的对象参数的BufferedReader构造器【类的多态】
            bufferedReader = new BufferedReader(new FileReader(filePath));
            // (nextLine = bufferedReader.readLine()) != null 每次读取文件的一行
            while ((nextLine = bufferedReader.readLine()) != null) {
                System.out.println(nextLine);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 只需关闭处理流即可
            if(bufferedReader != null){
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

使用BufferedWriter写入文件:

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

    }

    @Test
    public void BufferWriteFile() throws IOException {
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\b.txt";
        // 覆盖写入
//        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
        // 追加写入
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
        // 写入一个字符串
        bufferedWriter.write("hello1 韩顺平教育");
        // 插入一个与系统相关的换行符
        bufferedWriter.newLine();
        bufferedWriter.write("hello2 韩顺平教育");
        bufferedWriter.newLine();
        bufferedWriter.write("hello3 韩顺平教育");
        bufferedWriter.newLine();

        bufferedWriter.close();
    }
}

使用BufferedReader和BufferedWriter进行文件拷贝:

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

    }

    /**
     * 由于BufferedReader和BufferedWriter是操作字符流文件
     * 因此不能操作字节流文件【二进制文件】 例如,声音,视频,doc,pdf
     * @throws IOException
     */
    @Test
    public void BufferCopyFile() throws IOException {
        String srcFilePath = "F:\\韩顺平java基础笔记\\java图片\\a.txt";
        String destFilePath = "F:\\韩顺平java基础笔记\\java图片\\a1.txt";
        BufferedReader bufferedReader = new BufferedReader(new FileReader(srcFilePath));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(destFilePath));
        String nextLine = null;
        while((nextLine = bufferedReader.readLine()) != null){
            bufferedWriter.write(nextLine);
            bufferedWriter.newLine();
        }

        if(bufferedReader != null){
            bufferedReader.close();
        }
        if(bufferedWriter != null){
            bufferedWriter.close();
        }
    }
}

注意:关于文件拷贝

如果文件是字符流文件,则使用BufferedReader【FileReader】和BufferedWriter【FileWriter】进行文件拷贝

如果文件是字节流文件,则使用BufferedInputStream【FileInputStream】和BufferedOutputStream【FileOutputStream】进行文件拷贝

2)字节处理流

BufferedInputStream图示:

vip

BufferedOutputStream图示:

vip

 使用BufferedInputStream和BufferedOutputStream拷贝二进制文件

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

    }

    @Test
    public void BufferedCopyFile() throws IOException {
        String srcFilePath = "F:\\韩顺平java基础笔记\\java图片\\desk.jpg";
        String destFilePath = "F:\\韩顺平java基础笔记\\java图片\\desk1.jpg";
        BufferedInputStream bufferedInput = new BufferedInputStream(new FileInputStream(srcFilePath));
        BufferedOutputStream bufferedOutput = new BufferedOutputStream(new FileOutputStream(destFilePath));
        byte[] bytes = new byte[1024];
        int readLen = 0;
        while ((readLen = bufferedInput.read(bytes)) != -1){
            bufferedOutput.write(bytes,0,readLen);
        }

        if(bufferedInput != null) {
            bufferedInput.close();
        }
        if(bufferedOutput != null) {
            bufferedOutput.close();
        }
    }
}

阶段总结:

字节流:FileInputStream和FileOutputStream,既可以处理字节流文件【图片,视频,doc,pdf】,也可以处理字符流文件【txt】

字符流:FileReader和FileWriter只能处理字符流文件【txt】

处理流的核心操作仍然是字节流和字符流,扩展了功能

字节处理流:BufferedInputStream和BufferedOutputStream可以处理所有文件

字符处理流:BufferedReader和BufferedWriter只能处理字符流文件【txt】

3)对象处理流

vip

ObjectInputStream【反序列化】图示:

vip

ObjectOutputStream【序列化】图示:

vip

使用ObjectOutputStream序列化

public class ObjectOutputStreamTest {
    public static void main(String[] args) throws Exception{
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\objectData.bat";
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
        oos.write(100);
        oos.writeBoolean(true);
        oos.writeChar('A');
        oos.writeDouble(9.5);
        oos.writeUTF("韩顺平");

        oos.writeObject(new Dog("大白",12));
        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反序列化

重点重点:在序列化过程中,当Dog类不是public时,即不是主类时

 由于此时Dog不是public,因此不能import导入,如果将Dog类的代码复制到ObjectInputStreamTest中去,运行结果出错。

public class ObjectInputStreamTest {
    public static void main(String[] args) throws Exception {
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\objectData.bat";

        ObjectInputStream inputStream= new ObjectInputStream(new FileInputStream(filePath));
        System.out.println(inputStream.readInt());
        System.out.println(inputStream.readBoolean());
        System.out.println(inputStream.readChar());
        System.out.println(inputStream.readDouble());
        System.out.println(inputStream.readUTF());
        Object dog = inputStream.readObject();
        System.out.println(dog.getClass());
        System.out.println(dog);

        // 要想调用Dog的特定方法,调用run()方法
        // 必须将Dog类改成public 主类,否则报错
        Dog pet = (Dog) dog;
        pet.run();
        inputStream.close();
    }
}
// 如果需要序列化类的对象,则该类需要实现接口Serializable
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 void run(){
        System.out.println(name + "在跑步...");
    }
}

运行结果如下:

100
true
A
9.5
韩顺平
class exercise.file_.buffer.objectbuffer.Dog
Dog{name='大白', age=12}
Exception in thread "main" java.lang.ClassCastException: exercise.file_.buffer.objectbuffer.Dog cannot be cast to exercise.file_.buffer.objectBuffered.Dog
    at exercise.file_.buffer.objectBuffered.ObjectInputStreamTest.main(ObjectInputStreamTest.java:23)

Process finished with exit code 1

原因:在ObjectOutputStream反序列化后,文件已经保存了Dog的包名+类名,下图文件保存的Dog类的内容

而在ObjectInputStreamTest中复制的Dog类,包名是exercise.file_.buffer.objectBuffered.Dog。

 在ObjectInputStreamTest程序中:

// 向下转型
Dog pet = (Dog) dog;
pet.run();

dog对象的运行类型是exercise.file_.buffer.objectbuffer.Dog

但是这里的Dog类确是exercise.file_.buffer.objectBuffered.Dog,因此无法向下转型

正确写法:将Dog提升至主类,ObjectOutputStream和ObjectInputStream引用(import)同一个类。

 

import exercise.file_.buffer.objectbuffer.Dog;
public class ObjectInputStreamTest {
    public static void main(String[] args) throws Exception {
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\objectData.bat";

        ObjectInputStream inputStream= new ObjectInputStream(new FileInputStream(filePath));
        System.out.println(inputStream.readInt());
        System.out.println(inputStream.readBoolean());
        System.out.println(inputStream.readChar());
        System.out.println(inputStream.readDouble());
        System.out.println(inputStream.readUTF());
        Object dog = inputStream.readObject();
        System.out.println(dog.getClass());
        System.out.println(dog);

        // 要想调用Dog的特定方法,调用run()方法
        // 必须将Dog类改成public 主类,否则报错
        Dog pet = (Dog) dog;
        pet.run();
        inputStream.close();
    }
}

 对象处理流的使用细节:

vip

 四. 转换流

InputStreamReader图示:

vip

将指定字符集的InputStream子类【字节流】转换成Reader子类【字符流】。

OutputStreamWriter图示:

vip

 

 将指定字符集的OutputStream子类【字节流】转换成Writer子类【字符流】。

 使用InputStreamReader读取指定字符集的文件

public class TransferInOutput {
    public static void main(String[] args) throws IOException {
        // 使用字节流读取txt文件
        // 字节流的字符集,默认是utf-8
        // 字符流的字符集,默认是utf-8
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\b.txt";
        FileInputStream fileReader = new FileInputStream(filePath);
        BufferedInputStream bufferedReader = new BufferedInputStream(fileReader);
        int readLen = 0;
        byte[] bytes = new byte[1024];
        while((readLen = bufferedReader.read(bytes)) != -1){
            System.out.print(new String(bytes,0,readLen));
        }
        bufferedReader.close();
    }

    @Test
    public void transfer() throws IOException{
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\b.txt";
        // 1.创建字节流
        FileInputStream inputStream = new FileInputStream(filePath);
        // 2.创建转换流,将指定字符集的字节流转换成字符流
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"gbk");
        // 3.通过字符流【节点流】创建字符处理流【处理流】
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String str = null;
        while((str = bufferedReader.readLine()) != null){
            System.out.println(str);
        }

        bufferedReader.close();
    }
}

使用OutputStreamWriter将写入的内容,按照指定的字符集,保存到文件中

public class TransferOutInput {
    public static void main(String[] args) throws IOException {
        String filePath = "F:\\韩顺平java基础笔记\\java图片\\b1.txt";
        String charset = "gbk";
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), charset);
        osw.write("韩顺平教育");

        osw.close();
        System.out.println("字符集: " +charset + "文件创建成功");
    }
}
posted @ 2023-01-07 09:37  zwGitOne  阅读(326)  评论(0编辑  收藏  举报