1.序列化就是在保存数据时, 保存数据的值和数据类型
2.反序列化就是在恢复数据时, 恢复数据的值和数据类型
3.需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该
类必须实现如下两个接口之一:
Serializable //这是一个标记接口,没有方法
Externalizable //该接口有方法需要实现,因此我们一般实现上面的Serializable接口
第一种:输入流和输出流
按照流的流向来分,可以分为输入流和输出流。输入,输出都是从程序运行所在内存的角度来划分的。
输入流:只能从中读取数据,而不能向其写入数据,由InputStream和Reader作为基类。
输出流:只能向其写入数据,而不能从中读取数据。由OutputStream和Writer作为基类
第二种:字节流和字符流
字节流和字符流的用法几乎完全一样,区别在于字节流和字符流所操作的数据单元不同。
字节流操作的数据单元是8位字节,由InputStream和OutputStream作为基类。
字符流操作的数据单元是16位的字符,由Reader和Writer作为基类
第三种:节点流和处理流
按照流的角色来分,可以分为节点流和处理流。
节点流:可以从向一个特定的IO设备(如磁盘、网络)读/写数据的流。也被称为低级流。
处理流:用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能。也称为高级流
节点流和处理流的区别和联系
1.节点流是底层流/低级流,直接跟数据源相接。
2.处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
3.处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连[模拟修饰器设计模式]
处理流的功能主要体现在以下两个方面:
1.性能的提高:主要以增加缓冲的方式来提高输入输出的效率。
2.操作的便捷:处理流可能提供了- -系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便
常见的处理流BufferedReader和BufferedWriter
在关闭处理流时,只关闭外层流即可
字节流通常用来处理二进制文件,视频,音频,图片
/**
* FileInputStream使用(文件-->程序)
*/
public class FileInputStream_ {
public static void main(String[] args) {
// readFile01();
readFile02();
}
//单个字节的读取,效率比较低
public static void readFile01(){
String filePath="D://a.txt";
int readData=0;
FileInputStream fileInputStream=null;
try {
//创建FileInputStream对象,用于读取 文件
fileInputStream = new FileInputStream(filePath);
//一个字节一个字节的读,读取的数据存储在readData里,如果返回-1,则代表读取完毕
while ((readData = fileInputStream.read())!=-1){
System.out.print((char) readData);//转成char输出
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭文件流释放资源
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void readFile02(){
String filePath="D://a.txt";
int readLen=0;
FileInputStream fileInputStream=null;
//添加一个Byte容量设置为10数组
byte\[\] bytes = new byte\[9\];
try {
//创建FileInputStream对象,用于读取文件
fileInputStream = new FileInputStream(filePath);
//从该输入流读取最多10个字节的数据到字节数组。
//如果返回-1,则代表读取完毕
//如果读取正常返回实际读取的字节数
while ((readLen=fileInputStream.read(bytes))!=-1){
System.out.print(new String(bytes,0,readLen));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭文件流释放资源
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
注意先进行 ObjectOutputStream 序列化到 D:\a.dat 文件中 然后才进行的反序列化
public class ObjectInputStream_ {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//指定反序列化的文件
String filePath="D:\\a.dat";
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filePath));
//读取
//反序列的顺序需要和保存的数据的顺序一致,否则会出现异常
System.out.println(objectInputStream.readInt());
System.out.println(objectInputStream.readBoolean());
System.out.println(objectInputStream.readChar());
System.out.println(objectInputStream.readDouble());
System.out.println(objectInputStream.readUTF());
Object dog = objectInputStream.readObject();
System.out.println("运行类型:"+dog.getClass());
System.out.println("dog信息:"+dog);//底层 Object-->Dog
//关闭外层流即可
objectInputStream.close();
}
}
可以看到输出:
public class FileOutputStream_ {
public static void main(String[] args) {
writeFile();
}
/**
* 使用FileOutputStream将数据写入文件中
* 如果数据不存在,则自动创建该文件
*/
public static void writeFile(){
String filePath="D:\\a.txt";
FileOutputStream fileOutputStream=null;
try {
//得到FileOutputStream对象
//1、这种创建方式,写入的内容是覆盖原来的文件中的内容
//2、在构造器中添加 true 为追加填写
fileOutputStream = new FileOutputStream(filePath,true);
//写入一个字节
// fileOutputStream.write('a'); fileOutputStream.write(97);
//写入字符串 str.getBytes()字符串转为字节数组
String str="hollow";
//fileOutputStream.write(str.getBytes());
//也可以指定字节数组中的起始位置,末尾位置
fileOutputStream.write(str.getBytes(),0,str.length());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* ObjectOutputStream的使用,完成数据的序列化
*/
public class ObjectOutputStream_ {
public static void main(String[] args) throws Exception {
//序列化后,保存的格式,不是纯文本,而是按照他的格式来保存
String filePath = "D:\\a.dat";
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据到 D:\\a.bat
objectOutputStream.write(100);//int-->Integer(实现了Serializable)
objectOutputStream.writeBoolean(true);//boolean-->Boolean(实现了Serializable)
objectOutputStream.writeChar('a');//chat-->Character(实现了Serializable)
objectOutputStream.writeDouble(1.1);//double-->Double(实现了Serializable)
objectOutputStream.writeUTF("阿龙学习");//String
//保存一个对象
objectOutputStream.writeObject(new Dog("旺财",5));
objectOutputStream.close();
System.out.println("序列化数据保存完毕");
}
}
//lombok插件
@Data
@AllArgsConstructor
@NoArgsConstructor
//要实现Serializable接口才能够进行序列化
class Dog implements Serializable {
private String name;
private int age;
}
/**
* PrintStream字节打印流
*/
public class PrintStream_ {
public static void main(String[] args) throws IOException {
// System.out 就是 PrintStream
PrintStream out = System.out;
//在默认情况下,默认打印的是标准输出(即 显示器)
out.println("你好");
//因为底层使用的是write,所以可以直接调用write进行打印/输出
out.write("hello,你好!".getBytes(StandardCharsets.UTF_8));
//关闭流。
out.close();
//我们可以修改打印输出流的位置/设备
//修改成"D:\\a.txt"
//这句话将会输出到D:\a.txt
System.setOut(new PrintStream("D:\\a.txt"));
System.out.println("这句话将会输出到D:\\a.txt");
}
}
通常用来处理文本文件,更高效。
public class FileReader_ {
public static void main(String[] args) {
String filePath="d:\\a.txt";
FileReader fileReader=null;
int data= 0;
char[] chars = new char[10];
//1、创建FileReader对象
try {
fileReader = new FileReader(filePath);
//循环读取,使用read(chars),返回的是实际读取到的字符数
//如果返回-1则表示读到文件结尾
while ((data = fileReader.read(chars))!=-1){
System.out.print(new String(chars,0,data));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
BufferedReader类中,有属性Reader,即可以封装一个节点流,该节点流可以是任意的,只要是Reader子类 (BufferedWriter也是一样的操作)
public class BufferedReader_ {
public static void main(String[] args) throws Exception { //异常也可以try catch
String filePath = "D:\\a.txt";
//创建bufferedReader
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
//读取
String line;//按行读取,效率高
//1.bufferedReader.readLine() 按行读取文件
//2.当返回为空时,表示文件读取完毕。
while ((line = bufferedReader.readLine())!=null){
System.out.println(line);
}
//关闭流,只需要关闭外层的流,即bufferedReader,因为底层会自动的去关闭节点流 FileReader
bufferedReader.close();
}
}
/**
* InputStreamReader 转换流解决中文乱码问题
* 将字节流 FileInputStream 转换成字符流 InputStreamReader, 指定编码 gbk/utf-8
*/
public class InputStreamReader_ {
public static void main(String[] args) throws IOException {
String filePath = "D:\\a.txt";
//把 new FileInputStream(filePath) 转成 InputStreamReader 同时指定了编码 utf-8
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(filePath), StandardCharsets.UTF_8);
//把 InputStreamReader 传入 BufferedReader
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String readLine;
while(( readLine = bufferedReader.readLine())!=null){
System.out.println(readLine);
}
bufferedReader.close();
}
}
注意:FileWriter使用后,必须要关闭(close)或刷新(flush)流, 否则写入不到指定的文件!
public class FileWriter_ {
public static void main(String[] args) {
String filePath="D:\\a.txt";
FileWriter fileWriter=null;
String str="哈哈哈哈哈哈哈哈哈";
try {
fileWriter = new FileWriter(filePath,true);//true为追加,不写则覆盖
//fileWriter.write(str);
fileWriter.write(str,0,2);//指定str的某一部分
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class BufferedWriter_ {
public static void main(String[] args) throws IOException {
String filePath="D:\\a.txt";
//创建BufferedWriter
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));//追加要在节点流中进行设置
bufferedWriter.write("红红火火恍恍惚惚红红火火恍恍惚惚吼吼吼1");
//插入一个换行
bufferedWriter.newLine();
bufferedWriter.write("红红火火恍恍惚惚红红火火恍恍惚惚吼吼吼2");
//插入一个换行
bufferedWriter.newLine();
bufferedWriter.write("红红火火恍恍惚惚红红火火恍恍惚惚吼吼吼3");
//关闭外层流即可
bufferedWriter.close();
}
}
/**
* 将字节流FileOutputStream包装成(转换成)字符流OutputStreamWriter,
* 对文件进行写入(按照gbk格式,可以指定其他,比如utf-8/utf8)
*/
public class InputStreamWriter_ {
public static void main(String[] args) throws IOException {//异常直接进行的抛出,也可以try catch
String filePath = "D:\\a.txt";
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(filePath), "gbk");
outputStreamWriter.write("gbk格式的编码");
//关闭流
outputStreamWriter.close();
}
}
public class PrintWriter_ {
public static void main(String[] args) throws IOException {
//创建PrintWriter对象
PrintWriter printWriter = new PrintWriter(new FileWriter("D:\\a.txt"));
//将会打印到 D:\a.txt
printWriter.println("哈喽你好 ");
printWriter.close(); //flush + 关闭流
}
}
load:加载配置文件的键值对到Properties对象
list:将数据显示到指定设备
getProperty(key):根据键获取值
setProperty(key,value):设置键值对到Properties对象
store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果
含有中文,会存储为unicode码
public class Properties_read {
public static void main(String[] args) throws IOException {
//使用Properties读取ycl.properties文件
Properties properties = new Properties();
//加载指定的配置文件
properties.load(new FileReader("src/main/resources/ycl.properties"));
//键值对显示到控制台
properties.list(System.out);
//根据key 获取对应的值
String id = properties.getProperty("id");
System.out.println("id是:"+id);
}
}
public class Properties_writer {
public static void main(String[] args) throws IOException {
//使用Properties类, 创建配置文件,修改配置文件内容
Properties properties = new Properties();
//设置内容
//如果该文件没有对应的key,就是创建
//如果该文件有对应的key,就是修改
properties.setProperty("charset","utf-8");
properties.setProperty("username","小刚");//中文保存的是unicode码
properties.setProperty("pwd","123567894");
//将k-v 存储至文件
properties.store(new FileOutputStream("D:\\\\a.data"),null);
System.out.println("保存成功");
}
}
public class FileCopy {
public static void main(String[] args) {
copy();
}
public static void copy(){
String resourcePath="D:\\壁纸\\1.jpg";
String targetPath="D:\\壁纸\\3.jpg";
FileInputStream fileInputStream=null;
FileOutputStream fileOutputStream=null;
int readLen=0;
try {
fileInputStream = new FileInputStream(resourcePath);
fileOutputStream=new FileOutputStream(targetPath);
//定义一个数组提高效率
byte[] bytes = new byte[1024];
while ((readLen=fileInputStream.read(bytes))!=-1){
//边读边写
fileOutputStream.write(bytes,0,readLen);//必须用这个参数,否则出现文件损失
}
System.out.println("copy完成");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileInputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
BufferedReader和BufferedWriter 是按照字符操作的,不要去操作二进制文件(声音、视频、doc、pdf、图片等等),拷贝后的文件可能会造成文件损坏
public class Buffered_copy {
public static void main(String[] args) {
//源文件路径
String resourcePath = "D:\\a.txt";
//目标文件的路径
String targetPath = "D:\\b.txt";
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
//创建bufferedReader、bufferedWriter
bufferedReader = new BufferedReader(new FileReader(resourcePath));
bufferedWriter = new BufferedWriter(new FileWriter(targetPath,true));//true表示追加写入
String line;
//readLine() 读取一行内容,但是没有换行
while ((line = bufferedReader.readLine()) != null) {
//每读取一行就写入
bufferedWriter.write(line);
//插入换行
bufferedWriter.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//关闭流
if (bufferedReader!=null){
bufferedReader.close();
}
if (bufferedWriter!=null){
bufferedWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* BufferedInputStream、BufferedOutputStream的使用
*/
public class Buffered_copy02 {
public static void main(String[] args) {
String resourcePath = "D:\\壁纸\\2.jpg";
String targetPath = "D:\\壁纸\\4.jpg";
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
//创建对象
bufferedInputStream = new BufferedInputStream(new FileInputStream(resourcePath));
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(targetPath));
int readLen;
byte[] buf = new byte[1024];
//返回读取到的长度,当返回-1时,就表示文件读取完毕
while ((readLen = bufferedInputStream.read(buf))!=-1){
bufferedOutputStream.write(buf,0,readLen);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//关闭外层处理流即可,底层会自动关闭节点流
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (bufferedOutputStream!=null){
bufferedOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章