java的io用于处理输入和输出操作,java.io包提供了大量的类来执行读写操作
核心概念
-
流(Stream):数据流动的通道
-
文件(File):磁盘上的数据存储
-
IO操作:数据的读取和写入
1. 创建File对象
java
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) {
// 1. 使用路径字符串
File file1 = new File("C:/test.txt");
// 2. 使用父路径 + 子路径
File file2 = new File("C:/test", "test.txt");
// 3. 使用File父对象 + 子路径
File parent = new File("C:/test");
File file3 = new File(parent, "test.txt");
// 4. 相对路径(相对于项目根目录)
File file4 = new File("src/main/resources/config.txt");
// 5. 跨平台路径分隔符
String path = "data" + File.separator + "files" + File.separator + "test.txt";
File file5 = new File(path);
// 6. URI方式
File file6 = new File(new java.net.URI("file:/C:/test.txt"));
}
}
2. File类常用方法
java
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class FileMethods {
public static void main(String[] args) throws IOException {
File file = new File("test.txt");
// ========== 文件操作 ==========
// 创建文件
boolean created = file.createNewFile();
System.out.println("文件创建: " + created);
// 判断存在性
System.out.println("文件是否存在: " + file.exists());
// 删除文件
boolean deleted = file.delete();
System.out.println("文件删除: " + deleted);
// JVM退出时删除
file.deleteOnExit();
// ========== 文件状态判断 ==========
System.out.println("是否是文件: " + file.isFile());
System.out.println("是否是目录: " + file.isDirectory());
System.out.println("是否隐藏: " + file.isHidden());
System.out.println("是否可读: " + file.canRead());
System.out.println("是否可写: " + file.canWrite());
System.out.println("是否可执行: " + file.canExecute());
System.out.println("是否是绝对路径: " + file.isAbsolute());
// ========== 获取文件信息 ==========
System.out.println("文件名: " + file.getName());
System.out.println("父路径: " + file.getParent());
System.out.println("路径: " + file.getPath());
System.out.println("绝对路径: " + file.getAbsolutePath());
System.out.println("规范路径: " + file.getCanonicalPath());
System.out.println("文件大小(字节): " + file.length());
// 格式化最后修改时间
long lastModified = file.lastModified();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("最后修改时间: " + sdf.format(new Date(lastModified)));
// ========== 目录操作 ==========
File dir = new File("myDir/subDir/deepDir");
// 创建单级目录
boolean singleDir = new File("singleDir").mkdir();
// 创建多级目录
boolean multiDir = dir.mkdirs();
System.out.println("多级目录创建: " + multiDir);
// 列出目录内容
File directory = new File(".");
System.out.println("=== 当前目录内容 ===");
// 列出所有文件和目录名
String[] list = directory.list();
System.out.println("所有项: " + Arrays.toString(list));
// 列出所有文件(带过滤器)
File[] files = directory.listFiles((dir1, name) -> name.endsWith(".java"));
if (files != null) {
for (File f : files) {
System.out.println("Java文件: " + f.getName());
}
}
// 列出所有文件(FileFilter)
File[] allFiles = directory.listFiles(File::isFile);
// 获取磁盘根目录
File[] roots = File.listRoots();
for (File root : roots) {
System.out.println("根目录: " + root);
System.out.println("总空间: " + root.getTotalSpace() / (1024*1024*1024) + " GB");
System.out.println("可用空间: " + root.getFreeSpace() / (1024*1024*1024) + " GB");
}
// ========== 文件属性设置 ==========
file.setReadOnly(); // 设置为只读
file.setWritable(true); // 设置为可写
file.setExecutable(true); // 设置为可执行
file.setLastModified(System.currentTimeMillis()); // 修改时间
// ========== 重命名/移动 ==========
File newFile = new File("renamed.txt");
boolean renamed = file.renameTo(newFile);
System.out.println("重命名: " + renamed);
// ========== 创建临时文件 ==========
File tempFile = File.createTempFile("temp", ".txt");
System.out.println("临时文件: " + tempFile.getAbsolutePath());
tempFile.deleteOnExit(); // JVM退出时删除
// ========== 递归遍历目录 ==========
System.out.println("=== 递归遍历目录 ===");
listAllFiles(new File("."), 0);
}
/**
* 递归遍历目录,树形展示
*/
public static void listAllFiles(File dir, int level) {
File[] files = dir.listFiles();
if (files == null) return;
String indent = " ".repeat(level);
for (File file : files) {
if (file.isDirectory()) {
System.out.println(indent + "📁 " + file.getName());
listAllFiles(file, level + 1);
} else {
System.out.println(indent + "📄 " + file.getName() +
" (" + formatFileSize(file.length()) + ")");
}
}
}
/**
* 格式化文件大小
*/
private static String formatFileSize(long size) {
if (size < 1024) return size + " B";
if (size < 1024 * 1024) return String.format("%.2f KB", size / 1024.0);
if (size < 1024 * 1024 * 1024) return String.format("%.2f MB", size / (1024.0 * 1024));
return String.format("%.2f GB", size / (1024.0 * 1024 * 1024));
}
}
字节流详解
字节流用于处理二进制数据,如图片,视频,音频等。
FileInputStream 和 FileOutputStream
java
import java.io.*;
public class ByteStreamDemo {
/**
* 1. 读取单个字节(效率低,不推荐大文件)
*/
public static void readSingleByte(String filePath) throws IOException {
try (FileInputStream fis = new FileInputStream(filePath)) {
int data;
int count = 0;
while ((data = fis.read()) != -1) {
System.out.print((char) data);
count++;
}
System.out.println("\n总共读取 " + count + " 个字节");
}
}
/**
* 2. 使用字节数组批量读取(推荐)
*/
public static void readByteArray(String filePath) throws IOException {
try (FileInputStream fis = new FileInputStream(filePath)) {
byte[] buffer = new byte[1024]; // 1KB缓冲区
int bytesRead;
StringBuilder content = new StringBuilder();
while ((bytesRead = fis.read(buffer)) != -1) {
content.append(new String(buffer, 0, bytesRead));
}
System.out.println("文件内容: " + content);
System.out.println("文件大小: " + content.length() + " 字节");
}
}
/**
* 3. 分块读取大文件
*/
public static void readLargeFile(String filePath) throws IOException {
try (FileInputStream fis = new FileInputStream(filePath)) {
byte[] buffer = new byte[8192]; // 8KB缓冲区
int bytesRead;
long totalBytes = 0;
long fileSize = new File(filePath).length();
while ((bytesRead = fis.read(buffer)) != -1) {
totalBytes += bytesRead;
// 进度显示
if (totalBytes % (1024 * 1024) == 0) {
double progress = (double) totalBytes / fileSize * 100;
System.out.printf("读取进度: %.2f%%\n", progress);
}
}
System.out.println("文件读取完成,共 " + formatFileSize(totalBytes));
}
}
/**
* 4. 写入文件(覆盖)
*/
public static void writeFile(String filePath, String content) throws IOException {
try (FileOutputStream fos = new FileOutputStream(filePath)) {
byte[] data = content.getBytes();
fos.write(data);
System.out.println("写入成功,写入 " + data.length + " 字节");
}
}
/**
* 5. 追加内容到文件
*/
public static void appendToFile(String filePath, String content) throws IOException {
// 第二个参数true表示追加,false或省略表示覆盖
try (FileOutputStream fos = new FileOutputStream(filePath, true)) {
fos.write(content.getBytes());
fos.write(System.lineSeparator().getBytes()); // 添加换行
System.out.println("追加成功: " + content);
}
}
/**
* 6. 文件复制(字节流)
*/
public static void copyFile(String sourcePath, String destPath) throws IOException {
long startTime = System.currentTimeMillis();
try (FileInputStream fis = new FileInputStream(sourcePath);
FileOutputStream fos = new FileOutputStream(destPath)) {
byte[] buffer = new byte[8192]; // 8KB缓冲区
int bytesRead;
long totalBytes = 0;
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
totalBytes += bytesRead;
}
long endTime = System.currentTimeMillis();
System.out.printf("文件复制完成: %s, 耗时 %d ms\n",
formatFileSize(totalBytes), (endTime - startTime));
}
}
/**
* 7. 图片复制示例
*/
public static void copyImage(String sourcePath, String destPath) throws IOException {
try (FileInputStream fis = new FileInputStream(sourcePath);
FileOutputStream fos = new FileOutputStream(destPath)) {
byte[] buffer = new byte[4096];
int len;
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
System.out.println("图片复制成功: " + destPath);
}
}
/**
* 8. 分片读取(模拟断点续传)
*/
public static void readPartial(String filePath, long start, long end) throws IOException {
try (RandomAccessFile raf = new RandomAccessFile(filePath, "r")) {
raf.seek(start); // 定位到指定位置
long remaining = end - start + 1;
byte[] buffer = new byte[4096];
while (remaining > 0) {
int bytesToRead = (int) Math.min(buffer.length, remaining);
int bytesRead = raf.read(buffer, 0, bytesToRead);
if (bytesRead == -1) break;
// 处理读取的数据
System.out.write(buffer, 0, bytesRead);
remaining -= bytesRead;
}
}
}
private static String formatFileSize(long size) {
if (size < 1024) return size + " B";
if (size < 1024 * 1024) return String.format("%.2f KB", size / 1024.0);
if (size < 1024 * 1024 * 1024) return String.format("%.2f MB", size / (1024.0 * 1024));
return String.format("%.2f GB", size / (1024.0 * 1024 * 1024));
}
public static void main(String[] args) {
try {
String testFile = "test.txt";
// 写入文件
writeFile(testFile, "Hello, Java IO!\n第二行内容\n第三行内容");
// 追加内容
appendToFile(testFile, "这是追加的内容");
// 读取文件
readByteArray(testFile);
// 复制文件
copyFile(testFile, "test_copy.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedInputStream 和 BufferedOutputStream
缓冲流可以提高IO性能,减少实际读写次数
java
import java.io.*;
public class BufferedStreamDemo {
/**
* 1. 使用缓冲流复制文件
*/
public static void bufferedCopy(String sourcePath, String destPath) throws IOException {
long startTime = System.currentTimeMillis();
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourcePath));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destPath))) {
byte[] buffer = new byte[8192];
int bytesRead;
long totalBytes = 0;
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
totalBytes += bytesRead;
}
bos.flush(); // 刷新缓冲区,确保所有数据都写入
long endTime = System.currentTimeMillis();
System.out.printf("缓冲流复制完成: %s, 耗时: %d ms\n",
formatFileSize(totalBytes), (endTime - startTime));
}
}
/**
* 2. 性能对比测试
*/
public static void performanceTest() throws IOException {
String source = "large_file.dat";
String dest1 = "copy1.dat";
String dest2 = "copy2.dat";
// 创建测试文件(10MB)
createTestFile(source, 10 * 1024 * 1024);
// 不使用缓冲流(逐个字节)
long start = System.currentTimeMillis();
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(dest1)) {
int data;
while ((data = fis.read()) != -1) {
fos.write(data);
}
}
long time1 = System.currentTimeMillis() - start;
// 不使用缓冲流(批量)
start = System.currentTimeMillis();
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(dest1)) {
byte[] buffer = new byte[8192];
int len;
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
}
long time2 = System.currentTimeMillis() - start;
// 使用缓冲流
start = System.currentTimeMillis();
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest2))) {
byte[] buffer = new byte[8192];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
}
long time3 = System.currentTimeMillis() - start;
System.out.println("=== 性能对比 ===");
System.out.printf("逐个字节读写: %d ms (最慢)\n", time1);
System.out.printf("批量读写(无缓冲): %d ms\n", time2);
System.out.printf("缓冲流读写: %d ms (最快)\n", time3);
System.out.printf("缓冲流性能提升: %.2f 倍\n", (double) time1 / time3);
// 清理测试文件
new File(source).delete();
new File(dest1).delete();
new File(dest2).delete();
}
/**
* 3. 自定义缓冲区大小
*/
public static void customBufferSize(String source, String dest, int bufferSize)
throws IOException {
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(source), bufferSize);
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(dest), bufferSize)) {
byte[] buffer = new byte[bufferSize];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.flush();
System.out.printf("使用 %d 字节缓冲区复制完成\n", bufferSize);
}
}
private static void createTestFile(String path, int size) throws IOException {
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path))) {
byte[] data = new byte[1024];
for (int i = 0; i < size / 1024; i++) {
bos.write(data);
}
}
}
private static String formatFileSize(long size) {
if (size < 1024) return size + " B";
if (size < 1024 * 1024) return String.format("%.2f KB", size / 1024.0);
if (size < 1024 * 1024 * 1024) return String.format("%.2f MB", size / (1024.0 * 1024));
return String.format("%.2f GB", size / (1024.0 * 1024 * 1024));
}
}
DataInputStream 和 DataOutputStream
用于读写java基础数据类型,保持数据类型和精度
java
import java.io.*;
public class DataStreamDemo {
/**
* 1. 写入基本数据类型
*/
public static void writePrimitiveData(String filePath) throws IOException {
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(filePath))) {
// 写入各种基本类型
dos.writeInt(100);
dos.writeDouble(3.14159265358979);
dos.writeBoolean(true);
dos.writeChar('A');
dos.writeLong(123456789L);
dos.writeFloat(3.14f);
dos.writeUTF("Hello, 你好!"); // 写入UTF-8字符串
System.out.println("基本数据类型写入完成");
}
}
/**
* 2. 读取基本数据类型(必须按写入顺序读取)
*/
public static void readPrimitiveData(String filePath) throws IOException {
try (DataInputStream dis = new DataInputStream(new FileInputStream(filePath))) {
int intValue = dis.readInt();
double doubleValue = dis.readDouble();
boolean booleanValue = dis.readBoolean();
char charValue = dis.readChar();
long longValue = dis.readLong();
float floatValue = dis.readFloat();
String stringValue = dis.readUTF();
System.out.println("=== 读取的基本数据类型 ===");
System.out.println("int: " + intValue);
System.out.println("double: " + doubleValue);
System.out.println("boolean: " + booleanValue);
System.out.println("char: " + charValue);
System.out.println("long: " + longValue);
System.out.println("float: " + floatValue);
System.out.println("String: " + stringValue);
}
}
/**
* 3. 存储学生成绩数据
*/
public static class Student implements Serializable {
private String name;
private int age;
private double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return String.format("Student{name='%s', age=%d, score=%.1f}", name, age, score);
}
}
public static void saveStudentScores(String filePath, Student[] students) throws IOException {
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(filePath))) {
// 先写入学生数量
dos.writeInt(students.length);
// 写入每个学生的数据
for (Student s : students) {
dos.writeUTF(s.name);
dos.writeInt(s.age);
dos.writeDouble(s.score);
}
System.out.println("学生成绩保存成功,共 " + students.length + " 人");
}
}
public static void loadStudentScores(String filePath) throws IOException {
try (DataInputStream dis = new DataInputStream(new FileInputStream(filePath))) {
int count = dis.readInt();
System.out.println("=== 学生成绩列表 ===");
double sum = 0;
double max = Double.MIN_VALUE;
double min = Double.MAX_VALUE;
String maxName = "", minName = "";
for (int i = 0; i < count; i++) {
String name = dis.readUTF();
int age = dis.readInt();
double score = dis.readDouble();
sum += score;
if (score > max) {
max = score;
maxName = name;
}
if (score < min) {
min = score;
minName = name;
}
System.out.printf("%-8s 年龄: %2d, 分数: %5.1f\n", name, age, score);
}
System.out.println("=== 统计信息 ===");
System.out.printf("平均分: %.2f\n", sum / count);
System.out.printf("最高分: %s (%.1f分)\n", maxName, max);
System.out.printf("最低分: %s (%.1f分)\n", minName, min);
}
}
/**
* 4. 使用DataStream实现简单数据库
*/
public static class SimpleDatabase {
private static final String DB_FILE = "database.dat";
public static void saveUser(String username, String password, int level) throws IOException {
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(DB_FILE, true))) {
dos.writeUTF(username);
dos.writeUTF(password);
dos.writeInt(level);
System.out.println("用户保存成功: " + username);
}
}
public static void listAllUsers() throws IOException {
try (DataInputStream dis = new DataInputStream(new FileInputStream(DB_FILE))) {
System.out.println("=== 用户列表 ===");
while (true) {
try {
String username = dis.readUTF();
String password = dis.readUTF();
int level = dis.readInt();
System.out.printf("用户名: %-10s 权限等级: %d\n", username, level);
} catch (EOFException e) {
break; // 文件读取完毕
}
}
}
}
public static boolean authenticate(String username, String password) throws IOException {
try (DataInputStream dis = new DataInputStream(new FileInputStream(DB_FILE))) {
while (true) {
try {
String u = dis.readUTF();
String p = dis.readUTF();
int level = dis.readInt();
if (u.equals(username) && p.equals(password)) {
System.out.println("认证成功,权限等级: " + level);
return true;
}
} catch (EOFException e) {
break;
}
}
}
System.out.println("认证失败: 用户名或密码错误");
return false;
}
}
public static void main(String[] args) throws IOException {
// 1. 基本类型读写
String dataFile = "primitive.dat";
writePrimitiveData(dataFile);
readPrimitiveData(dataFile);
// 2. 学生成绩管理
Student[] students = {
new Student("张三", 20, 85.5),
new Student("李四", 21, 92.0),
new Student("王五", 20, 78.5),
new Student("赵六", 22, 88.0)
};
saveStudentScores("scores.dat", students);
loadStudentScores("scores.dat");
// 3. 简单数据库示例
SimpleDatabase.saveUser("admin", "admin123", 3);
SimpleDatabase.saveUser("user1", "pass123", 1);
SimpleDatabase.saveUser("user2", "pass456", 2);
SimpleDatabase.listAllUsers();
SimpleDatabase.authenticate("admin", "admin123");
SimpleDatabase.authenticate("user1", "wrong");
}
}