文章目录
一、File 类
- 如果希望在程序中操作文件和目录,都可以通过 File 类来完成;如果需要访问文件内容本身,则需要使用输入/输出流;
1. 访问文件和目录
- File 类可以使用文件路径字符串来创建 File 实例;
- 常用的方法:
①访问文件名相关的方法;
②文件检测相关的方法;
③获取常规文件信息;
④文件操作相关方法;
⑤目录操作相关方法;
2. 文件过滤器
- 在 File 类的 list() 方法中可以接收一个 FilenameFilter 参数,通过该参数可以只列出符合条件的文件;
二、 理解 Java 的 IO 流
1. 流的分类
- 输入流和输出流:
输入流:主要由 InputStream 和 Reader 作为基类;
输出流:主要由 OutputStream 和 Writer 作为基类; - 字节流和字符流:
字节流:数据单元是8位的字节,由 InputStream 和 OutputStream 作为基类;
字符流:数据单元是16位的字符,主要由 Reader 和 Writer 作为基类; - 节点流和处理流:
节点流:也被称为低级流,可以从/向一个特定的 IO 设备读/写数据的流;
处理流:也被称为高级流,用于对一个已存在的流进行连接或封装;
2. 流的概念模型
- Java 把所有设备里的有序数据抽象成流模型;
InputStream / Reader | 输入流 | 前者是字节输入流,后者是字符输入流 |
---|---|---|
OutputStream / Writer | 输出流 | 前者是字节输出流,后者是字符输出流 |
- 处理流的功能主要体现在:
①性能的提高,以增加缓冲的方式来提高输入输出效率;
②操作的便捷,提供便捷方法一次输入输出大量的内容;
三、字节流和字符流
- InputStream 和 Reader 都是抽象类,本身不能创建实例,分别有一个用于读取文件的输入流:FileInputStream 和 FileReader;
① 用字节输入流实现文件的读取:
public class InputStreamTest {
public static void main(String[] args) throws IOException {
//创建字节输入流
FileInputStream fis = new FileInputStream("F:\\java\\JavaTest.txt");
//创建长度为1024的“竹筒”
byte[] bbuf = new byte[1024];
//用于保存实际读取的字节数
int hasRead = 0;
//使用循环来重复“取水”过程
while ((hasRead = fis.read(bbuf)) > 0){
//将字节数组转换成字符串输入
System.out.println(new String(bbuf, 0, hasRead));
}
//关闭文件输入流
fis.close();
}
}
② 用字符输入流实现文件的读取:
public class ReaderTest {
public static void main(String[] args) throws IOException {
try (
//创建字符输入流
FileReader fr = new FileReader("F:\\java\\JavaTest.txt"))
{
//创建一个长度为32的“竹筒”
char[] cbuf = new char[128];
//用于保存实际读取的字符数
int hasRead = 0;
//使用循环重复“取水”过程
while ((hasRead = fr.read(cbuf)) > 0){
//将字符数组转换成字符串输入
System.out.println(new String(cbuf, 0, hasRead));
}
}
catch (IOException e){
e.printStackTrace();
}
}
}
- OutputStream 和 Writer用法和上面相似;
① 使用字节输出流 实现文件的复制:
public class OutputStreamTest {
public static void main(String[] args) {
try(
//创建字节输入流
FileInputStream fis = new FileInputStream("F:\\java\\JavaTest.txt");
//创建字节输出流
FileOutputStream fos = new FileOutputStream("F:\\java\\JavaCopy.txt"))
{
byte[] bbuf = new byte[128];
int hasRead = 0;
//循环从输入流中取出数据
while ((hasRead = fis.read(bbuf)) > 0){
//每读取一次,即写入文件输出流,读多少写多少
fos.write(bbuf, 0, hasRead);
}
}
catch (IOException e){
e.printStackTrace();
}
}
}
四、输入 / 输出流体系
1. 处理流的用法
- 它可以隐藏底层设备上节点流的差异,并对外提供更加方便的输入输出方法;
- 使用 PrintStream 处理流来包装 OutputStream;
//将 println 中的内容写入文件
public class PrintStreamTest {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("F:\\java\\JavaCopy.txt");
PrintStream ps = new PrintStream(fos))
{
//使用 PrintStream 执行输出
ps.println("普通字符串");
//直接使用 PrintStream 输出对象
ps.println(new PrintStreamTest());
}
catch (IOException e){
e.printStackTrace();
}
}
}
2. 输入/输出流体系
- 通常来说,字节流的功能比字符流功能强大,
如果进行输入/输出的内容是文本内容,则应该考虑用字符流;
如果进行输入/输出的内容是二进制内容,则应该考虑用字节流;
3. 转换流
- 用于实现:将字节流转换为字符流;
InputStreamReader:将字节输入流转换成字符输入流;
OutputStreamReader:将字节输出流转换成字符输出流; - 普通的 Reader 读取数据仍然不方便,可以将普通的 Reader 再次包装成 BufferReader,用 readLine() 方法可以一次读取一行内容;
public class KeyinTest {
public static void main(String[] args) {
try (
//将 System.in 对象转换成 Reader 对象
InputStreamReader reader = new InputStreamReader(System.in);
//将普通的 Reader 包装成 BufferedReader
BufferedReader br = new BufferedReader(reader))
{
String line = null;
//用循环逐行读取
while ((line = br.readLine()) != null){
//如果读取的字符串为“exit”,则程序退出
if (line.equals("exit")){
System.exit(1);
}
//打印读取的内容
System.out.println("输入内容为:" + line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
分析:BufferedReader 流具有缓冲功能,它可以一次读取一行文本(以换行符为标志);以上代码运行时,在控制台输入字符时,只有按下回车键,程序才会打印刚才输入的内容;
4. 推回输入流
五、重定向标准输入/输出
- 当程序通过 System.in 来获取输入时,实际是从键盘读入数据;
通过 System.out 执行输出时,程序总是输出到屏幕; - System 类里提供了三个重定向标准输入/输出的方法:
static void setErr(PrintStream err):重定向标准错误输出流;
static void setIn(InputStream in):重定向标准输入流;
static void setOut(PrintStream out):重定向标准输出流;
- 下面程序通过重定向标准输出流,将输出重定向到文件输出,而不是在屏幕上输出;
public class RedirectOut {
public static void main(String[] args) {
try(
//一次性创建 PrintStream 输出流
PrintStream ps = new PrintStream(new FileOutputStream("F:\\java\\JavaCopy.txt")))
{
//将标准输出重定向到 ps 输出流
System.setOut(ps);
//向标准输出 输出一个字符串
System.out.println("普通字符串");
//向标准输出 输出一个对象
System.out.println(new RedirectOut());
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
- 下面程序通过重定向标准输入,将输入重定向到指定文件,而不是键盘输入;
public class Redirectln {
public static void main(String[] args) {
try(
FileInputStream fis = new FileInputStream("F:\\java\\JavaCopy.txt"))
{
//将标准输入重定向到 fis 输入流
System.setIn(fis);
//使用 System.in 创建 Scanner 对象,用于获取标准输入
Scanner sc = new Scanner(System.in);
//增加下一行只把回车作为分隔符
sc.useDelimiter("\n");
//判断是否还有下一个输入项
while (sc.hasNext()){
//输出输入项
System.out.println("键盘输入的内容是:" + sc.next());
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
六、Java 虚拟机读写其他进程的数据
七、RandomAccessFile
- RandomAccessFile 是 Java 输入/输出流体系中功能最丰富的的文件内容访问类,它提供了众多的方法来访问文件内容,它既可以读取文件内容,也可以向文件输出数据;
- 与普通的输入/输出不同的是,RandomAccessFile 支持“随机访问”的方式,程序可以直接跳转到文件的任意地方来读写数据;
八、对象序列化
1. 序列化的含义和意义
- 序列化机智允许将实现序列化的 Java 对象转化为字节序列,这些字节序列可以保存到磁盘上,或者通过网络传输,以备以后重新恢复成原来的对象;