File(文件夹/目录)
作用:操作文件本身,如名字遍历删除,如果需要操作文件中的内容,我们必须使用Io来完成
window一般用\分割文件 然后 但是java中用//这个或者\
操作File常见方法:
-
String getName():获取文件名称
-
String getPath():获取文件路径
-
String getAbsolutePath():获取绝对路径
相对路径和绝对路径:
假如一个学生是我们班级的,我们只需要说他的名字就好,但是要是其他班级的就需要说明,是哪个班级的谁谁谁
-
File getParentFile():获取上级目录文件
当一直向上找的时候,找到根目录的时候,在点一次就会返回null
-
boolean exists():判断文件是否存在
-
boolean isFile() :是否是文件
-
boolean isDirectory():判断是否是目录
-
boolean delete() :删除文件
-
boolean mkdirs():创建当前目录和上级目录
-
File[] listFiles() :列出所有文件对象
递归:调用自己的方法
演示一个递归操作 ,遍历一个文件夹的所有文件(包括子文件)
注意:使用递归操作的时候,一定要给自己的方法一个出口 ,在递归调用的时候就是使用方法
package cn.wolfd._02_filesDir; import java.io.File; public class FileDemodir { public static void main(String[] args) { //需求 : 遍历当前文件夹的所有文件(包括所有的子文件) File file = new File("F:\\java学习资料\\预习资料\\基础班资料\\第四阶段-基础高级阶段\\04-IO\\day01\\笔记"); listFiles(file); } public static void listFiles(File file){ //判断当前传入地址是否是文件 if (file.isDirectory()){ //如果是 就列出所有文件的对象 File[] files = file.listFiles(); //判断文件中是否有元素 如果不为空 那么就将此file遍历 //遍历之后对没有文件夹执行listFile判断 如果是一个文件夹就继续遍历 //如果不是文件夹,就直接打印名字 if (files!=null){ for (File file1 : files) { listFiles(file1); } } //最后才会打印出 最开始的文件夹名字 System.out.println(file); } } }
字符集
Unicode 万国码
GBK家族一个汉字为两个字符集
UTF-8亚洲通用字符集 一个汉字三个字节,支持中文,建议在开发中使用
ISO–8859-410 老外服务器编码格式,常用
ASCLL和ISO-8859-1不能存中文会乱码
编码和解码
编码-将字符串转为一个byte[]数组(转为计算机能看懂的语言)
//编码操作:String -> byte[]
byte[] data = input.getBytes(“UTF-8”);
解码-将byte[]数组转为String (转为人能看懂得语言)
//解码操作:byte[] -> String
String ret = new String(data, “ISO-8859-1”);
乱码的原因—编码的字符集不一样
解决方案-将乱码转为二进制byte[] 然后我们再将二进制数组,转为我们想要的字符集就可以了
IO
io我们都是站在内存角度说的,所以说我们读取进来,就是input 就是输入道内存中 output就是输出从内存中输出出去
读进来,写出去-----
流的分类
节点流 基本流
包装流 功能更强大的节点流
输入流和输出流的参考点 只有内存 没有其他
- read 将文件中数据读进来
- write 将程序中的数据写道文件中
四大基本流
流向 | 字节流(单位是字节) | 字符流(单位是文字符) |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputString | Writer |
IO操作模板
1:创建目标源对象
一般都是创建一个文件对象
2:创建io流对象(一个文件和程序的连接渠道)
这个就是字节流字符流的各种形式
3:具体的Io流操作
read方法 将文件中的读取到程序中
writer方法 将程序中写出道文件中
4:关闭资源(勿忘) 当使用完不关闭浪费资源,关闭之后也就不能使用流了
流对象.close(); 用完关闭就好了
InputStream
属于Io包 一个抽象类 一堆儿子
常用方法
1:close() 正常关闭
2:read() 一次读取一个字节
3:read(byte[] buff) 读取多个字节
4:available()方法可以自动算读取多少个字节
int available1 = in.available();
byte[] buff = new byte[available1];
public static void main(String[] args) throws IOException {
//从指定文件按照字节为单位将数组读取到程序中
//1:只当操作的源文件
File file = new File("files/src.txt");
System.out.println(file.exists());
//2:创建输入流对象
FileInputStream in = new FileInputStream(file);
//3.执行read方法完成读取操作 提前准备一下接受的
byte[] buff = new byte[3];
int available = 0;
int len = 0;
//每次数组都是添加到buffer数组中,后面可能存在元素覆盖不完的问题
while((len = in.read(buff))!=-1){
//只转换到读取到的字节数
System.out.print(new String(buff,0,3));
}
//4关闭资源
in.close();
}
OutputStream
属于Io包 一个抽象类 一堆儿子
常用方法
1.close(); 正常关闭
2:finalize()清理文件的连接,并且保证没有更多的引用流时,将调用此文件输出流的close方法
3:getChannel() 返回与此文件输出流相关练习的唯一FileChannel对象
4:write();写出一个字节
5:write(byte[] buff);写出多个字节
6:write(byte[] buff,int off,int len);写出多个字节
public static void main(String[] args) throws IOException {
//1确定一个目标文件
File file = new File("files/dest.txt");
//2:创建文件输出流对象
// public FileOutputStream(File file, boolean append)
//如果再构造器的boolean输入true此时就可以实现追加输出
FileOutputStream os = new FileOutputStream(file,true);
//3:执行write方法完成输出操作
os.write(65);
os.write(66);
os.write(new byte[]{65,66,67,68,69,70,100});
//直接输入字符串 再输出的时候直接转换为byte数组 直接写出
os.write("wolfd".getBytes());
//用中文的时候 就不要轻易用
os.write("wolfd".getBytes(),0,2);
//4:关闭资源
os.close();
}
Write
常用方法
1.close(); 正常关闭
2:write();写出一个字符
3:write(char[] buff);写出多个字符
4:write(char[] buff,int off,int len);写出多个字符
5:构造器(File ,boolean b) 当b为true的时候就不覆盖文件中内容
public static void main(String[] args) throws IOException {
//1:确定目标文件的路径,2创建输出流对象
FileWriter fileWriter = new FileWriter("files/dest.txt",true);
//3:执行write方法完成写出的操作
fileWriter.write(65);
fileWriter.write("中立群塔千百,知乎,知乎,摆渡荷载");
fileWriter.write(new char[]{'A','B','C','D','E'},0,2);
//4关闭资源
fileWriter.close();
}
Reader
(char 默认为null 读取的时候给定一个范围)
常用方法
1:close() 正常关闭
2:read() 一次读取一个字符
3:read(char[] buff) 读取多个字符
4:read(cahr[] buff,int off,int len);
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("files/dest.txt");
//一次读取一个字符
int c = reader.read();
System.out.println((char)c);
//一次读取多个字符
char[] cuff = new char[3];
int read = reader.read(cuff);
System.out.println(new String(cuff));
int len=0;
//精髓代码区
while ((len=reader.read(cuff))!=-1){
System.out.print(new String(cuff,0,len));
}
reader.close();
}
总结:------字节流和字符流 就是单位不同,
开发中纯文本的通常用字符流更方便,如果有图片或视频我们必须使用字节流 ,使用字符流的时候可以使用带范围的构造器,
文件拷贝操作
我们上边学习了io的操作,接下来我们具体实战一下,完成以下文件拷贝的操作 以及正确的处理异常以及原因
1:正常拷贝文件的操作
private static void copy() throws Exception{
//1:creat target file
File src = new File("file/copy_before.txt");
File dest = new File("file/copy_after.txt");
//2:creat IO Object
FileReader in = new FileRead(src);
FileReader out = new Filewiter(dest);
//3:具体的IO操作
int len = -1;//记录以及读取了多个字符
char[] buff = new char[1024];//每次可以读取1024个字符
len = in.read(buff);//先读取一次
while(len > 0) {
//边读边写
out.write(buff, 0, len);
len = in.read(buff);//再继续读取
}
//4):关闭资源(勿忘)
out.close();
in.close();
}
上面的代码,采用抛出异常的方式进行编写,接下来我们演示在代码内进行处理
2:有异常处理的文件拷贝工作
private static void copy2() {
//1):创建源或者目标对象
File src = new File("file/copy_before.txt");
File dest = new File("file/copy_after.txt");
//把需要关闭的资源,声明在try之外
FileReader in = null;
FileWriter out = null;
try {
//可能出现异常的代码
//2):创建IO流对象
in = new FileReader(src);
out = new FileWriter(dest);
//3):具体的IO操作
int len = -1;//记录以及读取了多个字符
char[] buff = new char[1024];//每次可以读取1024个字符
len = in.read(buff);//先读取一次
while (len > 0) {
out.write(buff, 0, len);
len = in.read(buff);//再继续读取
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//4):关闭资源(勿忘)
try {
if (out != null) {
out.close();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (in != null) {
in.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
第三种改良版本
private static void copy2() {
//1):创建源或者目标对象
File src = new File("file/copy_before.txt");
File dest = new File("file/copy_after.txt");
//把需要关闭的资源,声明在try之外
try(
//指定可以自动关闭资源的io
FileReader in =in = new FileReader(src);
FileWriter out = out = new FileWriter(dest);
) {
//3):具体的IO操作
int len = -1;//记录以及读取了多个字符
char[] buff = new char[1024];//每次可以读取1024个字符
len = in.read(buff);//先读取一次
while (len > 0) {
out.write(buff, 0, len);
len = in.read(buff);//再继续读取
}
} catch (Exception e) {
e.printStackTrace();
}
//等全部执行完毕之后自动关闭
}
总结:
(1):ctrl + alt + t 可以选择代码被什么包围,可以用于快速处理异常
(2):如果规避空指针异常错误 判断当!=null这样就可以
(3):因为四大基本类型都实现了closeable接口 (实现了此接口然后在处理异常时候,可以自动关闭io但是要在try(这里面 定义需要关闭的资源对象,全部初始化){}catch(){})
缓冲流
作用:减少磁盘IO工作量,提高效率
原理:内置8192(字节/字符),其实就是数组,将我们需要的字节和字符缓存起来,等存满8192个字节在进行输出,此时问题来了,如果没满就不输入了吗,当然不是
输出条件一:当8192个字符都装满的情况下都装满了 输出条件二:当执行close的时候自动执行输出操作(刷新)
四个基本缓冲流
BufferedInputStream / BufferedOutputStream / BufferedReader / BufferedWriter
用法
private static void copy3() throws Exception {
//1):创建源或者目标对象
File src = new File("file/郭德纲-报菜名.mp3");
File dest = new File("file/郭德纲-报菜名2.mp3");
//2):创建IO流对象
BufferedInputStream bis =
new BufferedInputStream(new FileInputStream(src), 8192);
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream(dest), 8192);
//3):具体的IO操作
int len = -1;//记录以及读取了多个字符
byte[] buff = new byte[1024];//每次可以读取1024个字符
len = bis.read(buff);//先读取一次
while (len > 0) {
//边读边写
bos.write(buff, 0, len);
len = bis.read(buff);//再继续读取
}
//4):关闭资源(勿忘)
bos.close();
bis.close();
}
对象序列化
序列化作用:把java堆内存中的对象数据,通过某种关系把对象数据存储到磁盘上或者网络上
反序列化作用:把磁盘文件中的对象的数据或者把网络节点上的对象数据恢复成Java对象的过程。
如果要做序列化操作和反序列化操 必须实现Serializable接口,如果版本号不一致,那么就会反序列化失败
可以通过IO中的对象流来做序列化和反序列化操作。
-
ObjectOutputStream:通过writeObject方法做序列化操作的
-
ObjectInputStream:通过readObject方法做反序列化操作的
使用transient修饰的字段不会被序列化
class User implements Serializable {
private String name;
private transient String password;
private int age;
......//省略一万行代码
}
public class ObjectStreamDemo {
public static void main(String[] args) throws Exception {
String file = "file/obj.txt";
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
User u = new User("Will", "1111", 17);
out.writeObject(u);
out.close();
//--------------------------------------
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
in.close();
System.out.println(obj);
}
}
java.io.InvalidClassException 异常
版本号不一致 序列化的版本号发生了改变
对象的serialVersionUID被改变了
为了避免代码版本升级而造成反序列化因版本不兼容而失败的问题,在开发中我们可以故意在类中提供一个固定的serialVersionUID值。
class User implements Serializable {
private static final long serialVersionUID = 1L;
//TODO
}
无论如何结构都不能改变类的结构
Scanner
作用:对文件做扫描可以对文件进行操作
常用方法:
判断文件中是否有下一行 hasNextLine()
如果文中没有下一行那么久跳出nextLine()
标准IO
标准的输入:通过键盘录入数据给程序
标准的输出:在屏幕上显示程序数据
在System类中有两个常量int和out分别就表示了标准流:
InputStream in = System.in;
PrintStream out = System.out;