Java IO流

一、File 类

Java 中通过 java.util.File 类来对一个文件(包括目录)进行抽象的描述;

File 类构造方法

常用其他方法

代码示例

1. 创建一个 .txt文件

File file = new File("d:/testFile.txt");
boolean newFile = file.createNewFile();
System.out.println(newFile);

2.  获取文件名和文件路径

String name = file.getName();
String path = file.getPath();
System.out.println(name + "\n" + path);

3. 判断该文件是否存在并且是否是一个目录

boolean exists = file.exists();
boolean directory = file.isDirectory();
System.out.println(exists + "\n" + directory);

4. 执行代码 

 二、对文件内容的操作

Java 中通过流对象来实现对文件内容的操作,流对象可分为字节流和字符流

字节流:每次读/写的最小单位是字节(1字节 = 8 bit)

字符流:每次读/写的最小单位是字符(1个字符对应多个字节,跟编码方式有关,其中 GBK:1 中文字符 -> 2 字节,UTF8:1 中文字符 -> 3字节,Unicode:1 中文字符 -> 2 字节)

对文件的操作可分为读(输入)和写(输出),因此就构成了 Java IO 流的四个抽象基类,分别为:

输入输出
字节流InputStreamOutputStream
字符流ReaderWriter

上述四个类都是抽象类,具体实现是由具体的子类完成的

1. 字节流

1. FileInputStream

构造方法:

常用其他方法:

代码示例:

public class TestInputStream {
    public static void main(String[] args) {
        try (FileInputStream file = new FileInputStream("d:/test.txt")){
            int tmp;
            byte[] bytes = new byte[10];
            while((tmp = file.read(bytes)) != -1){
                System.out.print(new String(bytes, 0, tmp));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

注意:在使用字节流读取文本文件的时候,可能会出现乱码问题;

2. FileOutputStream

构造方法:

在构造方法中,若 append 为 true,则会在文件后面继续写(追加写),否则写操作会替换掉原来的内容(覆盖写);

常用其他方法:

代码示例:

public class TestOutputStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream("d:/test.txt", true);
        String str = "2024/7/10,你好,我在学IO";
        fileOutputStream.write(str.getBytes());
        fileOutputStream.close();
    }
}

3. 使用 FileOutputStream 和 FileInputStream 完成图片文件复制

public class TestFileCopy {
    public static void main(String[] args) throws IOException {
        FileInputStream fileInputStream = new FileInputStream("d:/dog.jpg");
        FileOutputStream fileOutputStream = new FileOutputStream("d:/dog2.jpg");
        byte[] bytes = new byte[1024];
        int tmp;
        while((tmp = fileInputStream.read(bytes)) != -1){
            fileOutputStream.write(bytes, 0, tmp);
        }
        System.out.println("复制完成");
        fileOutputStream.close();
        fileInputStream.close();
    }
}

2. 字符流

1. FileReader

构造方法:

常用其他方法: 

示例代码: 

public class TestReader {
    public static void main(String[] args) {
        try(FileReader reader = new FileReader("d:/test.txt")){
            char[] chars = new char[8];
            int tmp;
            while((tmp = reader.read(chars)) != -1){
                System.out.print(new String(chars, 0, tmp));
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

2. FileWriter

构造方法:

常用其他方法:

 示例代码:

public class TestWriter {
    public static void main(String[] args) {
        try(FileWriter fileWriter = new FileWriter("d:/test.txt")) {
            fileWriter.write("fileWriter 的 write 方法");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

3. 使用 FileReader 和 FileWriter 完成文件复制

public class TestFileCopy2 {
    public static void main(String[] args) {
        try (FileReader reader = new FileReader("d:/test.txt");
             FileWriter writer = new FileWriter("d:/test2.txt")){
            char[] chars = new char[16];
            int tmp;
            while((tmp = reader.read(chars)) != -1){
                writer.write(new String(chars, 0, tmp));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

3. 带缓冲的字节处理流

1. BufferedInputStream

构造方法:

其他常用方法: 

2. BufferedOutputStream

构造方法:

其他常用方法: 

在向文件中写入数据后,需要调用 flush 方法或者 close 方法刷新缓冲区, 才会生效;

4. 带缓冲的字符处理流 

1. BufferedReader

构造方法:

其他常用方法:

代码示例:

public class TestBufferedReader {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader("d:/test.txt"));
        String string = reader.readLine();
        System.out.println(string);
        reader.close();
    }
}

释放流资源时,只需释放最外层即可;

2. BufferedWriter

构造方法:

其他常用方法:

代码示例: 

public class TestBufferedWriter {
    public static void main(String[] args) throws IOException {
        BufferedWriter writer = new BufferedWriter(new FileWriter("d:/test.txt", true));
        writer.write("今天星期四");
        writer.write("今天天气不错", 2, 4);
        writer.close();
    }
}

在使用完之后,要使用 flush 或 close 刷新缓冲区,这样数据才会写入设备中,同样在关闭时,只需关闭外层流即可;   

5. 用于转换的字符流

1. InputStreamReader

可将字节输入流转换成字符输入流     

构造方法:

其他常用方法:

2. OutputStreamWriter 

可将字节输出流转换为字符输出流

构造方法:

其他常用方法: 

6. 打印输出流

1. PrintStream 

构造方法:

标准输出流 System 类中的对象 out 的编译类型就是 PrintStream;

2. PrintWriter

构造方法:

三、笔试题(实现 ObjectCloner 类)

在实际的 java 开发中,常常需要克隆一个对象,请编写一个工具类 ObjectCloner 实现 clone 方法来克隆指定对象,需满足以下要求:

1. obj1 != obj2  

2. obj1 和 obj2 是同一类型,具备相同的字段和方法

3. obj2 的字段值应于 obj1 保持一致,包括对基本数据类型和数组的字段进行深度克隆

4. ObjectClone 应该是一个通用的工具类,能够对任意类型的对象克隆

方法一:使用对象流的方式

package util;

import java.io.*;

public class ObjectCloner {

    /**
     * 克隆指定对象的方法
     * 
     * @param <T>   对象类型
     * @param obj   需要克隆的对象
     * @return      克隆后的对象
     * @throws IOException              如果在序列化过程中发生IO错误
     * @throws ClassNotFoundException   如果类未找到
     */
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T clone(T obj) throws IOException, ClassNotFoundException {
        if (obj == null) {
            throw new IllegalArgumentException("对象不能为空");
        }

        // 创建字节输出流
        ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
        // 创建对象输出流
        ObjectOutputStream outStream = new ObjectOutputStream(byteOutStream);
        // 将对象写入输出流
        outStream.writeObject(obj);
        outStream.flush();

        // 创建字节输入流,基于写入的数据
        ByteArrayInputStream byteInStream = new ByteArrayInputStream(byteOutStream.toByteArray());
        // 创建对象输入流
        ObjectInputStream inStream = new ObjectInputStream(byteInStream);

        // 读取克隆的对象并返回
        return (T) inStream.readObject();
    }
}

方法二:使用反序列化

package util;

import java.lang.reflect.Array;
import java.lang.reflect.Field;

public class ObjectCloner2 {
    // 克隆方法
    public static <T> T clone(T obj) throws Exception {
        // 获取对象的类类型
        Class<?> clazz = obj.getClass();
        // 创建新的实例
        T clone = (T) clazz.getDeclaredConstructor().newInstance();

        // 获取对象的所有字段
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);  // 设置字段可访问

            // 判断字段类型
            if(field.getType().isPrimitive() || field.getType().equals(String.class)){
                // 对于基本数据类型和String类型,直接进行赋值
                field.set(clone, field.get(obj));
            } else if (field.getType().isArray()){
                // 对于数组类型,通过Array的copy方法进行深度克隆
                Object arrayObj = field.get(obj);
                int length = Array.getLength(arrayObj);
                Object newArrayObj = Array.newInstance(field.getType().getComponentType(), length);
                System.arraycopy(arrayObj, 0, newArrayObj, 0, length);
                field.set(clone, newArrayObj);
            } else {
                // 对于其他引用类型,递归调用克隆方法进行深度克隆(要求其他引用类型也能实现克隆方法)
                field.set(clone, clone(field.get(obj)));
            }
        }

        return clone;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rcnhtin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值