1 File类
1.1 概述
-
FIle类是java.io包下代表和平台无关的文件和目录,换言之,如果希望在程序中操作文件和目录都可以使用File类来完成,File类能新建、删除、重命名文件和目录。
-
在API中File的解释是
文件和目录路径名的抽象表示形式
,即File类是文件或目录的路径,而不是文件本身,因此File类不能直接访问文件内容本身,如果需要访问文件内容本身,就需要使用IO流了。 -
File类代表磁盘或网络中某个文件或目录的路径名称,例如:
c:/美女.jpg
。 -
不能直接通过File对象读取和写入数据,如果要操作数据,需要IO流。
1.2 File的构造方法
- 通过将给定的路径名称字符串转换为抽象路径名为创建新的File实例:
public File(String pathname) {}
- 通过父路径名字符串和子路径名字符串创建新的File实例:
public File(String parent, String child) {}
- 通过父路径名和子路径名字符串创建新的File实例:
public File(File parent, String child) {}
- 通过将给定的
file:
URI到一个抽象路径名创建一个新的File实例:
public File(URI uri) {}
- 示例:
package top.open1024.file.demo1;
import java.io.File;
/**
* @author open1024
* @version 1.0
* @since 2021-10-03 08:25
*/
public class Test {
public static void main(String[] args) {
// 通过将给定的路径名称字符串转换为抽象路径名为创建新的File实例
File file = new File("D:\\develop\\Java\\jdk1.8.0_131\\bin\\javac.exe");
System.out.println("file = " + file);
}
}
- 示例:
package top.open1024.file.demo2;
import java.io.File;
/**
* @author open1024
* @version 1.0
* @since 2021-10-03 08:30
*/
public class Test {
public static void main(String[] args) {
// 通过父路径名字符串和子路径名字符串创建新的File实例
File file = new File("D:\\develop\\Java\\jdk1.8.0_131\\bin", "javac.exe");
System.out.println("file = " + file);
}
}
- 示例:
package top.open1024.file.demo3;
import java.io.File;
/**
* @author open1024
* @version 1.0
* @since 2021-10-03 08:31
*/
public class Test {
public static void main(String[] args) {
File parent = new File("D:\\develop\\Java\\jdk1.8.0_131\\bin");
String child = "javac.exe";
File file = new File(parent, child);
System.out.println("file = " + file);
}
}
- 示例:
package top.open1024.file.demo4;
import java.io.File;
import java.net.URI;
/**
* @author open1024
* @version 1.0
* @since 2021-10-03 08:33
*/
public class Test {
public static void main(String[] args) {
URI uri = URI.create("file:///D:/develop/Java/jdk1.8.0_131/bin/javac.exe");
File file = new File(uri);
System.out.println("file = " + file);
}
}
1.3 File的常用方法
1.3.1 获取文件和目录基本信息的方法
- 返回由此File表示的文件或目录的名称:
public String getName() {}
- 返回由此File表示的文件的长度:
ublic long length() {}
- 将此File转换为路径名字符串:
public String getPath() {}
- 示例:
package top.open1024.file.demo5;
import java.io.File;
import java.time.Instant;
/**
* @author open1024
* @version 1.0
* @since 2021-10-03 08:54
*/
public class Test {
public static void main(String[] args) {
File file = new File("D:\\develop\\Java\\jdk1.8.0_131\\bin\\javac.exe");
// 返回由此File表示的文件或目录的名称
String name = file.getName();
System.out.println("name = " + name); // name = javac.exe
// 返回由此File表示的文件的长度
long length = file.length();
System.out.println("length = " + length); // length = 15904
// 将此File转换为路径名字符串
String path = file.getPath();
System.out.println("path = " + path); // path = D:\develop\Java\jdk1.8.0_131\bin\javac.exe
long lastModified = file.lastModified();
System.out.println("lastModified = " + lastModified); // lastModified = 1626956893615
}
}
1.3.2 路径
- 将此File实例转换为路径名称字符串:
public String getPath() {}
- 返回此File实例的绝对路径名字符串:
public String getAbsolutePath() {}
- 返回此File实例所对应的规范路径名:
public String getCanonicalPath() throws IOException {}
- 示例:
package top.open1024.file.demo6;
import java.io.File;
import java.io.IOException;
/**
* @author open1024
* @version 1.0
* @since 2021-10-03 09:16
*/
public class Test {
public static void main(String[] args) throws IOException {
File file = new File("D:\\develop\\Java\\jdk1.8.0_131\\bin\\javac.exe");
// 将此File实例转换为路径名称字符串
String path = file.getPath();
System.out.println("path = " + path); // D:\develop\Java\jdk1.8.0_131\bin\javac.exe
// 返回此File实例的绝对路径名字符串
String absolutePath = file.getAbsolutePath();
System.out.println("absolutePath = " + absolutePath); // D:\develop\Java\jdk1.8.0_131\bin\javac.exe
// 返回此File实例所对应的规范路径名
String canonicalPath = file.getCanonicalPath();
System.out.println("canonicalPath = " + canonicalPath); // D:\develop\Java\jdk1.8.0_131\bin\javac.exe
}
}
1.3.3 判断功能的方法
- 判断File实例表示的文件或目录是否存在:
public boolean exists() {}
- 判断File实例表示的是否是文件:
public boolean isFile() {
- 判断File实例表示的是否是目录:
public boolean isDirectory() {}
- 判断File构造方法中的路径是否是绝对路径:
public boolean isAbsolute() {}
- 示例:
package top.open1024.file.demo7;
import java.io.File;
/**
* @author open1024
* @version 1.0
* @since 2021-10-03 09:23
*/
public class Test {
public static void main(String[] args) {
File file = new File("D:\\develop\\Java\\jdk1.8.0_131\\bin\\javac.exe");
boolean exists = file.exists();
System.out.println("exists = " + exists); // exists = true
boolean flag = file.isFile();
System.out.println("flag = " + flag); // flag = true
flag = file.isDirectory();
System.out.println("flag = " + flag); // flag = false
boolean absolute = file.isAbsolute();
System.out.println("absolute = " + absolute); // absolute = true
}
}
1.3.4 创建和删除的方法
- 当且仅当具有该名称的文件尚不存在时,创建一个新的空文件:
public boolean createNewFile() throws IOException {}
- 删除由此File表示的文件或目录(只能删除空目录):
public boolean delete() {}
- 创建由此File表示的目录:
public boolean mkdir() {}
- 创建由此File表示的目录(包含父目录):
public boolean mkdirs() {}
- 示例:
package top.open1024.file.demo8;
import java.io.File;
import java.io.IOException;
/**
* @author open1024
* @version 1.0
* @since 2021-10-03 09:45
*/
public class Test {
public static void main(String[] args) throws IOException {
// 文件的创建
File file = new File("aaa.txt");
System.out.println("是否存在:" + file.exists()); // 是否存在:false
System.out.println("是否创建:" + file.createNewFile()); // 是否创建:true
System.out.println("是否存在:" + file.exists()); // 是否存在:true
// 目录的创建
File file2 = new File("newDir");
System.out.println("是否存在:" + file2.exists()); // 是否存在:false
System.out.println("是否创建:" + file2.mkdir()); // 是否创建:true
System.out.println("是否存在:" + file2.exists()); // 是否存在:true
// 创建多级目录
File file3 = new File("newDira/newDirb");
System.out.println("是否存在:" + file3.exists()); // 是否存在:false
System.out.println("是否创建:" + file3.mkdirs()); // 是否创建:true
System.out.println("是否存在:" + file3.exists()); // 是否存在:true
// 文件的删除
System.out.println(file.delete()); // true
// 目录的删除
System.out.println(file2.delete()); // true
System.out.println(file3.delete()); // true
}
}
1.4 递归实现多级目录操作
1.4.1 相关方法
- 返回一个String数组,表示该File目录中的所有子文件或目录:
public String[] list() {}
- 返回一个File数组,表示该File目录中的所有的子文件或目录:
public File[] listFiles() {}
- 返回所有满足指定过滤器的文件和目录的String数组:
public String[] list(FilenameFilter filter) {}
- 返回所有满足指定过滤器的文件和目录的File数组:
public File[] listFiles(FilenameFilter filter) {}
1.4.2 递归打印多级目录
-
分析:多级目录的打印。遍历之前,无从知道到底有多少级目录,所以我们可以使用递归实现。
-
示例:
package top.open1024.file.demo9;
import java.io.File;
/**
* @author open1024
* @version 1.0
* @since 2021-10-03 15:45
*/
public class Test {
public static void main(String[] args) {
print(new File("D:\\develop\\Java\\jdk1.8.0_131"));
}
public static void print(File file) {
if (null != file && file.isDirectory()) {
File[] files = file.listFiles();
if (null != files) {
for (File f : files) {
print(f);
}
}
}
System.out.println(file);
}
}
1.4.3 递归打印某目录下(包括子目录)中所有满足条件的文件
- 示例:列出所有".java"文件
package top.open1024.file.demo10;
import java.io.File;
import java.io.FilenameFilter;
/**
* @author open1024
* @version 1.0
* @since 2021-10-03 16:12
*/
public class Test {
public static void main(String[] args) {
print(new File("D:\\project\\java-core"));
}
public static void print(File file) {
if (null != file && file.isDirectory()) {
File[] files = file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".java") || new File(dir, name).isDirectory();
}
});
if (null != files) {
for (File f : files) {
if (f.isFile()) {
System.out.println(f);
}
print(f);
}
}
}
}
}
2 IO流
2.1 概述
-
I/O是Input和Output的缩写,IO技术是非常实用的技术,用于
处理设备之间的数据传输
,如:读写文件、网络通讯等。 -
Java程序中,对于数据的输入/输出操作以
流stream
的方式进行。 -
java.io包下提供了各种“流”类和接口,用于获取不同种类的数据,并通过
标准的方法
输入或输出数据。
2.2 Java IO原理
-
输入(Input):读取外部数据(磁盘、U盘等存储设备的数据)到程序(内存)中。
-
输出(Output):将程序(内存)数据输出到磁盘、U盘等存储设备中。
2.3 IO的分类
-
根据流的流向分类:
-
- 输入流:将数据从
其他设备
上读取到内存
中的流。以InputStream、Reader结尾。
- 输入流:将数据从
-
- 输出流:将数据从
内存
中写出到其他设备
上的流。以OutputStream和Writer结尾。
- 输出流:将数据从
-
根据数据的类型分类:
-
- 字节流:以字节为单位,读写数据的流。以InputStream和OutputStream结尾。
-
- 字符流:以字符为单位,读写数据的流。以Reader和Writer结尾。
-
根据IO刘的角色不同分类:
-
- 节点流:可以从或向一个特定的地方(节点)读取数据。如FileReader。
-
- 处理流:对一个已经存在的流进行连接和封装,通过锁封装的流的功能实现数据读写。如:BufferReader,处理流的构造方法总是要带一个其它的流对象做参数。一个流对象经过多次其它流的多次包装,称为流的链接。
-
常用的节点流:
-
- 文件:FileInputStream、FileOutputStrean、FileReader、FileWriter文件进行处理的节点流。
-
- 字符串:StringReader、StringWriter对字符串进行处理的节点流。
-
- 数组: ByteArrayInputStream、ByteArrayOutputStream、CharArrayReader、CharArrayWriter对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)。
-
- 管道:PipedInputStream、PipedOutputStream、PipedReader、PipedWriter对管道进行处理的节点流。
-
常用处理流:
-
- 缓冲流:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter---增加缓冲功能,避免频繁读写硬盘。
-
- 转换流:InputStreamReader、OutputStreamReader---实现字节流和字符流之间的转换。
-
- 数据流:DataInputStream、DataOutputStream -提供读写Java基础数据类型功能。
-
- 对象流:ObjectInputStream、ObjectOutputStream--提供直接读写Java对象功能。
2.4 四大顶级抽象流父类
输入流 | 输出流 | |
---|---|---|
字节流 | 字节输入流InputStream | 字节输出流OutputStream |
字符流 | 字符输入流Reader | 字符输出流Writer |
2.5 字节流
2.5.1 概述
-
一切文件数据(文本、图片、视频等)在存储的时候,都是以二进制的形式保存的,都是一个个的字节;同样,在传输的时候依然如此。所以,字节流可以传输任意文件数据。
-
在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输始终是二进制数据。
2.5.3 OutputStream
-
java.io.OutputStream
抽象类是表示字节输出流的所有类的超类,将指定的字节信息输出的目的地。它定义了字节输出流的基本共性的功能方法。 -
写入单个字节:
public abstract void write(int b) throws IOException;
- 写入字节数组:
public void write(byte b[]) throws IOException {}
- 写入字节数组的一部分,从offset开始,一共len个:
public void write(byte b[], int off, int len) throws IOException {}
- 刷新流:
public void flush() throws IOException {}
- 关闭流:
public void close() throws IOException {}
注意:当完成流的操作的时候,必须调用close()方法,释放系统资源。
2.5.4 FileOutputStream
-
FileOutputStream是OutputStream的子类,FileOutputStream是文件输出流,用于将数据写出到文件中。
-
构造方法:
-
创建文件输出流以写入由指定的 File对象表示的文件:
public FileOutputStream(File file) throws FileNotFoundException {}
- 创建文件输出流以指定的名称写入文件:
public FileOutputStream(String name) throws FileNotFoundException {}
注意:当创建FileOutputStream流对象的时候,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件;如果有这个文件,会覆盖这个文件的数据。
-
数据追加:
-
创建文件输出流以写入由指定的 File对象表示的文件:
public FileOutputStream(String name, boolean append)
throws FileNotFoundException
{}
- 创建文件输出流以指定的名称写入文件:
public FileOutputStream(File file, boolean append)
throws FileNotFoundException
{}
-
换行写出:windows系统中的换行符号是
\r\n
。 -
示例:写出单个字节
package top.open1024.io.demo1;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* @author open1024
* @version 1.0
* @since 2021-10-04 06:04
*/
public class Test {
public static void main(String[] args) {
OutputStream os = null;
try {
// 使用文件名称创建流对象
os = new FileOutputStream("d:/demo.txt");
// 注意:虽然参数为int类型的四个字节,但是只会保留一个字节的信息写出
os.write(97); // 写出第1个字节
os.write(98); // 写出第2个字节
os.write(99); // 写出第3个字节
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != os) {
try {
// 关闭资源
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- 示例:写出字节数组
package top.open1024.io.demo2;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
/**
* @author open1024
* @version 1.0
* @since 2021-10-04 06:44
*/
public class Test {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
OutputStream os = new FileOutputStream("d:/demo.txt");
os.write("open1024".getBytes(StandardCharsets.UTF_8));
// 关闭资源
os.close();
}
}
- 示例:写出指定长度的字节数组
package top.open1024.io.demo3;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
/**
* @author open1024
* @version 1.0
* @since 2021-10-04 06:53
*/
public class Test {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
OutputStream os = new FileOutputStream("d:/demo.txt");
os.write("abcd".getBytes(StandardCharsets.UTF_8), 2, 1);
// 关闭资源
os.close();
}
}
- 示例:数据追加
package top.open1024.io.demo4;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
/**
* @author open1024
* @version 1.0
* @since 2021-10-04 06:59
*/
public class Test {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象,append为true,表示追加写出
OutputStream os = new FileOutputStream("d:/demo.txt", true);
os.write("abcd".getBytes(StandardCharsets.UTF_8), 1, 3);
// 关闭资源
os.close();
}
}
- 示例:换行写出
package top.open1024.io.demo5;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* @author open1024
* @version 1.0
* @since 2021-10-04 07:02
*/
public class Test {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象,append为true,表示追加写出
OutputStream os = new FileOutputStream("d:/demo.txt", true);
char[] chs = {'a', 'b', 'c', 'd'};
for (char ch : chs) {
os.write(ch);
os.write("\r\n".getBytes());
}
// 关闭资源
os.close();
}
}
2.5.5 IO异常处理
- 示例:
package top.open1024.io.demo1;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* @author open1024
* @version 1.0
* @since 2021-10-04 06:04
*/
public class Test {
public static void main(String[] args) {
OutputStream os = null;
try {
// 使用文件名称创建流对象
os = new FileOutputStream("d:/demo.txt");
// 注意:虽然参数为int类型的四个字节,但是只会保留一个字节的信息写出
os.write(97); // 写出第1个字节
os.write(98); // 写出第2个字节
os.write(99); // 写出第3个字节
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != os) {
try {
// 关闭资源
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- JDK7的新特性try-with-resources:
try(需要关闭的资源对象的声明){
业务逻辑代码
}catch(异常类型 e){
处理异常代码
}catch(异常类型 e){
处理异常代码
}
-
没有finally,也不需要程序员去关闭资源对象,无论是否发生异常,都会关闭资源对象。
-
实现了AutoCloseable或Closeable接口的类才可以自动进行资源关闭。
-
示例:JDK7的新特性try-with-resources
package top.open1024.io.demo6;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* @author open1024
* @version 1.0
* @since 2021-10-04 07:22
*/
public class Test {
public static void main(String[] args) {
// 使用文件名称创建流对象,append为true,表示追加写出
try (OutputStream os = new FileOutputStream("d:/demo.txt", true)) {
char[] chs = {'a', 'b', 'c', 'd'};
for (char ch : chs) {
os.write(ch);
os.write("\r\n".getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.5.6 InputStream
-
InputStream抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。
-
读取单个字节:
public abstract int read() throws IOException;
- 读取字节数组:
public int read(byte b[]) throws IOException {}
- 读取字节数组,从offset开始,len长度:
public int read(byte b[], int off, int len) throws IOException {}
- 关闭流:
public void close() throws IOException {}
2.5.7 FileInputStream
-
java.io.FileInputStream
类是文件输入流,从文件中读取字节。 -
构造方法:
-
通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的File对象file命名:
public FileInputStream(File file) throws FileNotFoundException {}
- 通过打开与实际文件的连接来创建一个FileInputStream ,该文件由文件系统中的路径名name命名:
public FileInputStream(String name) throws FileNotFoundException {}
- 示例:读取单个字节,读取到文件末尾,返回
-1
package top.open1024.io.demo7;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author open1024
* @version 1.0
* @since 2021-10-04 16:05
*/
public class Test {
public static void main(String[] args) {
try (InputStream is = new FileInputStream("d:/demo.txt")) {
int len;
while ((len = is.read()) != -1) {
System.out.println((char)len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 示例:读取字节数组,读取到文件末尾,返回
-1
package top.open1024.io.demo8;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author open1024
* @version 1.0
* @since 2021-10-04 16:13
*/
public class Test {
public static void main(String[] args) {
try (InputStream is = new FileInputStream("d:/demo.txt")) {
byte[] bytes = new byte[1024];
int len;
while ((len = is.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.5.8 文件复制
- 文件复制的本质是字节的搬家。
- 示例:
package top.open1024.io.demo9;
import java.io.*;
/**
* @author open1024
* @version 1.0
* @since 2021-10-04 19:46
*/
public class Test {
public static void main(String[] args) {
try (InputStream is = new FileInputStream("C:\\Users\\xudaxian\\Pictures\\枪械少女.jpg");
OutputStream os = new FileOutputStream("C:\\Users\\xudaxian\\Pictures\\枪械少女1.jpg")) {
byte[] bytes = new byte[1024];
int len;
while ((len = is.read(bytes)) != -1) {
os.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.6 字符流
2.6.1 概述
- 当使用字节流读取文本文件的时候,可能会有一个小问题:就是遇到中文字符的时候,可能显示不完整,那是因为一个中文字符可能占用多个字节存储。所以,Java提供了一些字符流,以字符为单位读写数据,专门用于处理文本文件。
2.6.2 Reader
-
java.io.Reader
抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。 -
关闭此流并释放与此流相关联的任何系统资源:
abstract public void close() throws IOException;
- 读取一个字符:
public int read() throws IOException
- 读取字符数组:
public int read(char cbuf[]) throws IOException {}
- 读取从offset索引开始,len长度的字符数组:
abstract public int read(char cbuf[], int off, int len) throws IOException;
2.6.3 FileReader
- java.io.FileReader类是读取字符文件的类。构造的时候使用系统默认的字符编码和默认字节缓冲区。
字符编码:字节和字符的对应规范。windows系统的中文编码默认是GBK。
-
构造方法:
-
创建一个新的FileReader,给定要读取的File对象:
public FileReader(File file) throws FileNotFoundException {}
- 创建一个新的FileReader,给定要读取的文件的名称:
public FileReader(String fileName) throws FileNotFoundException {}
- 示例:读取单个字符
package top.open1024.io.demo11;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/**
* @author open1024
* @version 1.0
* @since 2021-10-04 21:58
*/
public class Test {
public static void main(String[] args) {
try (Reader reader = new FileReader("d:/demo.txt")) {
int b;
while ((b = reader.read()) != -1) {
System.out.println((char)b);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 示例:读取字符数组
package top.open1024.io.demo12;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/**
* @author open1024
* @version 1.0
* @since 2021-10-05 08:37
*/
public class Test {
public static void main(String[] args) {
try (Reader reader = new FileReader("d:/demo.txt")) {
char[] buffer = new char[1024];
int len;
while ((len = reader.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.6.4 Writer
-
java.io.Writer抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地,它定义了字符输出流的基本共性功能方法。
-
写入单个字符:
public void write(int c) throws IOException {}
- 写入字符数组:
public void write(char cbuf[]) throws IOException {}
- 写入从offset索引开始,len长度的字符数组:
abstract public void write(char cbuf[], int off, int len) throws IOException;
- 写入字符串:
public void write(String str) throws IOException {}
- 写入从offset索引开始,len长度的字符串:
public void write(String str, int off, int len) throws IOException {}
- 刷新流:
abstract public void flush() throws IOException;
- 关闭流:
abstract public void close() throws IOException;
2.6.5 FileWriter
-
java.io.FileWriter
类是写出字符到文本的类。构造的时候使用系统默认的字符编码和默认字节缓冲区。 -
构造方法:
-
创建一个新的FileWriter,给定要读取的File对象:
public FileWriter(String fileName) throws IOException {}
- 创建一个新的FileWriter,给定要读取的文件的名称:
public FileWriter(File file) throws IOException {}
- 创建一个新的FileWriter,给定要读取的File对象,追加内容:
public FileWriter(String fileName, boolean append) throws IOException {}
- 创建一个新的FileWriter,给定要读取的文件的名称,追加内容:
public FileWriter(File file, boolean append) throws IOException {}
- 示例:写出单个字符
package top.open1024.io.demo13;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
/**
* @author open1024
* @version 1.0
* @since 2021-10-05 08:48
*/
public class Test {
public static void main(String[] args) {
try (Writer writer = new FileWriter("d:/demo.txt")) {
writer.write(97);
writer.write('a');
writer.write('b');
writer.write('c');
writer.write('许');
writer.write('大');
writer.write('仙');
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 示例:写出字符数组
package top.open1024.io.demo14;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
/**
* @author open1024
* @version 1.0
* @since 2021-10-05 08:50
*/
public class Test {
public static void main(String[] args) {
try (Writer writer = new FileWriter("d:/demo.txt")) {
writer.write("open1024".toCharArray());
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 示例:写出字符串
package top.open1024.io.demo15;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
/**
* @author open1024
* @version 1.0
* @since 2021-10-05 08:50
*/
public class Test {
public static void main(String[] args) {
try (Writer writer = new FileWriter("d:/demo.txt")) {
writer.write("open1024");
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.7 缓冲流
2.7.1 概述
-
缓冲流,也叫高效流,按照数据类型分类:
-
- 字节缓冲流:BufferedOutputStream、BufferedInputStream。
-
- 字符缓冲流:BufferedReader、BufferedWriter。
-
缓冲流会在内部创建一个缓冲区数组,缺省使用8192个字节(8kb)的缓冲区。
public class BufferedInputStream extends FilterInputStream {
private static int DEFAULT_BUFFER_SIZE = 8192;
...
}
-
缓冲流的基本原理:
-
- 当读取数据的时候,数据按块读入缓冲区,其后的读操作则直接访问缓冲区。
-
- 当使用BufferedInputStream读取字节文件时,BufferedInputStream会一次性的从文件中读取8192个,存储在缓冲区中,直到缓冲区中装满了,才重新从文件中读取下一个8192个字节数组。
-
- 向流中写入字节的时候,不会直接写到文件中,先写到缓冲区中直到缓冲区中写满,BufferedOutputStream才会将缓冲区中的数据一次性的写到文件里。使用flush()方法可以强制将缓冲区的内容全部写入输出流。
-
关闭流的顺序和打开流的顺序相反,只需要关闭最外层流即可,因为关闭最外层流的同时也会关闭对应的内层流。
-
flush()方法的使用:手动将buffer中内容写入文件。
-
如果是带缓冲区的流对象的close()方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭后不能再写出。
2.7.2 字节缓冲流
- BufferedOutputStream的构造方法:
public BufferedOutputStream(OutputStream out) {}
- BufferedInputStream的构造方法:
public BufferedInputStream(InputStream in) {}
- 示例:
package top.open1024.io.demo10;
import java.io.*;
/**
* @author open1024
* @version 1.0
* @since 2021-10-04 21:45
*/
public class Test {
public static void main(String[] args) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:/demo.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:/test.txt"))) {
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.7.3 字符缓冲流
- BufferedReader的构造方法:
public BufferedReader(Reader in) {}
- BufferedReader的特殊方法读取一行:
public String readLine() throws IOException {}
- BufferedWriter的构造方法:
public BufferedWriter(Writer out) {}
- BufferedWriter的特殊方法写入换行符:
public void newLine() throws IOException {}
- 示例:
package top.open1024.io.demo18;
import java.io.*;
/**
* @author open1024
* @version 1.0
* @since 2021-10-05 14:55
*/
public class Test {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("d:/demo.txt"));
BufferedWriter writer = new BufferedWriter(new FileWriter("d:/test.txt"))) {
char[] buffer = new char[1024];
int len;
while ((len = reader.read(buffer)) != -1) {
writer.write(new String(buffer, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.8 转换流
2.8.1 字符编码
-
计算机中存储的信息都是使用二进制表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制数转换之后的结果。
-
按照某种规则,将字符存储到计算机中,称为
编码
。 -
按照某种规则,将存储在计算机中的二进制数据解析并显示出来,称为
解码
。 -
例如:
-
- 按照A规则存储,同样按照A规则解析,那么就能正确的显示文本符号。
-
- 按照A规则存储,按照B规则解析,就会导致乱码现象。
-
字符编码(CharacterEncoding):就是一套自然语言的字符和二进制数之间的对应规则。
-
编码表:生活中的文字和计算机中二进制的对应规则。
2.8.2 字符集
-
字符集(Charset):也称为编码表,是一个系统支持的所有字符集合,包括各个国家文字、标点符号、图形符号、数字等。
-
计算机要准确的存储和识别各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见的字符集有:ASCII字符集、CBK字符集、Unicode字符集等等。
- 可见,当指定了编码,它所对应的字符集自然就指定了,所以编码才是我们最终要关心的。
2.8.3 概述
-
转换流提供了在字节流和字符流之间的转换。
-
Java API提供了两个转换流:
-
- InputStreamReader:将InputStream转换为Reader。
-
- OutputStreamWriter:将Writer转换为OutputStream。
-
字节流中的数据都是字符时,转换为字符流操作更加高效。
-
很多时候,我们使用转换流来处理文件乱码问题,实现编码和解码的功能。
2.8.4 InputStreamReader
-
转换流
java.io.InputStreamReader
是Reader的子类,是从字节流到字符流的桥梁。它读取字节,并使用指定额字符集将其解码为字符。它的字符集可以有名称指定,也可以接受平台的默认字符集。 -
构造方法:
-
创建一个使用默认字符集的字符流:
public InputStreamReader(InputStream in) {}
- 创建一个指定字符集的字符流:
public InputStreamReader(InputStream in, Charset cs) {}
- 示例:
package top.open1024.io.demo17;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
/**
* @author open1024
* @version 1.0
* @since 2021-10-05 10:56
*/
public class Test {
public static void main(String[] args) {
try (InputStreamReader reader =
new InputStreamReader(new FileInputStream("d:/demo.txt"), StandardCharsets.UTF_8)) {
char[] chs = new char[1024];
int len;
while ((len = reader.read(chs)) != -1) {
System.out.println(new String(chs, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.8.5 OutputStreamWriter
-
转换流
java.io.OutputStreamWriter
,是Writer的子类,是从字符流到字节流的桥梁。使用指定的字符集将字符编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集。 -
构造方法:
-
创建一个使用默认字符集的字符流:
public OutputStreamWriter(OutputStream out) {}
- 创建一个指定字符集的字符流:
public OutputStreamWriter(OutputStream out, Charset cs) {}
- 示例:
package top.open1024.io.demo16;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
/**
* @author open1024
* @version 1.0
* @since 2021-10-05 10:41
*/
public class Test {
public static void main(String[] args) {
try (OutputStreamWriter writer =
new OutputStreamWriter(new FileOutputStream("d:/demo.txt"), StandardCharsets.UTF_8)) {
writer.write("open1024,你好啊");
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.9 打印流
-
字节输出流:PrintStream。
-
字符输出流:PrintWriter。
-
打印流的特点:
-
- ① 打印流负责输出打印,不关心数据源。
-
- ② 提供了一系列重载的print()或println()方法,用于多种数据类型的输出。
-
- ③ 打印流永远不会抛出IOException。
-
- ④ 打印流具有自动刷新的功能:
-
-
- 构造方法的第一个参数必须是IO流对象,第二个参数是true。
-
public PrintStream(OutputStream out, boolean autoFlush) {}
-
-
- 必须调用println()、printf()、format()中的其中一个,才会启用自动刷新。
-
-
- ⑤ System.out返回的是PrintStream的实例。
-
示例:
package top.open1024.io.demo20;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
/**
* @author open1024
* @version 1.0
* @since 2021-10-05 19:02
*/
public class Test {
public static void main(String[] args) {
try (PrintStream ps = new PrintStream(new FileOutputStream("d:/demo.txt"),true)) {
ps.println(1);
ps.println("2");
ps.println('A');
ps.println(100L);
ps.println(true);
ps.println("你好啊");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
2.10 序列化
2.10.1 概述
-
Java提供了一种
对象序列化
的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的类型
和对象中存储的属性
等信息。 -
字节序列写出到文件之后,相当于文件中
持久保存
了一个对象信息;反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
。 -
对象的数据、对象的类型和对象中存储的数据信息,都可以用来在内存中创建对象。
2.10.2 ObjectOutputStream
-
java.io.ObjectOutputStream
类是将Java对象的原始数据类型写出到文件以实现对象的持久存储。 -
构造方法:
public ObjectOutputStream(OutputStream out) throws IOException {}
-
序列化操作:
-
- ① 类必须实现
java.io.Serializable
接口,Serializable
是一个标记接口,不实现此接口的类不会使任何状态序列化或反序列化,会抛出NotSerializableException
异常(如果类中的某个属性也是引用数据类型,那么该属性如果也要序列化,必须实现Serializable
接口)。
- ① 类必须实现
-
- ② 该类的所有属性必须是可序列化的。如果有一个属性不需要序列化的,则该属性必须注明是瞬时态的,使用
transient
关键字修饰。
- ② 该类的所有属性必须是可序列化的。如果有一个属性不需要序列化的,则该属性必须注明是瞬时态的,使用
-
- ③ 静态变量的值不会序列化。
-
写出对象的方法:
public final void writeObject(Object obj) throws IOException {}
- 示例:
package top.open1024.io.demo21;
import java.io.Serializable;
/**
* @author open1024
* @version 1.0
* @since 2021-10-05 21:48
*/
public class Person implements Serializable {
private String name;
private Integer age;
public Person() {}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" + "name='" + this.name + '\'' + ", age=" + this.age + '}';
}
}
package top.open1024.io.demo21;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**
* 序列化
*
* @author open1024
* @version 1.0
* @since 2021-10-05 21:14
*/
public class Test {
public static void main(String[] args) {
Person person = new Person("张三", 12);
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt"))) {
oos.writeObject(person);
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.10.3 ObjectInputStream
-
java.io.ObjectInputStream
类是将之前使用ObjectOutputStream序列化的原始数据恢复成对象。 -
构造方法:
public ObjectInputStream(InputStream in) throws IOException {}
- 读取对象的方法:
public final Object readObject()
throws IOException, ClassNotFoundException {}
- 示例:
package top.open1024.io.demo21;
import java.io.Serializable;
/**
* @author open1024
* @version 1.0
* @since 2021-10-05 21:48
*/
public class Person implements Serializable {
private String name;
private Integer age;
public Person() {}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" + "name='" + this.name + '\'' + ", age=" + this.age + '}';
}
}
package top.open1024.io.demo21;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* 反序列化
*
* @author open1024
* @version 1.0
* @since 2021-10-05 22:12
*/
public class Test2 {
public static void main(String[] args) {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"))) {
Person person = (Person)ois.readObject();
System.out.println("person = " + person);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
评论区