向Drunkbaby师傅学习!
在学习反序列化之前,首先要对输入输出流有一定的了解
什么是IO,即Input和Output输入与输出,通过IO可以完成硬盘文件的读和写。
流的传输过程:
首先不管是输入还是输出,传输的两端都是文件和java的运行程序,所以如果想要在这二者之间进行传输,我们就需要将他们两个之间搭起来一个可以传输的通道,这样就可以实现流的传输。
创建文件使用的是File类,这里具体的话有三种方式。三种方式使用的是同一种方法,使用其实三种方式都大同小异,接下来依次看看。
第一种
1、使用的方法是new File(String pathname)
,具体代码如下所示
package org.example;
import java.io.File;
import java.io.IOException;
//根据路径创建一个File对象
public class Main {
public static void main(String[] args) {
creatreFile();
}
public static void creatreFile(){
File file = new File("src/main/java/org/example/1.txt");//创建1.txt文件
try {
file.createNewFile();
System.out.println("Success");
} catch (IOException e) {
e.printStackTrace();
}
}
}
可以看到成功写入。接下来看第二种方式
第二种
2、使用的方法是 new File(File parent, String child)
,看似与上个相同,但实则多了一参数,而且第一个参数也变化了,示例如下
package org.example;
import java.io.File;
import java.io.IOException;
//根据路径创建一个File对象
public class Main {
public static void main(String[] args) {
creatreFile();
}
public static void creatreFile(){
String Parentfile = "src/main/java/org/example";
File file =new File(Parentfile,"2.txt");
try {
file.createNewFile();
System.out.println("Success");
} catch (IOException e) {
e.printStackTrace();
}
}
}
emmm,我感觉与第一个大同小异,只是表达方式简单变化了一下
第三种
3、使用的方法是 new File(File parent, String child)
,与上个差不多,接下来看demo
package org.example;
import java.io.File;
import java.io.IOException;
//根据路径创建一个File对象
public class Main {
public static void main(String[] args) {
creatreFile();
}
public static void creatreFile(){
String Parentfile = "src/main/java/org/example";
String filename = "3.txt";
File file =new File(Parentfile,filename);
try {
file.createNewFile();
System.out.println("Success");
} catch (IOException e) {
e.printStackTrace();
}
}
}
其实就是调用一下File类的几个方法,具体如下
package org.example;
import java.io.File;
import java.io.IOException;
//根据路径创建一个File对象
public class Main {
public static void main(String[] args) {
creatreFile();
}
public static void creatreFile(){
String Parentfile = "src/main/java/org/example";
File file =new File(Parentfile,"2.txt");
System.out.println("文件名为:"+file.getName());
System.out.println("文件的绝对路径为:" + file.getAbsolutePath());
System.out.println("文件的父级目录为:" + file.getParent());
System.out.println("文件的大小(字节)为:" + file.length());
System.out.println("这是不是一个文件:" + file.isFile());
System.out.println("这是不是一个目录:" + file.isDirectory());
}
}
这里因为没有在文件中写入内容,所以文件大小为0
使用 的是file.delete(Filename)
方法,具体demo如下
import java.io.File;
import java.io.IOException;
//根据路径创建一个File对象
public class Main {
public static void main(String[] args) {
creatreFileDir();
}
public static void creatreFileDir() {
String fileD = "src/main/java/org/example/";
File file = new File(fileD,"2.txt");
try {
file.delete();
System.out.println("success");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
这里使用的方法是file.mkdir()
,具体见demo
package org.example;
import java.io.File;
import java.io.IOException;
//根据路径创建一个File对象
public class Main {
public static void main(String[] args) {
creatreFileDir();
}
public static void creatreFileDir() {
String fileD = "src/main/java/org/example/FileDir";
File file = new File(fileD);
try {
file.mkdir();
System.out.println("success");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
使用的方法是File.mkdirs()
,具体demo如下
package org.example;
import java.io.File;
import java.io.IOException;
//根据路径创建一个File对象
public class Main {
public static void main(String[] args) {
creatreFileDir();
}
public static void creatreFileDir() {
String fileD = "src/main/java/org/example/FileDir/qwq2";
File file = new File(fileD);
try {
file.mkdirs();
System.out.println("success");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
删除目录同删除文件相同,使用的是File.delete
方法,但它只能删除空目录,所以在删除前需先清除文件
package org.example;
import java.io.File;
import java.io.IOException;
//根据路径创建一个File对象
public class Main {
public static void main(String[] args) {
creatreFileDir();
}
public static void creatreFileDir() {
File fileD =new File("src/main/java/org/example/FileDir");
System.out.println(fileD.delete()? "Delete Successfully":"Delete failed");
}
}
按照操作数据单位不同分为:字节流和字符流
字节流(8bit,适用于二进制文件)
字符流(按字符,因编码不同而异,适用于文本文件)
按照数据流流向不同分为:输入流和输出流
按照流的角色不同分为:节点流,处理流/包装流
抽象基类 | 字节流 | 字符流 |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
读取文件分为两步
1.将文件中的数据转换为流对象
2.读取流对象的数据
细分的话,可分为如下三步
1、创建流对象
2、读取流对象内部数据
3、关闭流对象
使用read方法读取文件,有关read
方法的解释如下
read()
public int read() throws IOException
从此输入流中读取一个数据字节。
如果没有输入可用,则此方法将阻塞。
指定者: 类 InputStream 中的 read
返回: 下一个数据字节;如果已到达文件末尾,则返回 -1。
抛出: IOException - 如果发生 I/O 错误。
reads()
允许在方法中添加一个字节数组。
这种方式很有意思,当我们设置缓冲区的值为 8 时,若文件中的字符长度超过了 8,则会换行输出。这和上面的换行实际上是异曲同工。
再回到之前我们讲的 Runtime 类进行命令执行的 Payload,在那里,我们设置的 Cache 缓冲区的值为 1024.
读取文件Demo
package org.example;
import java.io.*;
/**
* Creator: yz
* Date: 2019/12/4
*/
public class Main{
public static void main(String[] args) throws IOException {
File file = new File("C:\\WINDOWS\\system32\\drivers\\etc\\hosts");
// 打开文件对象并创建文件输入流
FileInputStream fis = new FileInputStream(file);
// 定义每次输入流读取到的字节数对象
int a = 0;
// 定义缓冲区大小
byte[] bytes = new byte[1024];
// 创建二进制输出流对象
ByteArrayOutputStream out = new ByteArrayOutputStream();
// 循环读取文件内容
while ((a = fis.read(bytes)) != -1) {
// 截取缓冲区数组中的内容,(bytes, 0, a)其中的0表示从bytes数组的
// 下标0开始截取,a表示输入流read到的字节数。
out.write(bytes, 0, a);
}
System.out.println(out.toString());
}
}
这里简单介绍一下函数
fis.read()方法是依次读取一个个字节数据,返回每个数据的整型,该方法的作用是每次读取流中的一个字节,如果需要读取流中的所有数据,需要使用循环读取。
fis.read(bytes)此方法是就实现了将流对象fis中的数据读取到字节数组bytes中,该行代码的作用是将fis流中的数据读取出来,并依次存储到数组data中,返回值为实际读取的有效数据的个数。
package org.example;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Creator: yz
* Date: 2019/12/4
*/
public class Main {
public static void main(String[] args) throws IOException {
// 定义写入文件路径
File file = new File("D:/1.txt");
// 定义待写入文件内容
String content = "Hello World.";
// 创建FileOutputStream对象
FileOutputStream fos = new FileOutputStream(file);
// 写入内容二进制到文件
fos.write(content.getBytes());
fos.flush();
fos.close();
}
}