Java知识点总结——IO流框架(2)


注:当编码方式和解码方式不一致时,就会出现乱码!

五、字符流


引入:3个字节相当于一个字符,当我们要读取汉字(字符)时,如果用字节流来读取的话,他是一个一个字节读取的,最终的结果是字节,而不是我们想要的字符了!

字符流的两个父类(抽象类):

  • Reader :字符输入流

常用方法:

public int read() {}

public int read(char[] c) {}

public int read(char[] b, int off, int len) {}

  • Write :字符输出流

常用方法:

public void write(int n) {}

public void write(String str) {}

public void write(char[] c) {}

文件字符流

  • FileReader ——文件字符输入流

阅读字符文件的便利课。 该类的构造函数假定默认字符编码和默认字节缓冲区大小是适当的。 要自己指定这些值,请在FileInputStream上构造一个InputStreamReader。

FileReader 是用于读取字符流。 要读取原始字节流,请考虑使用 FileInputStream 。

public class FileReader extends InputStreamReader

构造方法:

常用方法:继承父类!

public int read(char[] c);

从流中读取多个字符,讲读到内容存入c数组,返回实际读到的字符数;如果文件达到尾部,则返回-1.

【参考代码】

import java.io.FileReader;

public class FileReaderDemon {

public static void main(String[] args) throws Exception{

//1. 创建FileReader 文件字符输入流

FileReader fr = new FileReader(“d:\\hello.txt”);

//2. 读取

//2.1 单个读取

// int data = 0;

// while ((data = fr.read()) != -1){ // 读取一个字符!

// System.out.println((char)data);

// }

char[] buf = new char[1024];

int count = 0;

while((count = fr.read(buf)) != -1){

System.out.println(new String(buf, 0, count));

}

//3. 关闭

fr.close();

}

}

  • FileWriter ——文件字符输出流

public void write(String str);

一次写入多个字符,将b数组中所有字符,写入输出流;

【参考代码】

import java.io.FileWriter;

public class FileWriterDemon {

public static void main(String[] args) throws Exception{

//1. 创建FileWriter对象

FileWriter fw = new FileWriter(“d:\\write.txt”);

//2. 写入字符

String str = “防不胜防”;

for(int i = 0; i < str.length(); i ++){

fw.write(str);

fw.flush();

}

//3. 关闭

fw.close();

System.out.println(“执行完毕”);

}

}

案例:文件字符流实现文本文件复制

注: FileReader、FileWriter 只能复制文本文件,不能复制图片或者二进制文件!—— 文本文件有字符编码!

【参考代码】

import java.io.FileReader;

import java.io.FileWriter;

public class CopyDemon {

public static void main(String[] args) throws Exception{

//1. 创建FileReader FileWriter 对象

FileReader fr = new FileReader(“d:\\write.txt”);

FileWriter fw = new FileWriter(“d:\\write2.txt”);

//2. 读写

int data = 0;

while((data = fr.read()) != -1){

fw.write(data);

fw.flush();

}

//3. 关闭

fr.close();

fw.close();

System.out.println(“复制完毕!”);

}

}

字符缓冲流

字符缓冲流: BufferedReader/BufferedWriter

(1)高效读写

(2)支持输入换行

(3)可一次写一行,读一行。

  • BufferedReader ——字符缓冲输入流

​ 从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。

​ 可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途。

​ 通常,由读取器做出的每个读取请求将引起对底层字符或字节流的相应读取请求。 因此,建议将BufferedReader包装在其read()操 作可能昂贵的读取器上,例如FileReader

BufferedReader in = new BufferedReader(new FileReader(“foo.in”));

将缓冲指定文件的输入。 没有缓冲,每次调用read()或readLine()可能会导致从文件中读取字节,转换成字符,然后返回,这可能非常低效。

构造方法:

常用方法:

【参考代码】

``

import java.io.BufferedReader;

import java.io.FileReader;

/**

* 字符缓冲流读取文件

*/

public class BufferedReaderDemon {

public static void main(String[] args) throws Exception{

//1. 创建缓冲流

FileReader fr = new FileReader(“d:\\write.txt”);

BufferedReader br = new BufferedReader(fr);

//2. 读取

//2.1 第一种读取方式

// char[] buf = new char[1024];

// int count = 0;

// while ((count = br.read(buf)) != -1){

// System.out.println(new String(buf, 0, count));

// }

//2.2 第二种读取方式。 一行一行的读取

String line = null;

while ((line = br.readLine()) != null){

System.out.println(line);

}

//3. 关闭

br.close();

}

}

  • BufferedWriter ——字符缓冲输出流(写入字符)

将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入。

可以指定缓冲区大小,或者可以接受默认大小。 默认值足够大,可用于大多数用途。

提供了一个newLine()方法,它使用平台自己的系统属性 line.separator 定义的行分隔符概念。 并非所有平台都使用换行符(‘\ n’)来终止行。 因此,调用此方法来终止每个输出行,因此优选直接写入换行符。

构造方法:

常用方法:

【参考代码】

import java.io.BufferedWriter;

import java.io.FileWriter;

public class BufferedWriterDemon {

public static void main(String[] args) throws Exception{

//1. 创建BufferedWriter对象

FileWriter fw = new FileWriter(“d:\\buffer.txt”);

BufferedWriter bw = new BufferedWriter(fw);

//2. 写入

for (int i = 0; i < 5; i ++){

bw.write(“好好学习吧!”);

bw.newLine();// 换行!

bw.flush();

}

//3. 关闭

bw.close();

}

}

打印流

  • PrintWriter ——打印流

将对象的格式表示打印到文本输出流。 这个类实现了全部在发现 print种 方法 PrintStream。 它不包含用于编写原始字节的方法,程序应使用未编码的字节流。

不像类,如果启用自动刷新,它只会在调用的 println,printf, 或 format 方法来完成,而不是当一个换行符恰好是输出。 这些方法使用平台自己的行分隔符而不是换行符。

转换流

转换流: InputStreamReader/OutputStreamWriter

(1)可以将字节流转为字符流

(2)可设置字符的编码方式

转换流的使用:

InputStreamReader读取文件

【参考代码】

import java.io.FileInputStream;

import java.io.InputStreamReader;

public class ZhuanHuanLiuTest {

public static void main(String[] args) throws Exception{

//1. 创建InputStreamReader对象

FileInputStream fis = new FileInputStream(“d:\\write.txt”);

InputStreamReader isr = new InputStreamReader(fis, “utf-8”); // 转换流设置编码方式

//2.读取文件

int data = 0;

while ((data = isr.read()) != -1){

System.out.println((char) data);

}

//3. 关闭

isr.close();

}

}

OutputStreamWriter——写入文件

【参考代码】

import java.io.FileOutputStream;

import java.io.OutputStreamWriter;

public class ZhuanHuanLiuTest {

public static void main(String[] args) throws Exception{

//1. 创建OutputStreamWriter对象

FileOutputStream fos = new FileOutputStream(“d:\\info.txt”);

OutputStreamWriter osw = new OutputStreamWriter(fos, “gbk”); // 转换流设置编码方式

//2. 写入

for(int i = 0; i < 5; i ++){

osw.write(“我爱学习\r\n”);

osw.flush();

}

//3. 关闭

osw.close();

}

}

六、对象流


对象流: ObjectInputStream/ObjectOutputStream 。

(1)增强了缓冲区功能

(2)增强了读取8种基本数据类型和字符串功能

(3)增强了读写对象的功能:

​ readObject() 从流中读取一个对象(反序列化)

​ writeObject(Object obj) 向流中写入一个对象(序列化)

使用流传输对象的过程称为序列化,和反序列化。

  • 对象输出流: ObjectOutputStream ——序列化(写入对象)

​ ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以 通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象。

构造方法:

常用方法:

【参考代码】

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

public class ObjectOutputStreamDemon {

/**

* 使用ObjectOutputStream实现对象的序列化————读入对象

* 要求:序列化类必须实现接口

*/

public static void main(String[] args) throws Exception{

//1. 创建对象流

FileOutputStream fos = new FileOutputStream(“d:\\stu.bin”);

ObjectOutputStream oos = new ObjectOutputStream(fos);

//2. 序列化(写入操作)

Student student = new Student(“张三”,19);

oos.writeObject(student);

//3. 关闭(自带flush()方法了)

oos.close();

System.out.println(“序列化完毕”);

}

}

class Student implements Serializable {

private String name;

private int age;

public Student(String name, int age) {

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

@Override

public String toString() {

return “Student{” +

“name='” + name + ‘\’’ +

“, age=” + age +

‘}’;

}

}

使用ObjectOutputStream实现对象的序列化————写入对象

​ 要求:序列化类必须实现接口

  • 对象输入流: ObjectInputStream ——反序列化(读取重构成对象)

​ ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象。

构造方法:

常用方法:

【参考代码】

import java.io.*;

public class ObjectInputStreamDemon {

public static void main(String[] args) throws Exception{

//1. 创建对象流

FileInputStream fis = new FileInputStream(“d:\\stu.bin”);

ObjectInputStream ois = new ObjectInputStream(fis);

//2. 读取文件(反序列化)

Student st = (Student) ois.readObject();

//3. 关闭

ois.close();

System.out.println(st.toString());// Student{name=‘张三’, age=19}

}

}

序列化和反序列化注意事项:

(1)序列化类必须实现 Serializable 接口

(2)序列化类中对象属性要求实现Serializable接口

(3)序列化版本号ID,保证序列化的类和反序列化的类是同一个类

(4)使用transient(瞬间的)修饰属性,这个属性不能序列化

(5)静态属性不能序列化

(6)序列化多个对象,可以借助集合

七、File类


概念:代表物理磁盘中的一个 文件 或者 文件夹(目录) 。

常用方法:

文件操作

(1)分隔符:

;

\

(2)文件操作:

  • 创建文件 createNewFile()

boolean createNewFile() 当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。

if(!file.exists()){ // 如果文件不存在则创建

boolean b = file.createNewFile();

System.out.println(“创建结果” + b);

}

  • 删除文件

直接删除: delete()

boolean delete() 删除由此抽象路径名表示的文件或目录

JVM退出时删除:

file.deleteOnExit();

Thread.sleep(5000); // 休眠五秒

  • 获取文件信息

  • getAbsolutePath() :获取到文件的绝对路径

  • getPath() :获取到文件的路径

  • getName() :获取文件的名称

  • getParent() :获取文件的父级目录

  • length() :获取文件的长度

  • lastModified() :获取文件的创建时间

System.out.println(“文件创建时间:” + new Date(file.lastModified()));

  • 判断

canWrite()

isFile()

isHidden()

【参考代码】

import java.io.File;

import java.util.Date;

public class FileTest {

public static void main(String[] args) throws Exception{

fileOpe();

}

/**

* 文件操作

*/

public static void fileOpe() throws Exception{

//1. 创建文件

File file = new File(“d:\\file.txt”); // 只是创建了一个文件对象,此时在d盘下并没有该文件

if(!file.exists()){ // 如果文件不存在则创建

boolean b = file.createNewFile();

System.out.println(“创建结果” + b);

}

//2. 删除文件

//2.1 直接删除

// System.out.println(“删除结果” + file.delete());

// //2.2 JVM退出时删除

// file.deleteOnExit();

// Thread.sleep(5000); // 休眠五秒

//3. 获取文件信息

System.out.println(“获取文件绝对路径” + file.getAbsolutePath()); // 获取文件绝对路径d:\file.txt

System.out.println(“获取路径” + file.getPath());

System.out.println(“获取文件名称” + file.getName());

System.out.println(“获取文件父目录” + file.getParent());

System.out.println(“获取文件长度” + file.length());

System.out.println(“文件创建时间:” + new Date(file.lastModified()));

//4. 判断

System.out.println(“是否可写” + file.canWrite());

System.out.println(“是否是文件” + file.isFile());

System.out.println(“是否隐藏” + file.isHidden());

}

}

文件夹操作

  • 创建文件夹

| boolean | mkdir() 创建由此抽象路径名命名的目录。 |

| — | — |

| boolean | mkdirs() 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录。 |

File dir = new File(“d:\\aaa\\bbb\\ccc”);

if(! dir.exists()){

dir.mkdir();// 只能单级目录

System.out.println(“创建结果:” + dir.mkdirs()); //mkdirs();//可以创建多级目录

}

  • 删除文件夹

直接删除: delete() ——只能删除空目录

JVM删除: file.deleteOnExit();Thread.sleep(5000); // 休眠五秒

  • 获取文件夹信息

getAbsolutePath()

getPath()

getName()

getParent()

lastModified()

  • 判断

isDirectory()

isHidden()

  • 遍历文件

(1) list()

//5. 遍历文件夹

File dir2 = new File(“e:\\picture”);

String[] files = dir2.list();

for(String str: files){

System.out.println(str);

}

(2) listFiles()

//5. 遍历文件夹

File dir2 = new File(“e:\\picture”);

File[] files = dir2.listFiles(); // 文件数组

for(File file: files){

System.out.println(file.getName());

}

FileFilter接口

当调用File类中的 listFiles() 方法时,支持传入 FileFilter 接口接口实现类,对获取文件进行过滤,只有满足条件的文件才可以出现在 listFiles() 方法的返回值中。

【参考代码】

File dir2 = new File(“e:\\picture”);

// 过滤:过滤出满足条件的文件

File[] file2 = dir2.listFiles(new FileFilter() {

@Override

public boolean accept(File pathname) {

if(pathname.getName().endsWith(“.png”)){ // 只要.png结尾的图片

return true;

}

return false;

}

});

// 遍历输出

for(File file : file2){

System.out.println(file.getName());

}

递归遍历与删除

递归遍历文件夹:

遍历拿到 dir.listFiles() 路径的路径数组,数组不为空且有文件的情况下,如果是文件夹递归则进去,直到不是文件夹,然后输出文件,否则输出当前目录下的文件!

【参考代码】

import java.io.File;

public class ListDemon {

public static void main(String[] args) {

listDir(new File(“e:\\aaa”));

}

//递归遍历文件夹

public static void listDir(File dir){

File[] files = dir.listFiles();// 得到所有得子文件与子文件夹

System.out.println(“路径:”+ dir.getAbsolutePath());

if(files != null && files.length > 0){

for(File file : files){

if(file.isDirectory()){// 判断是否为文件夹

listDir(file); // 如果是文件夹递归进去,直到不是文件夹

}else{// 不是文件夹 则输出

System.out.println(file.getAbsolutePath());

}

}

}

}

}

我电脑E盘下的aaa文件如下图:

递归删除文件夹:

我们直到 delete() 方法只能删除空目录。如果目录里边有内容, delete() 方法是无法删除的,即我们想用 delete() 方法删除上述aaa文件是行不通的!

为此,我们得先将 aaa 文件中所有内容给删除之后,才能将 aaa 文件删除掉! aaa 里边有 bbb 文件夹,为此得先把它里边得内容先删掉, bbb 里边有 ccc 文件夹为此得先把它里边得内容先删掉…然后再逐步回退删除文件夹!

【参考代码】

import java.io.File;

public class ListDemon {

public static void main(String[] args) {

deleteDir(new File(“e:\\aaa”));

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

完结

Redis基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。Redis是如今互联网技术架构中,使用最广泛的缓存,在工作中常常会使用到。Redis也是中高级后端工程师技术面试中,面试官最喜欢问的问题之一,因此作为Java开发者,Redis是我们必须要掌握的。

Redis 是 NoSQL 数据库领域的佼佼者,如果你需要了解 Redis 是如何实现高并发、海量数据存储的,那么这份腾讯专家手敲《Redis源码日志笔记》将会是你的最佳选择。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
方法只能删除空目录。如果目录里边有内容, delete() 方法是无法删除的,即我们想用 delete() 方法删除上述aaa文件是行不通的!

为此,我们得先将 aaa 文件中所有内容给删除之后,才能将 aaa 文件删除掉! aaa 里边有 bbb 文件夹,为此得先把它里边得内容先删掉, bbb 里边有 ccc 文件夹为此得先把它里边得内容先删掉…然后再逐步回退删除文件夹!

【参考代码】

import java.io.File;

public class ListDemon {

public static void main(String[] args) {

deleteDir(new File(“e:\\aaa”));

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-34Q3ohVz-1713304848988)]

[外链图片转存中…(img-eVPz3Tlr-1713304848989)]

[外链图片转存中…(img-y4GwfTpk-1713304848989)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

完结

Redis基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。Redis是如今互联网技术架构中,使用最广泛的缓存,在工作中常常会使用到。Redis也是中高级后端工程师技术面试中,面试官最喜欢问的问题之一,因此作为Java开发者,Redis是我们必须要掌握的。

Redis 是 NoSQL 数据库领域的佼佼者,如果你需要了解 Redis 是如何实现高并发、海量数据存储的,那么这份腾讯专家手敲《Redis源码日志笔记》将会是你的最佳选择。

[外链图片转存中…(img-TXE37dN1-1713304848989)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值