说明:本次课程学习了 IO 缓冲流(
BufferedOutputStream/BufferedInputStream:内部缓冲区、flush()刷新、基础流 vs 扩展流)、字符流(FileReader/FileWriter:字符流 = 字节流 + 字符集编码表、直接write(String)写中文无需getBytes())、字符缓冲流(BufferedReader/BufferedWriter:readLine()逐行读取、newLine()跨平台换行)以及 接口化文件复制(CopyFile接口 + 面向接口编程 / 多态 +System.currentTimeMillis()耗时对比)。本作业共 3 道题:基础题(必做)——字符流中文读写器;进阶题(必做)——字符缓冲流成绩排序写回;挑战题(选做)——接口化文件复制效率对比器。覆盖今日 80% 以上知识点。
| 项目 | 要求 |
|---|---|
| 类名 | Demo_题号_你的姓名(如 Demo_01_张三、Demo_02_李四、Demo_03_王五) |
| 文件头注释 | 每个 Java 文件头部需包含 @author、@title、@create 文档注释 |
| 项目 | 要求 |
|---|---|
| 提交方式 | 将源码文件 + 运行结果截图提交至班级指定平台 |
| 截止时间 | 下次上课前 |
知识点:字符流概念(字符流 = 字节流 + 字符集编码表)、FileWriter(直接 write(String) 写中文、六种写方法)、FileReader(read() / read(char[]) 两种读法)、new String(chars, 0, count) 字符数组转字符串、flush() / close()
场景描述:字节流操作中文很不方便,需要 getBytes() 手动转字节数组。字符流内部按字符集编码表完成"字符 ↔ 字节"转换,可以直接 write("中文")。请用 FileWriter 把一首中文古诗写入 D:/poem.txt,再用 FileReader 读回并显示到控制台。
题目要求:
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author 你的姓名
* @title 题目1:字符流中文读写器
* @create 2026/8/7
*/
public class Demo_01_姓名 {
public static void main(String[] args) throws IOException {
// ========== 写:FileWriter 直接写中文(无需 getBytes) ==========
// TODO 1: new FileWriter("D:/poem.txt") 创建文件字符输出流
// TODO 2: 用 fw.write("...") 写至少 2 句中文(如静夜思),句末用 fw.write("\r\n") 换行
// TODO 3: fw.flush(); // 字符流自带缓冲区,强制刷新到文件
// TODO 4: fw.close(); // 关闭流
// ========== 读:FileReader 读回并显示 ==========
// TODO 5: new FileReader("D:/poem.txt") 创建文件字符输入流
// TODO 6: char[] chars = new char[1024];
// int count;
// while ((count = fr.read(chars)) != -1) {
// System.out.print(new String(chars, 0, count));
// }
// TODO 7: fr.close(); // 关闭流
}
}
预期输出示例:
床前明月光,疑是地上霜。
举头望明月,低头思故乡。
要求说明:
FileWriter / FileReader),不允许用字节流getBytes(),直接 write("中文")read(char[]) 批量读取 + new String(chars, 0, count),不允许逐字符打印💡 提示:
FileWriter / FileReader 构造方法只传路径即可(使用系统默认字符集)fr.read(chars) 返回本次读到的有效字符个数,可能小于 chars.length,所以转字符串时务必用 new String(chars, 0, count) 截断有效部分flush() 之后还可以继续写;close() 之前会自动刷新一次🎯 挑战加分(选做):
new FileWriter("D:/poem.txt", true) 追加写第二段,验证 append=true 追加 vs 默认覆盖write(String, off, len) 只写入诗句的某一段子串知识点:BufferedReader / BufferedWriter、readLine() 逐行读取(末尾返回 null)、newLine() 跨平台换行、String.split("-") 拆分、Integer.parseInt() 字符串转整数、ArrayList + Collections.sort + Comparator(Lambda)排序、读取→处理→集合→排序→写回五步闭环
场景描述:D:/scores.txt 中保存了若干行"姓名-成绩"(顺序是乱的),如下:
李四-78
王五-92
张三-66
赵六-85
孙七-95
周八-88
请用 BufferedReader 逐行读取 → split("-") 拆分成姓名和成绩 → 封装 Student 对象存入 ArrayList → 按成绩从高到低排序 → 用 BufferedWriter 把带名次的结果写回 D:/sorted.txt。
题目要求:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
/**
* @author 你的姓名
* @title 题目2:字符缓冲流成绩排序写回
* @create 2026/8/7
*/
public class Demo_02_姓名 {
// 学生类:姓名 + 成绩
static class Student {
private String name;
private int score;
public Student(String name, int score) { this.name = name; this.score = score; }
public String getName() { return name; }
public int getScore() { return score; }
@Override
public String toString() { return name + "-" + score; }
}
public static void main(String[] args) throws IOException {
// ========== 1、将文件中的数据读取到程序中 ==========
// TODO 1: new BufferedReader(new FileReader("D:/scores.txt")) 字符缓冲流包装
// TODO 2: while ((line = br.readLine()) != null) { ... } 逐行读取
// ========== 2、对读取到的数据进行处理 ==========
// TODO 3: String[] parts = line.split("-"); 按 "-" 拆分成 [姓名, 成绩]
// TODO 4: int score = Integer.parseInt(parts[1]); 成绩字符串 → 整数
// ========== 3、将处理后的数据添加到集合中 ==========
// TODO 5: new Student(parts[0], score) 封装对象,list.add(stu) 存入 ArrayList
// ========== 4、对集合中的数据进行排序 ==========
// TODO 6: Collections.sort(list, (o1, o2) -> o2.getScore() - o1.getScore()); // 按成绩降序
// ========== 5、将排序后的集合中的数据写入到文件中 ==========
// TODO 7: new BufferedWriter(new FileWriter("D:/sorted.txt"))
// TODO 8: for 遍历排序后的集合,bw.write("第" + (i+1) + "名:" + list.get(i)) + bw.newLine()
// TODO 9: bw.flush(); bw.close(); br.close();
System.out.println("排序完成!结果已写入 D:/sorted.txt");
}
}
预期输出示例(D:/sorted.txt 内容):
第1名:孙七-95
第2名:王五-92
第3名:周八-88
第4名:赵六-85
第5名:李四-78
第6名:张三-66
要求说明:
BufferedReader / BufferedWriter),不允许用普通字符流readLine() 逐行读取,while ((line = br.readLine()) != null) 循环Collections.sort + Comparator(Lambda 或匿名内部类均可),按成绩降序newLine() 换行(不要手写 "\r\n")💡 提示:
line.split("-") 返回 String[],parts[0] 是姓名、parts[1] 是成绩字符串Integer.parseInt(parts[1]) 把成绩字符串转成整数后,才能按数值降序(否则字符串按字典序,"95" 会排在 "9" 后面导致排序错误)bw.write("第" + (i + 1) + "名:" + list.get(i)) 直接拼接对象会自动调用重写的 toString() 输出"姓名-成绩"🎯 挑战加分(选做):
result == 0 ? o1.getName().compareTo(o2.getName()) : result)Student implements Comparable<Student>,用 TreeSet 自动排序去重知识点:CopyFile 接口(面向接口编程 / 多态)、FileInputStream / FileOutputStream 普通字节流、BufferedInputStream / BufferedOutputStream 字节缓冲流、byte[] 缓冲区循环复制、try-catch-finally 关闭资源、System.currentTimeMillis() 耗时对比、基础流 vs 扩展流
场景描述:课堂用 CopyFile 接口统一了文件复制规范,并实现了两个版本:Copy01(普通字节流 + byte[8192] 数组)和 BufferedCopy(缓冲流包装底层流)。请定义 CopyFile 接口 + 实现这两个版本,复制同一个大文件,用耗时说话——验证"缓冲流更快"。
题目要求:
import java.io.*;
/**
* @author 你的姓名
* @title 题目3:接口化文件复制效率对比器
* @create 2026/8/7
*/
public class Demo_03_姓名 {
// ========== ① 复制器接口:统一复制规范 ==========
interface CopyFile {
String copy(String src, String desc) throws IOException;
}
// ========== ② 普通字节流实现:FileInputStream + FileOutputStream + byte[8192] + try-catch-finally ==========
static class Copy01 implements CopyFile {
@Override
public String copy(String src, String desc) {
// TODO 1: FileOutputStream fos / FileInputStream fis 声明为 null,try 中创建
// TODO 2: byte[8192] 缓冲区 + while ((len = fis.read(bytes)) != -1) { fos.write(bytes, 0, len); }
// TODO 3: catch (IOException e) 返回 "文件复制失败"
// TODO 4: finally 中关闭 fos / fis(close 也可能抛 IOException → 包装成 RuntimeException)
return "文件复制成功";
}
}
// ========== ③ 缓冲流实现:BufferedOutputStream / BufferedInputStream 包装底层流 ==========
static class BufferedCopy implements CopyFile {
@Override
public String copy(String src, String desc) throws IOException {
// TODO 5: 先创建文件流,再用缓冲流包装(new BufferedOutputStream(fos))
// TODO 6: byte[8192] + while ((count = bis.read(bytes)) != -1) { bos.write(bytes, 0, count); }
// TODO 7: 关闭:先关缓冲流再关底层流
return "复制成功";
}
}
public static void main(String[] args) throws IOException {
String src = "D:/大文件.zip"; // 换成你电脑上任意大于 10MB 的文件
// TODO 8: 用 new Copy01().copy(src, "D:/copy1.zip") 复制,System.currentTimeMillis() 统计耗时
// TODO 9: 用 new BufferedCopy().copy(src, "D:/copy2.zip") 复制,统计耗时
// TODO 10: 输出两次耗时,对比哪个更快
}
}
预期输出示例:
普通字节流耗时:486 毫秒
缓冲流耗时:203 毫秒
缓冲流更快!
要求说明:
CopyFile 接口方法 String copy(String src, String desc) throws IOExceptionimplements CopyFile,体现面向接口编程 / 多态System.currentTimeMillis() 分别统计两个版本的复制耗时并输出对比💡 提示:
Copy01 用 try-catch-finally 内部处理异常(返回提示信息);BufferedCopy 可以直接 throws IOException(接口允许两种异常处理风格并存)Copy01 先关 fos 再关 fis;BufferedCopy 先关缓冲流再关底层流🎯 挑战加分(选做):
byte[] 改成 1024 / 4096 / 8192 / 16384 各测一次,总结"缓冲区大小 → 耗时"规律FileWriter 的 Charset.forName("GBK") 写一个中文文件,再用默认字符集的 FileReader 读取,观察乱码;改用 FileReader(path, Charset.forName("GBK")) 指定同一字符集读,验证乱码消失Demo_题号_姓名(如 Demo_01_张三、Demo_02_李四、Demo_03_王五)@author(你的姓名)、@title(题目名称)、@create 2026/8/7