用FileInputStream和FileOutputStream复制文件的核心是纯字节搬运,需验证源文件存在且可读、提前创建目标目录、使用带缓冲的批量读写(如8KB缓冲区)、并用try-with-resources自动关闭流。

用 FileInputStream 和 FileOutputStream 复制图片或音频文件,核心是“纯字节搬运”——不解析内容,只确保源数据完整、目标路径可用、流正确关闭。关键不在格式,而在路径处理和异常兜底。
确保源文件存在且可读
复制前必须验证源文件真实存在且有读取权限,否则会抛 FileNotFoundException:
- 用
new File(sourcePath).exists()主动检查,避免靠异常捕获来判断 - 如果源路径是相对路径(如
"img/logo.png"),注意当前工作目录是否符合预期;建议统一用Paths.get(...)或绝对路径构造File - 中文路径在开发环境通常没问题,但打包成 JAR 后,若目标系统默认编码不是 UTF-8(如某些 Windows Server),可能出错;可考虑用
StandardCharsets.UTF_8显式处理路径字符串(较少见,一般无需干预)
提前创建目标目录结构
FileOutputStream 不会自动创建父目录,目标路径的上级文件夹不存在就会失败:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 调用
new File(destPath).getParentFile().mkdirs(),它会递归创建所有缺失的父级目录 - 即使目标路径是
"output/2026/photo.jpg",也要确保output/2026目录已存在 - 不要依赖
FileOutputStream的append模式来绕过这个问题——它只控制写入方式,不解决路径缺失
使用带缓冲的字节数组批量读写
逐字节读写(read() 返回单个 int)效率极低,尤其对大文件;推荐固定大小缓冲区(如 8KB)一次读多字节:
立即学习“Java免费学习笔记(深入)”;
- 缓冲区大小设为 8192(8KB)或 65536(64KB),平衡内存占用与吞吐量
- 必须用
fos.write(buf, 0, len)而非fos.write(buf),因为read()实际读到的字节数可能小于缓冲区长度 - 示例片段:
byte[] buf = new byte[8192];
int len;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
用 try-with-resources 自动释放资源
手动 close() 容易遗漏或被异常打断;Java 7+ 推荐 try-with-resources 语法,确保流无论成功与否都会关闭:
- 输入流和输出流都声明在 try 括号内,用分号分隔
- 不需要显式调用
close(),也不用写 finally 块 - 异常统一捕获
IOException即可,FileNotFoundException是它的子类,会被覆盖捕获 - 完整结构:
try (FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(dst)) {
// 读写逻辑
} catch (IOException e) {
// 记录日志或提示用户
}

















