Java I/O操作详解:从控制台到文件读写
1. Java输入输出方法概述在Java编程中输入输出(I/O)是最基础也是最重要的操作之一。无论是控制台程序、桌面应用还是Web服务都离不开数据的输入和输出。Java提供了丰富的I/O类库可以满足各种场景下的数据交互需求。对于初学者来说掌握Java的I/O操作是迈向实际开发的第一步。我见过太多新手因为不熟悉I/O操作而卡在简单的数据交互环节导致学习进度受阻。本文将系统介绍Java中最常用的输入输出方法包括控制台输入输出、格式化输出、文件读写等核心内容。2. 控制台输出方法详解2.1 基本输出方法Java中最简单的输出方式是使用System.out提供的三个方法System.out.print(Hello); // 不换行输出 System.out.println(World); // 带换行输出 System.out.printf(PI%.2f, 3.14159); // 格式化输出print()和println()的区别仅在于是否在输出后添加换行符。在实际开发中println()使用频率最高因为它能让输出结果更清晰易读。注意System.out.print()系列方法实际上属于PrintStream类System.out是Java标准库预定义的一个PrintStream实例。2.2 格式化输出技巧printf()方法提供了强大的格式化输出能力其语法与C语言的printf类似double price 19.99; int quantity 5; System.out.printf(单价: %.2f, 数量: %d, 总价: %.2f\n, price, quantity, price*quantity);常用格式说明符%d十进制整数%f浮点数%s字符串%n平台相关的换行符%t日期时间格式控制还可以指定宽度、精度和对齐方式System.out.printf(|%10s|%-10s|%10.2f|, Hello, World, 3.1415);3. 控制台输入方法详解3.1 使用Scanner类Java中最常用的输入方式是使用java.util.Scanner类import java.util.Scanner; public class InputDemo { public static void main(String[] args) { Scanner scanner new Scanner(System.in); System.out.print(请输入姓名: ); String name scanner.nextLine(); System.out.print(请输入年龄: ); int age scanner.nextInt(); System.out.printf(你好%s你今年%d岁, name, age); } }Scanner提供了多种方法来读取不同类型的数据nextLine()读取一行文本nextInt()读取整数nextDouble()读取双精度浮点数nextBoolean()读取布尔值3.2 输入验证技巧实际开发中用户输入往往不可靠需要进行验证Scanner scanner new Scanner(System.in); int age 0; while(true) { System.out.print(请输入年龄: ); if(scanner.hasNextInt()) { age scanner.nextInt(); break; } else { System.out.println(输入无效请重新输入数字); scanner.next(); // 清除无效输入 } }经验使用hasNextXxx()方法先验证输入类型可以有效避免InputMismatchException异常。4. 文件读写操作4.1 文件读取Java提供了多种文件读取方式以下是使用BufferedReader的示例import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class FileReadDemo { public static void main(String[] args) { try (BufferedReader br new BufferedReader(new FileReader(test.txt))) { String line; while ((line br.readLine()) ! null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } } }4.2 文件写入使用BufferedWriter写入文件import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class FileWriteDemo { public static void main(String[] args) { try (BufferedWriter bw new BufferedWriter(new FileWriter(output.txt))) { bw.write(第一行内容); bw.newLine(); bw.write(第二行内容); } catch (IOException e) { e.printStackTrace(); } } }4.3 使用try-with-resourcesJava 7引入的try-with-resources语法可以自动关闭资源避免内存泄漏try (BufferedReader br new BufferedReader(new FileReader(file.txt))) { // 使用资源 } catch (IOException e) { // 异常处理 }5. 高级I/O操作5.1 字节流与字符流Java I/O分为字节流和字符流两大体系字节流InputStream/OutputStream处理二进制数据字符流Reader/Writer处理文本数据常用实现类FileInputStream/FileOutputStream文件字节流FileReader/FileWriter文件字符流BufferedInputStream/BufferedOutputStream缓冲字节流BufferedReader/BufferedWriter缓冲字符流5.2 对象序列化Java对象可以通过实现Serializable接口进行序列化import java.io.*; class Person implements Serializable { String name; int age; } public class SerializationDemo { public static void main(String[] args) { Person p new Person(); p.name 张三; p.age 25; // 序列化 try (ObjectOutputStream oos new ObjectOutputStream( new FileOutputStream(person.dat))) { oos.writeObject(p); } catch (IOException e) { e.printStackTrace(); } // 反序列化 try (ObjectInputStream ois new ObjectInputStream( new FileInputStream(person.dat))) { Person p2 (Person) ois.readObject(); System.out.println(p2.name , p2.age); } catch (Exception e) { e.printStackTrace(); } } }6. 常见问题与解决方案6.1 中文乱码问题文件读写时经常遇到中文乱码解决方案是指定正确的字符编码BufferedReader br new BufferedReader( new InputStreamReader(new FileInputStream(file.txt), UTF-8));6.2 文件路径问题相对路径和绝对路径的使用需要注意// 相对路径相对于项目根目录 File file new File(data/test.txt); // 获取绝对路径 String absPath file.getAbsolutePath();6.3 资源释放问题忘记关闭I/O流会导致资源泄漏推荐使用try-with-resources语法。6.4 大文件处理技巧处理大文件时应该使用缓冲并逐行/逐块处理try (BufferedReader br new BufferedReader(new FileReader(large.txt))) { String line; while ((line br.readLine()) ! null) { // 处理每一行 } } catch (IOException e) { e.printStackTrace(); }7. 性能优化建议使用缓冲流(BufferedInputStream/BufferedReader)可以提高I/O性能批量读写比单字节/字符读写效率高得多对于频繁读写操作考虑使用内存映射文件(MappedByteBuffer)合理设置缓冲区大小(通常8KB是个不错的起点)对于大量小文件操作考虑合并处理或使用NIO8. Java NIO简介Java NIO(New I/O)提供了更高效的I/O操作方式import java.nio.file.*; import java.util.List; public class NioDemo { public static void main(String[] args) { try { // 读取所有行 ListString lines Files.readAllLines(Paths.get(file.txt)); // 写入文件 Files.write(Paths.get(output.txt), Hello NIO.getBytes(), StandardOpenOption.CREATE); } catch (IOException e) { e.printStackTrace(); } } }NIO的主要优势通道(Channel)和缓冲区(Buffer)的概念非阻塞I/O支持选择器(Selector)实现多路复用更灵活的文件操作API9. 实际应用案例9.1 配置文件读取import java.util.Properties; import java.io.FileInputStream; public class ConfigReader { public static void main(String[] args) { Properties prop new Properties(); try (FileInputStream fis new FileInputStream(config.properties)) { prop.load(fis); String dbUrl prop.getProperty(db.url); String user prop.getProperty(db.user); System.out.println(数据库URL: dbUrl); System.out.println(用户名: user); } catch (Exception e) { e.printStackTrace(); } } }9.2 日志文件分析import java.nio.file.*; import java.util.stream.*; public class LogAnalyzer { public static void main(String[] args) { try (StreamString lines Files.lines(Paths.get(server.log))) { long errorCount lines .filter(line - line.contains(ERROR)) .count(); System.out.println(错误日志数量: errorCount); } catch (IOException e) { e.printStackTrace(); } } }10. 最佳实践总结优先使用try-with-resources确保资源释放文本处理使用字符流二进制数据处理使用字节流总是考虑字符编码问题推荐统一使用UTF-8大文件处理使用缓冲和流式处理用户输入必须进行验证和异常处理考虑使用NIO API处理高性能I/O需求合理使用第三方库如Apache Commons IO简化开发重要操作添加日志记录便于问题排查Java的I/O系统看似简单实则包含大量细节和技巧。在实际项目中合理的I/O操作能显著提升应用性能和稳定性。建议开发者不仅要掌握基本用法还要深入理解底层原理这样才能在面对复杂场景时游刃有余。