Java__IO流
1.File类
File类是java.io包中很重要的一个类。
一个File类的对象表示一个计算机中的文件或者目录(文件夹)。
(1)File类的构造方式(3种)
// 方式一
File f = new File("D:/message.txt");
// 方式二
String p = "D:\\";
File f1 = new File(p,"message.txt");
File f2 = new File(p,"work");
// 方式三
File fp = new File("D:\\");
File f3 = new File(fp,"message.txt");
File f4 = new File(fp,"work");
(2)File类的常用方法
public static void main(String[] args) {
/*
File类
一个File类的对象就表示一个计算机中的文件或者目录(文件夹)
*/
File f = new File("D:/message.txt"); // 在创建File对象时,不检测文件是否存在
System.out.println(f.length()); //10 获取文件的长度(字节)
System.out.println(f.getParent());//D:\ 获取上一级路径
System.out.println(f.getName());//message.txt 获取文件名
System.out.println(f.getAbsolutePath());//D:\message.txt 获取文件路径
System.out.println(f.exists()); //true 判断文件是否存在
System.out.println(f.isDirectory()); //false 判断是否是文件夹
System.out.println(f.isHidden()); //false 判断文件是否为隐藏文件
System.out.println(f.isAbsolute()); //true 判断路径是否为绝对路径
File f1 = new File("message.txt");
System.out.println(f1.isAbsolute());//false
f.lastModified();
System.out.println(f.lastModified()); //1609487897379 返回最后一次修改时间 long型
Date date = new Date(f.lastModified()); // long型转Date型
DateUtil d = new DateUtil();
System.out.println(d.dateToString(date)); //2021-01-01 15:58:17 ven.
}
public static void main(String[] args) {
/* File f = new File("D:/test");
try {
System.out.println(f.createNewFile()); //创建文件,需要用try-catch抛出一个IOException
// 如果已经存在,就不创建了,返回false
// 如果不存在,就创建,返回true
// 如果盘符/地址在计算机没有(不存在),直接抛出异常
} catch (IOException e) {
e.printStackTrace();
}*/
File f = new File("D:/test.txt");
try {
f.createNewFile(); // //创建文件
} catch (IOException e) {
e.printStackTrace();
}
f.delete(); // 删除文件,该文件存在返回true,不存在返回false
File f1 = new File("D:/Demo/Demo");
// f1.mkdir(); // 只能创建单级文件夹
f1.mkdirs();// 可以创建多级文件
f1.delete(); //删除文件夹,删除时文件夹必须为空,即要删除的文件夹不包含任何东西,包括文件夹
File f3 = new File("D:/Demoss");
f3.mkdir(); // 只能创建单级文件夹
File f2 = new File("D:/工具包");
/* // 获取指定目录下的所有子级的文件或目录,以字符串形式返回
String[] farray1 = f2.list();//返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录
for (String s : farray1) {
System.out.println(s);
}*/
/*
// 添加过滤条件,筛选文件
String[] farr = f2.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith("exe");
}
});
for (String arr : farr){
System.out.println(arr);
}
*/
File[] fs = f2.listFiles(new FilenameFilter(){ // 获取指定目录下的所有子级的文件或目录,返回一个文件数组
@Override
public boolean accept(File dir, String name) { // 添加过滤条件,筛选文件
return name.endsWith("exe"); // 指定后缀名
}
});
for (File ft : fs){
System.out.println(ft);
}
File f5 = new File("D:\\demo.txt");
File f6 = new File("D:\\demo1.txt");
f5.renameTo(f6);//重命名
System.out.println(f6);// D:\demo1.txt
}
2.输入及输出(I/O)
输入:把电脑硬盘上的数据读到程序中,即input,进行数据的read操作。
输出:从程序往外部设备写数据,称为输出,即output,进行数据的write操作。
3.流的分类
流按着数据的传输方向分为:输入流 与 输出流。
- 输入流:往程序中读叫输入流。
- 输出流:从程序中往外写叫输出流。
从数据流编码格式上划分为: 字节流 与 字符流。
根据封装类型不同流又分为: 节点流 与 处理流
- 节点流:如果流封装的是某种特定的数据源,如文件、字符串、字符串数组等,则称为节点流。
- 处理流: 如果流封装的是其它流对象,称为处理流。处理流提供了缓冲功能,提高读写效率,同时增加了一些新的方法。
4. 字节流与字符流
字节流中常用类:
- 字节输入流 FileInputStream
- 字节输出流 FileOutputStream
字符流中常用类:
- 字符输入流 FileReader
- 字符输出流 FileWriter
public static void main(String[] args) {
// 创建方法1
/*File f = new File("D:\\message.txt");
try {
FileInputStream in1 = new FileInputStream(f)
} catch (FileNotFoundException e) {
e.printStackTrace();
}*/
try {
// 创建方法2
/*
创建FileInputStream对象,指定要输入(读)的文件,文件不存在,会抛出异常
*/
FileInputStream in = new FileInputStream("D:\\\\message.txt");
int b = 0;
try {
b = in.read(); // 读取文件中的内容,返回一个字节
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(b);
int b1 = in.read();
System.out.println(b1);
int b2 = in.read();
System.out.println(b2);
int b3 = in.read();
System.out.println(b3);
int b4 = in.read();
System.out.println(b4);
int b5 = in.read();
System.out.println(b5);
int b6 = in.read();
System.out.println(b6);
int b7 = in.read();
System.out.println(b7);
//read() 每read()一次,从输入流中读到一个字节 返回,文件内容全部读完后,返回-1.
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
eg:读一个指定目录下的文件,并把它写进另一个指定的文件中。
public static void main(String[] args) {
、
/*
读一个指定目录下的文件,并把它写进另一个指定的文件中。
方法1:读一个字节,写入一个字节
*/
FileInputStream in = null;
FileOutputStream out = null;
try {
/*
创建FileInputStream对象,指定要输入(读)的文件,文件不存在,会抛出异常
*/
in = new FileInputStream("D:\\message.txt");
/*
创建FileOutputStream对象,自动创建输出的目标文件
*/
out = new FileOutputStream("D:\\demo.txt");
int b = 0; // 记录每次读到的字节值
while ((b = in.read()) != -1) {
System.out.println(b);
out.write(b); // 向指定的文件中输出字节
}
//关闭流对象,释放系统资源
in.close();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
/*
读一个指定目录下的文件,并把它写进另一个指定的文件中。
方法2:把文件分成一份份指定数组长度大小的临时文件(读),储在一个temp的文件夹中,最后将这若干份合并为一个 文件(写)。
*/
FileInputStream in = new FileInputStream("D:\\testread.mp4");
FileOutputStream out = new FileOutputStream("D:\\temp");
byte[] b = new byte[1024];//存储读到的内容
int length = 0; // 记录每次读到的字节值
while ((length = in.read(b)) != -1) {
out.write(b,0,length); // 向外写出一个byte数组个字节,从数组指定位置开始,写length个字节
}
// 关闭通道。释放资源
in.close();
out.close();
}
5.节点流与处理流
节点流中的常用类:
- 字节输入流 FileInputStream
- 字节输出流 FileOutputStream
- 字符输入流 FileReader
- 字符输出流 FIleWriter
处理流中的常用类:
- 缓冲字节输出流 BufferedOutputStream
- 缓冲字节输入流 BufferedInputStream
- 缓冲字符输入流 BufferedReader
- 缓冲字符输出流 BufferedWriter
public static void main(String[] args) throws IOException {
/*
字节流以字节为单位读写数据
*/
// 创建输入节点流,直接负责对文件读写
FileInputStream in = new FileInputStream("D:\\testread.mp4");
// 创建处理对象,内部有一个缓冲数组,默认为8192个字节
BufferedInputStream bin = new BufferedInputStream(in);
FileOutputStream out = new FileOutputStream("D:\\testread.txt");
BufferedOutputStream bout = new BufferedOutputStream(out);
// 读一个字节,写一个字节
/* int b = 0;
while ((b=bin.read())!=-1){
bout.write(b);
}*/
// 读一个数组长度,写一个数组长度
byte[] b = new byte[1024];
int length=0;
while ((length=bin.read(b))!=-1){
bout.write(b,0,length);
}
bout.flush(); // 刷新缓冲区
bout.close(); // 关闭处理流通道,其封装的节点流也被关闭
bin.close();
}
public static void main(String[] args) throws IOException {
/*
字符流以字符为单位读写数据
*/
FileReader reader = new FileReader("D:\\message.txt");
BufferedReader breader = new BufferedReader(reader);
FileWriter writer = new FileWriter("D:\\demo.txt");
BufferedWriter bwriter = new BufferedWriter(writer);
// 读一个字符 ,返回该字符对应的字符编码
/* int c = ' ';
while ((c=breader.read())!=-1){
System.out.println(c);
bwriter.write(c);
}*/
// 读指定数组长度大小个字符
/* char[] c = new char[5];
int length =0;
while ((length =breader.read(c) )!=-1){
bwriter.write(c,0,length);
}*/
// 读一行
String c = " ";
while ((c =breader.readLine() )!=null){ //breader.readLine() 一次读一行
System.out.println(c);
bwriter.write(c);//一次写一个字符串
bwriter.newLine();//换行
}
bwriter.flush();
bwriter.close();
breader.close();
}
6.Print流(打印流)
Print流(打印流):只做输出没有输入
/*
打印流 单向的从程序中向外输出数据
PrintWriter 打印输出流
*/
public static void main(String[] args) throws FileNotFoundException {
PrintWriter out = new PrintWriter("D:\\demo29.html");// 创建一个HTML文档
/*
print 与write 都是从程序向外输出数据,里面的文本内容可以加HTML的标签
println 是源码换行
*/
out.println("<h1>这是从服务器端响应的数据</h1>");
out.print("<h1>这是从服务器端响应的数据</h1>");
out.print("<h1>这是从服务器端响应的数据</h1>");
out.print("<h1>这是从服务器端响应的数据</h1>");
// print底层使用的还是write(), 只是重载了多个,可以处理多种的数据类型
out.write("<h2> 二级标签 </h2>");
out.close();
}
7.对象输入输出流
对象的输入输出流:主要的作用是用于写入对象信息与读取对象信息。对象信息一旦写到文件上那么对象的信息就可以做到持久化了。
- 对象的输出流: ObjectOutputStream
- 对象的输入流: ObjectInputStream
要将序列化之后的对象保存下来,需要通过对象输出流(bjectOutputStream)将对象状态保存,之后在通过对象输入流(ObjectInputStream)j将对象状态恢复。
- 在ObjectInputStream中用readObject()方法可以直接读取一个对象
- ObjectOutputStream中用writeObject()方法可以直接将对象保存到输出流中
public static void main(String[] args) throws IOException, ClassNotFoundException {
/*
对象输入输出流
对象: 内存中的对象
为什么要将对象输出?
内存中的数据由于电脑关闭,服务器停止,数据就会消失
有时候需要将这些数据保存起来(这个过程被称为对象的序列化)
*/
/*
//第一步: 将指定对象的数据存到指定路径的文件下
FileOutputStream out = new FileOutputStream("D:\\data.txt");
ObjectOutputStream oout = new ObjectOutputStream(out);
String s = "hello World";
Date date = new Date(); // 当前日期
oout.writeObject(s);
oout.writeObject(date);
oout.close();
*/
// 第二步:从上一步的指定文件中读取存进去的数据
FileInputStream in = new FileInputStream("D:\\data.txt");
ObjectInputStream oin = new ObjectInputStream(in);
String s = (String) oin.readObject();
System.out.println(s); // hello World
Date date = (Date) oin.readObject();
System.out.println(date); // Thu Jan 14 15:21:34 CST 2021
oin.close();
}
8.对象序列化
对象的寿命通常随着生成该对象的程序的终止而终止。有时候,我们可能需要将对象的状态保存下来,在需要时再将对象恢复。
- 对象的序列化:(通过对象的输出流)将指定的对象写入到文件的过程,就是将对象序列化的过程。
- 对象的反序列化:(通过对象的输入流)将指定序列化好的文件读出来的过程,就是对象反序列化的过程。
既然对象的输出流将对象写入到文件中称之为对象的序列化,所以必须要实现Serializable
接口。
Serializable
接口中没有任何方法。当一个类声明实现Serializabl接口后,表明该类可被序列化。
一个类声明实现Serializabl接口后,可以生成一个编号:
private static final long serialVersionUID = -14188555542742906L;
这个编号(serialVersionUID)是随机生成的,并且它是唯一的。
serialVersionUID用来表明实现序列化的不同版本间的兼容性。某个类在与之对应的对象已经序列化出去后做了修改,该对象依然可以被正确反序列化。