在Java编程中,文件操作和输入输出(IO)处理是必不可少的部分。本文将深入探讨Java IO包
中的文件流操作,包括基础概念、分类、常用类以及实际应用场景。
1. File类
File类是Java IO操作的基础,它实现了Serializable和Comparable<File>接口。
构造方法
// 通过路径名创建File对象
File file1 = new File("pathName");// 通过父路径和子路径创建
File file2 = new File("parent", "child");// 通过父File对象和子路径创建
File file3 = new File(parentFile, "child");// 通过URI创建
File file4 = new File(URI uri);
常用方法
1.exists()
:判断文件/目录是否存在
2.isFile()
/isDirectory()
:判断是否为文件/目录
3.createNewFile()
:创建新文件
4.mkdir()
/mkdirs()
:创建目录
5.list()
/listFiles()
:列出目录内容
6.delete()
:删除文件/目录
2. 流的分类
Java IO流可以按照不同维度进行分类:
按数据流向
输入流:用于读取数据(如读取配置文件)
输出流:用于写入数据(如写日志文件、导出到表格)
按数据类型
字节流:以byte为单位操作数据
字符流:以char为单位操作数据
分类组合
输入 | 输出 | |
---|---|---|
字节流 | InputStream | OutputStream |
字符流 | Reader | Writer |
3. 基础流类
Java IO提供了四个抽象基类:
InputStream
/OutputStream
:字节流基类Reader
/Writer
:字符流基类
4. 字节流操作
字节流以byte为单位操作数据,可以处理任意类型的文件数据。
基本使用方法
// 1. 声明流
FileInputStream fis = null;
FileOutputStream fos = null;try {// 2. 创建流fis = new FileInputStream("input.txt");fos = new FileOutputStream("output.txt");// 3. 使用流int data;while ((data = fis.read()) != -1) {fos.write(data);}
} catch (IOException e) {e.printStackTrace();
} finally {// 4. 关闭流try {if (fis != null) fis.close();if (fos != null) fos.close();} catch (IOException e) {e.printStackTrace();}
}
常用字节流类
FileInputStream
/FileOutputStream
:文件字节流,操作文件数据ByteArrayInputStream
/ByteArrayOutputStream
:字节数组流(内存流),操作内存数据
注意:内存流不需要手动关闭,由垃圾回收器负责清理。
5. 字符流操作
字符流提供了更方便高效的字符处理方式,底层仍是字节流,但自动处理字符编码转换。
try (FileReader reader = new FileReader("input.txt");FileWriter writer = new FileWriter("output.txt")) {int data;while ((data = reader.read()) != -1) {writer.write(data);}
} catch (IOException e) {e.printStackTrace();
}
注意:字符流只能操作文本文件,不能处理图片、音频、视频等二进制文件。
6. 异常处理
IO操作必须正确处理异常,推荐两种方式:
方式1:try-catch-finally
FileInputStream fis = null;
try {fis = new FileInputStream("file.txt");// 使用流
} catch (IOException e) {e.printStackTrace();
} finally {if (fis != null) {try {fis.close();} catch (IOException e) {e.printStackTrace();}}
}
方式2:try-with-resource(自动关闭资源)
try (FileInputStream fis = new FileInputStream("file.txt");FileOutputStream fos = new FileOutputStream("output.txt")) {// 使用流// 资源会自动关闭
} catch (IOException e) {e.printStackTrace();
}
7. 增强流
增强流提供更高级的功能和操作,通常包装在基础流之上。
缓冲流(高效流)
缓冲流通过在内存中创建缓冲区,减少实际IO操作次数,提高效率。
// 字节缓冲流
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("input.txt"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"))) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = bis.read(buffer)) != -1) {bos.write(buffer, 0, bytesRead);}
}// 字符缓冲流
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"));BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {String line;while ((line = reader.readLine()) != null) {writer.write(line);writer.newLine();}
}
标准流
Java预定义了三个标准流:
System.in
:标准输入流(字节流,通常是键盘输入)System.out
:标准输出流(字节流,通常是控制台输出)System.err
:标准错误流(字节流,输出错误信息)
// 使用Scanner读取标准输入
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();// 标准输出
System.out.println("普通信息");
System.err.println("错误信息");
转换流
转换流用于在字节流和字符流之间进行转换,并可指定编码。
try (InputStreamReader isr = new InputStreamReader(new FileInputStream("input.txt"), "UTF-8");OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("output.txt"), "UTF-8")) {int data;while ((data = isr.read()) != -1) {osw.write(data);}
}
对象流
对象流用于序列化和反序列化Java对象。
// 需要序列化的类必须实现Serializable接口
class Person implements Serializable {private static final long serialVersionUID = 1L;private String name;private transient int age; // transient修饰的字段不会被序列化// 构造方法、getter和setter
}// 序列化对象
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.dat"))) {oos.writeObject(new Person("张三", 25));
}// 反序列化对象
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.dat"))) {Person person = (Person) ois.readObject();System.out.println(person.getName());
}
注意:serialVersionUID
用于确保序列化兼容性,建议显式定义。
数据流
数据流专门用于读写基本数据类型和字符串。
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.dat"))) {dos.writeInt(100);dos.writeDouble(3.14);dos.writeUTF("Hello");
}try (DataInputStream dis = new DataInputStream(new FileInputStream("data.dat"))) {int i = dis.readInt();double d = dis.readDouble();String s = dis.readUTF();
}
8. 随机访问流
RandomAccessFile
类允许对文件进行随机访问,集输入输出于一体。
try (RandomAccessFile raf = new RandomAccessFile("file.txt", "rw")) {// 定位到文件末尾raf.seek(raf.length());// 写入数据raf.writeUTF("追加的内容");// 定位到文件开头raf.seek(0);// 读取数据String content = raf.readLine();
}
9. 实际应用场景
写日志:使用字符输出流(如FileWriter)记录程序运行日志
读写配置文件:使用Properties类结合文件流读写配置文件
文件上传下载:使用字节流处理文件传输
数据持久化:使用对象流将对象序列化到文件中
大数据处理:使用缓冲流提高大文件读写效率
总结
Java IO提供了丰富的API来处理文件和数据流操作。在实际开发中,应根据具体需求选择合适的流类型:
处理文本文件:优先考虑字符流
处理二进制文件:使用字节流
需要高效读写:使用缓冲流
需要对象持久化:使用对象流
需要随机访问:使用RandomAccessFile
正确使用和关闭流资源是避免内存泄漏和资源耗尽的关键,推荐使用try-with-resources语句确保资源正确释放。
掌握Java IO操作对于开发高效、稳定的应用程序至关重要,希望本文能为您提供全面的指导和参考。