目录
一、文件的读
InputStream 输入流 可以想象一个水龙头在滴水 数据从水龙头中流出的这样一个过程
1.方法
方法 | 说明 |
abstract int read() |
|
int read(byte[] b) | 准备一个桶,桶的大小就是byte[ ] b的大小 返回的是真实读了多少字节的数据 |
| 这个桶 从 off 开始的 len 个字节可以使用 |
void close() | 水龙头打开需要关闭 |
2.代码
(1)一个字节一个字节的读取
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
// 文件内容一个字节的读取
public class ReadFile {
public static void main(String[] args) throws IOException {
// 使用相对路径:hello.txt
//E:\java程序\class practice...(绝对路径)
try(InputStream is = new FileInputStream("这里需要写你文件的路径")){
// 不知道文件大小想要读取时
while (true){
int b = is.read();
System.out.println(b);
if(b == -1){
break;
}
}
// for(int i = 0;i < 13;i++){
// int b = is.read();
// System.out.println(b);
// }
// // 读取完之后会读到 -1
// System.out.println(is.read());
}
}
}
(2)一次读一堆
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
// 文件内容的读取:一次读一堆
public class ReadFile2 {
public static void main(String[] args) throws IOException {
byte[] b = new byte[20];
try(InputStream is = new FileInputStream("这里需要写你文件的路径")){
while(true){
int n = is.read(b);
if(n == -1){
break;
}
byte[] a = Arrays.copyOf(b,n);
System.out.println(Arrays.toString(a));
}
}
}
}
如果把 b 数组的大小改成 5,则会分三次读取
byte[] b = new byte[5];
(3)文件内容中有中文
UTF-8 变长(每个字符占用的字节数不固定)
数字、英文、回车 1 个字节 按照 ASCII标准
中文 大部分是 3 个字节
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
// 文件中有中文的读取
public class ReadText {
public static void main(String[] args) throws IOException {
try(InputStream is = new FileInputStream("这里需要输入你的文件路径")){
try(Scanner scanner = new Scanner(is,"UTF-8")){
while (scanner.hasNextLine()){
String line = scanner.nextLine();
System.out.println(line);
}
}
}
}
}
当我们文件的的编码格式和我们代码中相同时,会输出正确的结果。但如果两者不匹配时,输出就会乱码。解决方案就是修改这个编码格式。
二、文件的写
OutPutStream 相当于是下水道
1.方法
方法 | 说明 |
void flush() | 冲刷缓冲区的 |
void write(byte[ ] b) | 准备一个桶,一次写一批数据 |
void write(byte[ ] b,int off,int len) | 一次写一批,桶从 off 开始,长度为 len |
abstract void write(int b) | 一次写一个字节 |
FileOutputStream 是覆盖式的写
对应文件不存在,创建文件写入
对应的文件存在 && 普通文件 -> 删除文件原有内容,覆盖写入
对应的文件存在 && 目录文件 -> 失败(异常)
2.代码
(1) 一个字节一个字节的写
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
// 文件的写入:一个字节一个字节的写
public class WriteFile {
public static void main(String[] args) throws IOException {
try(OutputStream os = new FileOutputStream("这里写文件路径\\world.txt")){
os.write('H');
os.write('e');
os.write('\r');
os.write('\n');
os.flush(); // 手动调用 flush,确保所有数据真正写入文件中
}
}
}
(2)一堆的写
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
// 文件的写入:一个字节一个字节的写
public class WriteFile {
public static void main(String[] args) throws IOException {
try(OutputStream os = new FileOutputStream("这里写文件路径\\world.txt")){
byte[] b = {'H','e','l','l','o','\r','\n'};
os.write(b);
os.flush();
}
}
}
3.应用
(1)文件复制工具
给定源文件(普通文件)路径 + 目标文件路径,完成文件复制工作
同理,图片文件也可以这么复制
import java.io.*;
public class CopyFile {
public static void main(String[] args) throws IOException {
String srcPath = "hello.txt";
String destPath = "dest.txt";
// 确认源文件存在 && 是普通文件
// 确保目标路径不存在 && 目标文件的父目录是否存在
File srcFile = new File(srcPath);
if(!srcFile.isFile()){
System.out.println("源文件不存在 or 不是普通文件");
return;
}
File destFile = new File(destPath);
if(destFile.exists()){
System.out.println("目标文件已经存在");
return;
}
File parentFile = destFile.getParentFile();
if(!parentFile.isDirectory()){
System.out.println("目标文件的父目录不是目录");
return;
}
byte[] b = new byte[1024];
try (InputStream is = new FileInputStream(srcFile)){
try(OutputStream os = new FileOutputStream(destFile)){
while (true){
int n = is.read(b);
if(n == -1){
break;
}
os.write(b,0,n);
}
os.flush();
}
}
}
}
(2)目录复制工具
给定源目录路径 + 目标目录路径 ,完成整个目录的复制工作
子树的复制 = 遍历树的每个结点 + 每个结点进行复制
1.目录:mkdirs()
2.文件:应用1 的方式
import java.io.*;
// 目录复制
public class CopyDirectory {
// 1. static 是为了遍历的时候随时可以使用这两个值
// 2. 定义 File,一会要使用 File 中的某些方法
static File srcDir = new File("E:\\java程序\\图书管理系统");
static File destDir = new File("E:\\java程序\\目标");
private static File getDestFile(File file) throws IOException{
String srcPath = srcDir.getCanonicalPath();
String filePath = file.getCanonicalPath();
String subPath = filePath.substring(srcPath.length());
String destPath = destDir.getCanonicalPath();
String destFilePath = destPath + subPath;
return new File(destFilePath);
}
private static void traversal(File dir) throws IOException {
//1.获取目录下的所有孩子
File[] files = dir.listFiles();
if(files == null){
return;
}
// 2. 遍历目录下的每个孩子(文件)
for(File file : files){
File destFile = getDestFile(file);
// 文件是目录
if(file.isDirectory()){
// 按照相同的结构,创建出目录 mkdirs()
destFile.mkdirs();
traversal(file);
} else {
// 文件是普通文件
copyFile(file,destFile);
}
}
}
// 文件复制
private static void copyFile(File srcFile, File destFile) throws IOException{
byte[] b = new byte[1024];
try (InputStream is = new FileInputStream(srcFile)){
try(OutputStream os = new FileOutputStream(destFile)){
while (true){
int n = is.read(b);
if(n == -1){
break;
}
os.write(b,0,n);
}
os.flush();
}
}
}
public static void main(String[] args) throws IOException{
// 基本条件检查
if(!srcDir.isDirectory()){
System.out.println("源不是目录");
return;
}
if(destDir.exists()){
System.out.println("目标目录已经存在");
return;
}
traversal(srcDir);
}
}
(3)文本替换工具
你好 -> Hello
import java.io.*;
import java.util.Scanner;
public class ReplaceTool {
public static void main(String[] args) throws IOException {
try(InputStream is = new FileInputStream("E:\\java程序\\class practice\\src\\com\\lingqi_practice_2022\\May\\p05_10\\src.txt")){
try(Scanner sc = new Scanner(is,"UTF-8")){
try(OutputStream os = new FileOutputStream("E:\\java程序\\class practice\\src\\com\\lingqi_practice_2022\\May\\p05_10\\dest.txt")){
// OutputStream(byte) -> OutputStreamWriter(char) -> PrintWriter(print/println/printf)
try(OutputStreamWriter writer = new OutputStreamWriter(os,"UTF-8")){
try(PrintWriter printWriter = new PrintWriter(writer)){
// 读取每一行,进行替换,写入新的文件
while (sc.hasNextLine()){
String line = sc.nextLine();
String replace = line.replace("你好","Hello");
printWriter.println(replace);
}
printWriter.flush();
}
}
}
}
}
}
}
总结IO:
IO{文件、网络、其他设备}
我们以文件为例介绍IO File 是作用于文件的,像网络就不能使用
InputStreatm/OutputStream... 系列可以作用于其他IO