目录
File 类
File 类构造器
路径分隔符
File file1 = new File("d:\\目录\\info.txt");
File file2 = new File("d:" + File.separator + "目录" + File.separator + "info.txt");
File file3 = new File("d:/目录");
File file4 = new File("d:" + File.separator + "目录");
File 类的常用方法
File 类的属性
public static void main(String[] args) {
File dir1 = new File("D:/IOTest/dir1");
if (!dir1.exists()) { // 如果D:/IOTest/dir1不存在,就创建为目录
dir1.mkdir();
}
File dir2 = new File(dir1, "dir2");// 创建以dir1为父目录,名为"dir2"的File对象
if (!dir2.exists()) { // 如果还不存在,就创建为目录
dir2.mkdirs();
}
File dir4 = new File(dir1, "dir3/dir4");
if (!dir4.exists()) {
dir4.mkdirs();
}
File file = new File(dir2, "test.txt");// 创建以dir2为父目录,名为"test.txt"的File对象
if (!file.exists()) { // 如果不存在,就创建为文件
try {
file.createNewFile();// 创建文件,前提是存在对应的目录,否则异常
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
IO流
流的分类与流的基类
输入/输出的区分在于流的目的地,输入流的目的地时内存,其它都是输出流
关闭处理流时,其底层的节点流也会自动关闭
常见的IO流
输入流基类
InputStream
Reader
输出流基类
OutputStream
Writer
IO流的使用
FileReader fr = null;
try {
fr = new FileReader(new File("c:" + File.separator + "test.txt")); // 创建一个数据源是 test 文件的文件输入流
char[] buf = new char[1024];
int len;
while ((len = fr.read(buf)) != -1) { // 循环,直到完全将 test 文件的内容全部读取完
System.out.print(new String(buf, 0, len));
}
} catch (IOException e) {
System.out.println("read-Exception :" + e.getMessage());
} finally {
if (fr != null) {
try {
fr.close(); // 最后关闭 文件输入流
} catch (IOException e) {
System.out.println("close-Exception :" + e.getMessage());
}
}
}
FileWriter fw = null;
try {
fw = new FileWriter(new File("Test.txt")); // 创建一个目的地是 Test 文件的文件输出流
fw.write("这段内容将持久化输出到Test.txt文件"); // 向 Test 文件写入内容,如果没有该文件就创建再写入
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fw != null)
try {
fw.flush(); // 清空缓存,确保所有内容都写入到 Test 文件
fw.close(); // 关闭 文件输出流
} catch (IOException e) {
e.printStackTrace();
}
常见处理流
缓冲流
- 缓冲流即为处理流,缓冲流建立在已存在的IO流之上
- 缓冲流又称为包装流
- 数据的交换按块(缓冲区)交换
- 关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也会相应关闭内层节点流
flush()
:调用该方法,手动将buffer中内容写入文件- 如果是带缓冲区的流对象的
close()
方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭后不能再使用该流对象
BufferedReader br = null;
BufferedWriter bw = null;
try {
// 创建缓冲流对象:它是处理流,是对节点流的包装
br = new BufferedReader(new FileReader("d:\\IOTest\\source.txt"));
bw = new BufferedWriter(new FileWriter("d:\\IOTest\\dest.txt"));
String str;
while ((str = br.readLine()) != null) { // 循环,每次读取 source 文件的一行字符,知道读取到空行
bw.write(str); // 循环,每次写入 dest文件 一行字符串
bw.newLine(); // 写入行分隔符
}
bw.flush(); // 刷新缓冲区
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bw != null) {
bw.close(); // 关闭处理流时,会自动关闭它所包装的底层节点流
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
转换流
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("dbcp.txt");
fos = new FileOutputStream("dbcp5.txt");
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
InputStreamReader isr = null;
OutputStreamWriter osw = null;
try {
// 实现 转码 功能
isr = new InputStreamReader(fis, "GBK");
osw = new OutputStreamWriter(fos, "GBK");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
BufferedReader bufferedReader = new BufferedReader(isr);
BufferedWriter bufferedWriter = new BufferedWriter(osw);
String str = null;
while (true) {
try {
if ((str = bufferedReader.readLine()) == null) break; //循环,每次读取 dbcp 文件的一行字符,直到读取到空行
bufferedWriter.write(str); // 循环,每次写入 dbcp5 文件 一行字符串
bufferedWriter.newLine();
bufferedWriter.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
try {
if (bufferedWriter != null) bufferedWriter.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
if (bufferedReader != null) bufferedReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
标准输入/输出流(会阻塞)
System.out.println("请输入信息(退出输入e或exit):");
// 把"标准"输入流(键盘输入)这个字节流包装成字符流,再包装成缓冲流
BufferedReader bufferedReader1 = new BufferedReader(new InputStreamReader(System.in));
String s = null;
try {
while ((s = bufferedReader1.readLine()) != null) { // 读取用户输入的一行数据 --> 阻塞程序
if ("e".equalsIgnoreCase(s) || "exit".equalsIgnoreCase(s)) {
System.out.println("安全退出!!");
break;
}
// 将读取到的整行字符串转成大写输出
System.out.println("-->:" + s.toUpperCase());
System.out.println("继续输入信息");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedReader1 != null) {
bufferedReader1.close(); // 关闭过处理流时,会自动关闭它包装的底层节点流
}
} catch (IOException e) {
e.printStackTrace();
}
}
打印流
PrintStream ps = null;
try {
FileOutputStream fileOutputStream = new FileOutputStream(new File("D:\\IO\\text.txt"));
// 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
ps = new PrintStream(fileOutputStream, true);
if (ps != null) {// 把标准输出流(控制台输出)改成 text 文件
System.setOut(ps);
}
for (int i = 0; i <= 255; i++) { // 输出ASCII字符 到 text 文件
System.out.print((char) i);
if (i % 50 == 0) { // 每50个数据一行
System.out.println(); // 换行
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (ps != null) {
ps.close();
}
}
数据流
DataOutputStream dos = null;
DataInputStream dis = null;
try { // 创建连接到指定文件的数据输出流对象
dos = new DataOutputStream(new FileOutputStream("destData.dat"));
dos.writeUTF("我爱北京天安门"); // 写UTF字符串
dos.writeBoolean(false); // 写入布尔值
dos.writeLong(1234567890L); // 写入长整数
System.out.println("写文件成功,直接将基本数据类型和String类型数据写入到文件中");
dis = new DataInputStream(new FileInputStream("destData.dat"));
String stringInfo = dis.readUTF();
boolean booleanInfo = dis.readBoolean();
long longInfo = dis.readLong();
System.out.println("读文件成功,直接将文件中的基本数据类型和String类型数据读取到内存");
} catch (IOException e) {
e.printStackTrace();
} finally { // 关闭流对象
try {
if (dos != null) {
// 关闭处理时,会自动关闭它包装的底层节点流
dos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
对象流
序列化
使用对象流序列化对象
- 一个类的对象能否被序列化,除了其本身需要满足需求外,该类的成员属性也需要满足,这个类的对象才能序列化
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("data.txt"));
ois = new ObjectInputStream(new FileInputStream("data.txt"));
} catch (IOException e) {
throw new RuntimeException(e);
}
SerializeTest serializeTest = new SerializeTest("韩梅梅", 1);
try {
oos.writeObject(serializeTest);
oos.flush(); // 注意每写出一次,操作flush()一次
SerializeTest serializeTest2 = (SerializeTest)ois.readObject();
System.out.println(serializeTest2);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
try {
if (oos != null) oos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
RandomAccessFile 随机存取文件流
文件断点续传功能
- 可以用
RandomAccessFile
这个类,来实现一个多线程断点下载的功能,用过下载工具的朋友们都知道,下载前都会建立两个临时文件,一个是与被下载文件大小相同的空文件,另一个是记录文件指针的位置文件,每次暂停的时候,都会保存上一次的指针,然后断点下载的时候,会继续从上一次的地方下载,从而实现断点下载或上传的功能
RandomAccessFile 使用
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile("test.txt", "rw");
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
byte [] b = new byte[1024];
int off = 0;
int len = 5;
try {
raf.seek(5); // 将文件记录指针移动到 文件开头的第 5 个字节 的位置
raf.read(b, off, len); // 从第 5 个字节 开始,读取 5 个字节到字节数组 b 中
String stringRead = new String(b, 0, len);
System.out.println(stringRead);
raf.seek(0); // 将文件记录指针移动到 文件开头 的位置
raf.write(b); // 将 字节数组中的内容从文件开头 写入 到文件中,原来位置的内容被覆盖
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
if (raf != null)raf.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
NIO
随着 JDK 7 的发布,Java对NIO进行了极大的扩展,增强了对文件处理和文件系统特性的支持,以至于我们称他们为 NIO.2
Paths 工具类常用方法
Path 接口的实现类常用方法
Files 工具类常用方法
实际IO操作
- 一般通过第三方的jar包commons-io中的API实现对IO的操作