Java基础十一 流(Stream)、文件(File)和IO

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");
    }
}
相关推荐
叶小鸡1 小时前
Java 篇-项目实战-天机学堂(从0到1)-day11
java·开发语言
格林威1 小时前
线阵工业相机:线阵图像出现“波浪纹”,是机械振动还是编码器问题?
开发语言·人工智能·数码相机·计算机视觉·视觉检测·工业相机·线阵相机
knight_9___1 小时前
LLM工具调用面试篇5
人工智能·python·深度学习·面试·职场和发展·llm·agent
light blue bird1 小时前
MES/ERP 工序 BOM 协同多节点工站组件
java·jvm·oracle
Pkmer2 小时前
古法编程: 适配器模式
java·设计模式
liliangcsdn2 小时前
LLM如何辅助RAG从大量文档中筛选目标文档
开发语言·人工智能
无忧.芙桃2 小时前
C++IO库的超详细讲解
开发语言·c++
longxibo2 小时前
【Flowable 7.2 源码深度解析与实战】
java·后端·流程图