Day22JavaSE——其他的一些流
文章目录
数据输入输出流
内存操作流
打印流
序列化流
随机访问流
Properties
数据输入输出流
数据输入流: DataInputStream
数据输出流: DataOutputStream
特点: 可以写基本数据类型,可以读取基本数据类型
public class Test1 {
public static void main(String[] args) throws IOException {
/* 数据输入流:
以Stream结尾的 一般都是字节流
DataInputStream
数据输出流:
DataOutputStream
这对流的特点是能够读写基本数据类型*/
//writeData();
//读取数据:怎么写的,就怎么读,顺序不要乱
writeData();
DataInputStream in = new DataInputStream(new FileInputStream("a.txt"));
int i = in.readInt();
System.out.println(i);
boolean b = in.readBoolean();
System.out.println(b);
double v = in.readDouble();
System.out.println(v);
char c = in.readChar();
System.out.println(c);
String s = in.readUTF();
System.out.println(s);
in.close();
}
private static void writeData() throws IOException {
//写入基本数据类型
DataOutputStream out = new DataOutputStream(new FileOutputStream("a.txt"));
out.writeInt(50000);
out.writeBoolean(true);
out.writeDouble(3.141592654);
out.writeChar('你');
out.writeUTF("法国和结构化分级");
out.close();
}
}
内存操作流
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1fzJLeIG-1591948053349)(https://s1.ax1x.com/2020/06/11/tH4hm8.png)]
概述
/*
* 内存操作流:不直接去关联文件,只是在内存中进行数据读写
* 站在内存之外去理解函数的功能更加的号理解
* 内存操作流有三对
* 1、操作字节数组
* ByteArrayOutputStream
* ByteArrayInputStream
* 此流关闭无效,所以无需关闭
* 2、操作字符数组
* CharArrayWrite
* CharArrayReader
* 3、操作字符串
* StringWriter
* StringReader*/
public class Test1 {
public static void main(String[] args) throws IOException {
System.out.println("=============操作字节数组=============");
/*ByteArrayOutputStream
ByteArrayInputStream
关闭无效,无需关闭*/
/*此类实现了一个输出流,其中的数据被写入一个byte数组
* 缓冲区会随着数据的不断写入而自动增长
* 可使用toByteArray () 和 toString () 获取数据*/
ByteArrayOutputStream out = new ByteArrayOutputStream();
String str="好好学习";
String str2="天天向上";
String str3="爱生活";
String str4="爱Java";
byte[] bytes = str.getBytes();
byte[] bytes1 = str2.getBytes();
byte[] bytes2 = str3.getBytes();
byte[] bytes3 = str4.getBytes();
//把字节数组写入创建的字节数组输出流中
out.write(bytes);
out.write(bytes1);
out.write(bytes2);
out.write(bytes3);
//取出ByteArrayOutputStream 他所维护的那个字节数组中的字节数据
byte[] allBytes = out.toByteArray();
//将字节数组转换成字符串
String s = new String(allBytes);
System.out.println(s);
//直接从字节流中变成字符串
System.out.println(out.toString());
System.out.println("=============读取文件=============");
/* ByteArrayInputStream(byte[] buf)
创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。*/
ByteArrayOutputStream out1 = new ByteArrayOutputStream();
String str5="好好学习";
String str6="天天向上";
String str7="爱生活";
String str8="爱Java";
byte[] bytes5 = str5.getBytes();
byte[] bytes6 = str6.getBytes();
byte[] bytes7 = str7.getBytes();
byte[] bytes8 = str8.getBytes();
//把上面4个字节数组中的数据,统一写入ByteArrayOutputStream 自己所维护的那个字节数组中国
out1.write(bytes5);
out1.write(bytes6);
out1.write(bytes7);
out1.write(bytes8);
//取出ByteArrayOutputStream 他所维护的那个字节数组中的字节数据
byte[] allByte1 = out1.toByteArray();
ByteArrayInputStream in = new ByteArrayInputStream(allByte1);
byte[] cachBytes = new byte[1024 * 8];
int len = in.read(cachBytes);//将维护的缓冲区内容读取到新建字节数组中
System.out.println(new String(cachBytes, 0, len));
out1.close();
in.close();
System.out.println("=============操作字符数组=============");
/*CharArrayWrite 他维护的缓冲区是一个字符数组
CharArrayReader*/
CharArrayWriter charArrayWriter = new CharArrayWriter();
String s1 = "好好学习";
String s2 = "天天向上";
String s3 = "爱生活";
String s4 = "爱Java";
charArrayWriter.write(s1);
charArrayWriter.write(s2);
charArrayWriter.write(s3);
charArrayWriter.write(s4);
//取出CharArrayWrite所维护的字符数组
char[] allChar = charArrayWriter.toCharArray();
String s5 = new String(allChar);
System.out.println(s5);
//toString也可以直接转换为字符串
System.out.println(charArrayWriter.toString());
System.out.println("=============操作字符串=============");
/*操作字符串
StringWriter 他底层用的是StringBuffer 来充当缓冲区
StringReader*/
StringWriter writer = new StringWriter();
writer.write("abc");
writer.write("abc");
writer.write("abc");
writer.write("abc");
writer.write("abc");
String s6 = writer.toString();
System.out.println(s);
}
}
合并多个文件
内存操作流实现
public class Test {
public static void main(String[] args) {
//1、将要操作的两首歌文件封装成文件数据
File file = new File("C:\\Users\\adair_liu\\Desktop\\复试资料\\Jam - 七月上.mp3");
File file1 = new File("C:\\Users\\adair_liu\\Desktop\\复试资料\\崔健 - 新长征路上的摇滚.mp3");
//再将这两个文件封装成流
FileInputStream in1=null;
FileInputStream in2=null;
try {
in1 = new FileInputStream(file);
in2 = new FileInputStream(file1);
//创建列表将这两个文件对象存入列表,方便遍历
ArrayList<FileInputStream> list = new ArrayList<>();
list.add(in1);
list.add(in2);
//遍历集合,读取两首歌的字节数据,并把两首歌的字节数据,放到内存操作流所维护的字节数组中
//这个流是从外部将数据输给内存中的字节数组
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024 * 8];
int len=0;
for (FileInputStream fin : list) {
while ((len = fin.read(buf)) != -1) {
out.write(buf,0,len);
}
//释放读取文件流的资源
fin.close();
}
//将两首歌的字节数据从操作流维护的字节数组中取出来
byte[] allBytes = out.toByteArray();
//把两首歌文件放到一个文件中
//创建一个流,这个流是从内存中读取数据
ByteArrayInputStream in = new ByteArrayInputStream(allBytes);
FileOutputStream outFile = new FileOutputStream("C:\\Users\\adair_liu\\Desktop\\1.MP3");
byte[] bufOut = new byte[1024 * 8];
int len1=0;
//将内存中都取出来的数据通过输出流写到指定的文件夹中
while ((len1 = in.read(bufOut)) != -1) {
outFile.write(bufOut,0,len1);
}
outFile.close();
in1.close();
in2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用字节流和列表实现
public class Test2 {
public static void main(String[] args) {
//将多个文件合并成一个没必要使用内存操作流来中传数据
FileInputStream in1 = null;
FileInputStream in2 = null;
FileOutputStream out = null;
try {
in1 = new FileInputStream("C:\\Users\\adair_liu\\Desktop\\复试资料\\Jam - 七月上.mp3");
in2 = new FileInputStream("C:\\Users\\adair_liu\\Desktop\\复试资料\\崔健 - 新长征路上的摇滚.mp3");
out = new FileOutputStream("C:\\Users\\adair_liu\\Desktop\\2.MP3");
ArrayList<FileInputStream> inDataList = new ArrayList<>();
inDataList.add(in1);
inDataList.add(in2);
byte[] buff = new byte[1024 * 8];
int len = 0;
for (FileInputStream in : inDataList) {
while ((len=in.read(buff)) != -1) {
out.write(buff,0,len);
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try{
if(in1!=null){
in1.close();
}
if(in2!=null){
in2.close();
}
if(out!=null){
out.close();
}
} catch (IOException e){
e.printStackTrace();
}
}
}
}
打印流
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HovJsKn2-1591948053350)(https://s1.ax1x.com/2020/06/11/tH5GB8.png)]
概述
字节流打印流
字符打印流
public class Test1 {
public static void main(String[] args) throws IOException {
//打印流:就是单个的,只能往出写数据,
//打印流:字符打印流。字节打印流
System.out.println("==========字符打印流==========");
//PrintWriter
/* PrintWriter(File file)
使用指定文件创建不具有自动行刷新的新 PrintWriter。
PrintWriter(String fileName)
创建具有指定文件名称且不带自动行刷新的新 PrintWriter。*/
PrintWriter printWriter = new PrintWriter(new File("b.txt"));
printWriter.write("abc");
printWriter.write("\r\n");
//输出并换行
printWriter.println("aaaaaaaaaaaaaa");
printWriter.println(200);
printWriter.println(true);
printWriter.flush();
printWriter.close();
/*PrintWriter(OutputStream out, boolean autoFlush)
通过现有的 OutputStream 创建新的 PrintWriter。
PrintWriter(Writer out, boolean autoFlush)
创建新 PrintWriter。*/
//参数2:true开启自动刷新
/*如果启用了自动刷新,则只有在调用 println、printf 或 format
的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。*/
PrintWriter writer = new PrintWriter(new FileWriter("c.txt"), true);
writer.print("abc555555");
writer.println("cccc");
writer.println("cccc");
writer.println("cccc");
writer.println("cccc");
writer.println("cccc");
writer.close();
System.out.println("==========字节打印流==========");
//PrintStream 字节打印流 单个的,只能输出数据。
/*PrintStream(File file)
创建具有指定文件且不带自动行刷新的新打印流。
PrintStream(File file, String csn)
创建具有指定文件名称和字符集且不带自动行刷新的新打印流。
PrintStream(OutputStream out)
创建新的打印流。
PrintStream(String fileName)
创建具有指定文件名称且不带自动行刷新的新打印流。
PrintStream(String fileName, String csn)
创建具有指定文件名称和字符集且不带自动行刷新的新打印流。*/
//创建一个字节打印流,就关联一个文件,文件不存在会自动创建
PrintStream stream = new PrintStream("d.txt");
stream.write("nihao".getBytes());
stream.println("sbc");
stream.println(2000);
stream.println(true);
stream.flush();
stream.close();
System.out.println("==================================");
//我们通过System类中的静态变量in 可以获取出一个PrintStream字节打印流 调用输出的方法时输出的目的地是屏幕
//System类的属性 out标准输出流。此流已打开并准备接受输出数据。通常,此流对应于显示器输出
PrintStream out = System.out;
out.write("asdfasdfasdfasdf".getBytes());
out.println("aaaaaaaaaaa");
out.println("aaaaaaaaaaa");
out.println("aaaaaaaaaaa");
out.println("aaaaaaaaaaa");
out.println("aaaaaaaaaaa");
out.println("aaaaaaaaaaa");
}
}
打印流复制文件
public class Test2 {
public static void main(String[] args) throws IOException {
/* A:
案例演示:
打印流复制文本文件*/
//使用BufferReader读取,用PrintWriter输出
BufferedReader reader = new BufferedReader(new FileReader("b.txt"));
PrintWriter printWriter = new PrintWriter(new FileWriter("copy.txt"), true);
String line=null;
while ((line = reader.readLine()) != null) {
printWriter.println(line);
}
reader.close();
printWriter.close();
}
}
标准输入输出流概述和输出语句的本质
概述
在System这个类中存在两个静态的成员变量:
public static final InputStream in: 标准输入流, 对应的设备是键盘
public static final PrintStream out: 标准输出流 , 对应的设备就是显示器
System.in的类型是InputStream.
System.out的类型是PrintStream是OutputStream的孙子类FilterOutputStream 的子类.
public class Test1 {
public static void main(String[] args) throws IOException {
//in
//public static final InputStream in“标准”输入流。
// 此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。
//Scanner scanner = new Scanner(System.in);
/*Scanner(File source)
构造一个新的 Scanner,它生成的值是从指定文件扫描的。
Scanner(InputStream source)
构造一个新的 Scanner,它生成的值是从指定的输入流扫描的。*/
//Scanner 关联文件,从文件中一行一行扫描数据
Scanner sc = new Scanner(new File("b.txt"));
while (sc.hasNextLine()) {
String s = sc.nextLine();
System.out.println(s);
}
}
}
用Scanner和PrintWriter 配合来复制文件
public class Test2 {
public static void main(String[] args) throws IOException {
//我们用Scanner和PrintWriter 配合来复制文件
Scanner sc = new Scanner(new File("b.txt"));
//开启自动刷新
PrintWriter writer = new PrintWriter(new FileWriter("ccc.txt"), true);
while ((sc.hasNextLine())) {
String s = sc.nextLine();
writer.println(s);
}
sc.close();
writer.close();
}
}
二种方式实现键盘录入
A:Scanner
B:BufferedReader的readLine方法。
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public class Test3 {
public static void main(String[] args) throws IOException {
//键盘录入的第二种方式
//in
//public static final InputStream in“标准”输入流。
// 此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。
// Scanner scanner = new Scanner(System.in);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.println("请输入数据");
String s = reader.readLine();
//自己定义一个结束标记
if ("886".equals(s)) {
break;
}
System.out.println(s);
}
}
}
随机访问流
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YIPgXRIN-1591948053352)(https://s1.ax1x.com/2020/06/11/tHTWCQ.png)]
概述
A:随机访问流概述
RandomAccessFile概述 最大特点 能读能写
RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能。
支持对随机访问文件的读取和写入。
RandomAccessFile的父类是Object , 这个流对象可以用来读取数据也可以用来写数据.可以操作任意数据类型的数据.
我们可以通过getFilePointer方法获取文件指针,并且可以通过seek方法设置文件指针
public class Test {
public static void main(String[] args) throws IOException {
RandomAccessFile read = new RandomAccessFile("C:\\Users\\adair_liu\\Desktop\\复试资料\\[迅雷下载Www.99b.Cc]入殓师1280x720日语中字版.mp4", "r");
File file = new File("1.MP4");
RandomAccessFile write = new RandomAccessFile(file, "rw");
byte[] buffer = new byte[1024 * 10];
copyStop(read,write,file,buffer);
//copyMp4(read,write,file,buffer);
}
public static void copyStop(RandomAccessFile read,RandomAccessFile write,File file,byte[] buffer) throws IOException {
int flag=0;
int i=1;
try {
while ((flag = read.read(buffer)) != -1) {
//使用一个异常去模拟暂停
if(i++>30) {
//出现异常直接去catch,不会再执行 后面的写操作
//缓存区一次读取8Kb,i加到第31次碰见异常跳出
//相当于用户在下载到8kb*30的数据的时候暂停了,去执行catch的逻辑
System.out.println(1 / 0);
}
write.write(buffer);
}
} catch (Exception e) {
/*long l = System.currentTimeMillis();
Date date = new Date(l);
String pointFileName = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);*/
//当复制或下载文件过程当中遇到了异常或用户手动暂停,我们就把文件当前的指针位置,存到一个配置文件中,
//为了用户下次继续复制或下载时,把这个位置读取回去,从这个位置开始继续读写。
long interrupt = read.getFilePointer();
System.out.println(interrupt);
//创建打印流文件对象,以系统当前时间为文件名
PrintWriter printWriter = new PrintWriter("pointStop.txt");
//打印输出
printWriter.println(interrupt);
//刷新
printWriter.flush();
//关闭输出流
printWriter.close();
e.printStackTrace();
}
}
public static void copyMp4(RandomAccessFile read,RandomAccessFile write,File file,byte[] buffer) throws IOException {
RandomAccessFile point = new RandomAccessFile("pointStop.txt", "r");
if(!file.exists()){
read.seek(0);
write.seek(0);
}else if(file.exists()){
read.seek(point.readInt());
write.seek(point.readInt());
}
int flag=0;
while ((flag = read.read(buffer)) != -1) {
write.write(buffer);
}
}
}
随机访问流设置文件指针
//RandomAccessFile概述 最大特点 能读能写而且有一个文件指针,可以控制指针的位置。
/*此类的实例支持对随机访问文件的读取和写入。
随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。
存在指向该隐含数组的光标或索引,称为文件指针;
输入操作从文件指针开始读取字节,
并随着对字节的读取而前移此文件指针。*/
/*RandomAccessFile(File file, String mode)
mode "r"一个 ,"rw","rws",或 "rwd"
创建一个随机访问文件流从File参数指定的文件中读取,并可选地写入文件。
RandomAccessFile(String name, String mode)
创建随机访问文件流,以从中指定名称的文件读取,并可选择写入文件。*/
public class Test1 {
public static void main(String[] args) throws IOException {
writeData();
RandomAccessFile rw = new RandomAccessFile(new File("b.txt"), "rw");
//怎么写就怎么读
System.out.println("============文件指针操作============");
int i = rw.readInt();
System.out.println(i);
System.out.println("----------");
System.out.println(rw.length());
System.out.println("----------");
//这个流会经常用到,因为可以通过构造方法设置文件模式还可以同时读写文件
/*long getFilePointer()
返回此文件中的当前偏移量。 此函数可以获取文件指针的位置*/
/*void seek(long pos)
设置文件指针偏移,从该文件的开头测量,发生下一次读取或写入 */
long filePointer = rw.getFilePointer();
System.out.println("文件指针的位置"+filePointer);
boolean b = rw.readBoolean();
System.out.println(b);
long filePointer1 = rw.getFilePointer();
System.out.println("文件指针的位置"+filePointer1);
String s = rw.readLine();
System.out.println(s);
long filePointer2 = rw.getFilePointer();
System.out.println("文件指针的位置"+filePointer2);
//设置文件指针
rw.seek(3);
int read = rw.readInt();
System.out.println(read);
long filePointer3 = rw.getFilePointer();
System.out.println("文件指针的位置"+filePointer3);
System.out.println("=================");
/*rw.readChar();
System.out.println(rw.getFilePointer());*/
rw.seek(1);
String s1 = rw.readUTF();
System.out.println(s1);
long filePointer4 = rw.getFilePointer();
System.out.println("文件指针的位置"+filePointer4);
}
private static void writeData() throws IOException {
//rw可读可写
RandomAccessFile w = new RandomAccessFile("b.txt", "rw");
w.writeInt(100);
w.writeChar('a');
w.writeUTF("随机访问流");
w.close();
}
}
随机访问流模拟文件复制的暂停与开始
public class Test2 {
public static void main(String[] args) throws IOException {
/**
* 使用一个异常来代表用户暂停下载文件,暂停时文件指针存储在pointStop.txt文件里
* 继续下载请看Test3例程*/
//复制文件,可以暂停继续
//下载:断点下载
RandomAccessFile read = new RandomAccessFile("C:\\Users\\Administrator\\Desktop\\WeChat Files\\[迅雷下载Www.99b.Cc]入殓师1280x720日语中字版.mp4", "rw");
File file = new File("[迅雷下载Www.99b.Cc]入殓师1280x720日语中字版.mp4");
RandomAccessFile write = new RandomAccessFile(file, "rw");
byte[] buffer = new byte[1024 * 8];
//stopDownlode(read,write,buffer);
Downlode(file,read,write,buffer);
}
public static void stopDownlode(RandomAccessFile read,RandomAccessFile write,byte[] buffer) throws IOException {
int flag=0;
int i=1;
try {
while ((flag = read.read(buffer)) != -1) {
//使用一个异常去模拟暂停
if(i++>30) {
//出现异常直接去catch,不会再执行 后面的写操作
//缓存区一次读取8Kb,i加到第31次碰见异常跳出
//相当于用户在下载到8kb*30的数据的时候暂停了,去执行catch的逻辑
System.out.println(1 / 0);
}
write.write(buffer);
}
} catch (Exception e) {
/*long l = System.currentTimeMillis();
Date date = new Date(l);
String pointFileName = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);*/
//当复制或下载文件过程当中遇到了异常或用户手动暂停,我们就把文件当前的指针位置,存到一个配置文件中,
//为了用户下次继续复制或下载时,把这个位置读取回去,从这个位置开始继续读写。
long interrupt = read.getFilePointer();
System.out.println(interrupt);
//创建打印流文件对象,以系统当前时间为文件名
PrintWriter printWriter = new PrintWriter("pointStop.txt");
//打印输出
printWriter.println(interrupt);
//刷新
printWriter.flush();
//关闭输出流
printWriter.close();
e.printStackTrace();
}
}
public static void Downlode(File file,RandomAccessFile read,RandomAccessFile write,byte[] buffer) throws IOException {
/**
* 在Test2中我们利用一个异常暂停了下载并记录了下载暂停时的文件指针位置
* 在这个例程中我们将写出继续下载的逻辑
* 1、先判断之前没下载完的文件是否还存在
* 2、不存在将读取文件指针设为0,将写入文件指针设为0
* 3、存在就读取存在指针配置文件中的暂停时的指针地址,并开始继续写入*/
//逻辑严谨性,先判断之前文件是否存在
if(!file.exists()){
//将写入和读取文件指针都设置为0
/*read.seek(0);*/
write.seek(0);
}else{
//断点应该设置断点文件里配置的值
RandomAccessFile point = new RandomAccessFile("pointStop.txt","r");
int pointInterruptNum = new Integer(point.readLine()).intValue();
read.seek(pointInterruptNum);
write.seek(pointInterruptNum);
}
int flag=0;
while ((flag = read.read(buffer)) != -1) {
write.write(buffer);
}
}
}
序列化流
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fw7dNQDz-1591948053354)(https://s1.ax1x.com/2020/06/11/tH7WdK.png)]
概述
//序列化和反序列化
//序列化:将Java对象保存到文件中---->out---->write
//反序列化:将文件中的对象读取回来---->in---->read
//这对流能够对Java对象进行读写
/*序列化流: ObjectOutputStream
反序列化流: ObjectInputStream*/
public class Test1 {
public static void main(String[] args) {
System.out.println("==========写入对象==========");
/* try {
writeData();
} catch (IOException e) {
e.printStackTrace();
}*/
System.out.println("==========读取对象==========");
try {
readData();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private static void readData() throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.txt"));
//反序列化
Object obj = in.readObject();//读取出来的是Object类型,需要向下转型
Student stu = (Student) obj;
System.out.println(stu);
in.close();
}
private static void writeData() throws IOException {
Student student = new Student("张三", 23,"女");
/**
ObjectOutputStream(OutputStream out)
创建一个写入指定的OutputStream的ObjectOutputStream*/
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student.txt"));
//把Java对象写入文件中
//1、当我们去序列化一个Java对象时,要求我们这个对象所对应的类,必须实现一个序列化接口Serializable
out.writeObject(student);
out.close();
}
}
如何解决序列化时候的黄色警告线问题
public class Student implements Serializable {
//要序列化这个Java对象,要求我们这个类必须实现Serializable这个接口
//Serialiazble是一个标记接口,告诉虚拟机这个类要序列化,与Cloneable用法相同
private String name;
private String sex;
private int age;
public Student() {
}
public Student(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
/**
* 我们的一个类可以被序列化的前提是需要这个类实现Serializable接口,就需要给这个类添加一个标记.
* 在完成序列化以后,序列化文件中还存在一个标记,然后在进行反序列化的时候,
* 会验证这个标记和序列化前的标记是否一致,如果一致就正常进行反序列化,如果
* 不一致就报错了. 而现在我们把这个类做了修改,将相当于更改了标记,而导致这两个标记不一致,就报错了
*/
//固定UID标记
public static final long serialVersionUID = 42L;
/**
* 解决问题: 只要让这个两个标记一致,就不会报错了吧
* 怎么让这两个标记一致呢? 不用担心,很简单,难道你们没有看见黄色警告线吗? alt+enter, 生成出来
*/
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;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name) &&
Objects.equals(sex, student.sex);
}
@Override
public int hashCode() {
return Objects.hash(name, sex, age);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
'}';
}
}
public class Test2 {
public static void main(String[] args) {
Student student = new Student("小张", 88, "男");
/*try {
writeData(student);
} catch (IOException e) {
e.printStackTrace();
}*/
try {
readData();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private static void writeData(Student student) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student1.txt"));
out.writeObject(student);
out.close();
}
private static void readData() throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("student1.txt"));
System.out.println(in.readObject());
in.close();
}
}
如何让对象的成员变量不被序列化
使用transient关键字声明不需要序列化的成员变量
private transient int age ;// 可以阻止成员变量的序列化使用transient
public class Test3 {
public static void main(String[] args) {
//如果我们要序列化多个对象,我们可以把这多个对象存入一个容器中,再将容器序列化
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("小张",25,"男"));
list.add(new Student("小胡",33,"男"));
list.add(new Student("小倩",14,"女"));
/*try {
writeData(list);
} catch (IOException e) {
e.printStackTrace();
}*/
try {
readData();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private static void writeData(ArrayList<Student> list) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("stu.txt"));
out.writeObject(list);
out.close();
}
private static void readData() throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("stu.txt"));
System.out.println(in.readObject());
in.close();
}
}
Properties的特殊功能使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7R2dd3aN-1591948053355)(https://s1.ax1x.com/2020/06/11/tHHnSJ.png)]
A:Properties的特殊功能
public Object setProperty(String key,String value)
public String getProperty(String key)
public Set<String> stringPropertyNames()
概述
//属性集合
//Properties继承自Hashtable,是一个双列集合
//我们经常使用这个集合来读取配置文件
//Properties规定了键和值都是String类型
/***
* 构造函数
* Properties()
* 创建一个没有默认值的空属性列表。
* Properties(Properties defaults)
* 创建具有指定默认值的空属性列表。*/
public class Test1 {
public static void main(String[] args) {
Properties properties = new Properties();
//添加元素
properties.put("小张","s003");
properties.put("小胡","s004");
//获取元素
String xiaoZhang =(String) properties.get("小张");
System.out.println(xiaoZhang.toString());
//获取元素我们推荐使用其特有的方法来存取
properties.setProperty("小李","s005");
properties.setProperty("小王","s006");
System.out.println(properties.getProperty("小李"));
System.out.println(properties.getProperty("小王"));
//键未找到值,返回null
System.out.println(properties.getProperty("user"));
//特有的获取元素的函数第二个参数
//参数2:是一个默认值,如果通过键没找到这个对应的值,就返回默认值
System.out.println(properties.getProperty("userName", "NotFoundError"));
}
}
public class Test2 {
public static void main(String[] args) throws IOException {
//将双列集合中的数据,存储到文本文件中保存
//存储的样子如下
//usename=zhangsan
//password=123456
//email=westos@163.com
HashMap<String, String> userName = new HashMap<>();
userName.put("username","adair");
userName.put("password","123456789");
userName.put("email","adair@qq.com");
PrintWriter out = new PrintWriter(new FileOutputStream(new File("user.properties")), true);
userName.forEach(new BiConsumer<String, String>() {
@Override
public void accept(String key, String value) {
out.println(key+" ==== "+value);
}
});
out.close();
System.out.println("==============================");
//第二种方法调用Properties里面的store函数将集合中的数据输入到配置文件中
Properties properties = new Properties();
properties.setProperty("username","Tom");
properties.setProperty("password","4567921324");
properties.setProperty("email","Tom@qq.com");
properties.store(new FileWriter("user2.properties"),null);
}
}
Properties的load()和store()功能
public class Test3 {
public static void main(String[] args) throws IOException {
//有一个配置文件,其内容是键值对
//如何将配置文件中的数据读到双列集合中
System.out.println("==============方式1==============");
HashMap<String, String> data = new HashMap<>();
//创建一个高效的输入流
BufferedReader reader = new BufferedReader(new FileReader("user.properties"));
String s = reader.readLine();
//将读取进来的字符串分割成两个字符串数组
String[] s1 = s.split("=+");
data.put(s1[0],s1[1]);
System.out.println(data);
System.out.println("==============方式2==============");
//使用Properties中特有的方法
//Properties 属性集合来取读取配置文件,要求配置文件的中的数据 键和值是以=来拼接的
//一般属性配置文件的后缀名会以 .properties作为扩展名
Properties properties = new Properties();
//把配置文件中的键值对数据读到属性集合中
properties.load(new FileInputStream("user.properties"));
System.out.println(properties);
System.out.println(properties.getProperty("username"));
String password = properties.getProperty("password");
System.out.println(password);
}
}
判断文件中是否有指定的键如果有就修改值的
分析:
- a: 把文本文件中的数据加载到Properties集合中
- b: 判断这个集合中是否有"lisi"这个键
- 如果有直接修改其值为100
- c: 把集合中的数据再次存储到文本文件中
SequenceInputStream
概述
public class Test {
public static void main(String[] args) throws IOException {
/** A:
案例需求:
将a.txt和b.txt两个文本文件的内容合并到c.txt*/
/**SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,
并从第一个输入流开始读取,直到到达文件末尾,
接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。*/
FileInputStream in1 = new FileInputStream("user.properties");
FileInputStream in2 = new FileInputStream("user2.properties");
/**构造函数
* SequenceInputStream(InputStream s1, InputStream s2)
通过记住这两个参数来初始化新创建的
SequenceInputStream
(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。*/
SequenceInputStream in = new SequenceInputStream(in1, in2);
FileOutputStream out = new FileOutputStream("all.properties");
int len=0;
byte[] buffer = new byte[1024];
while ((len = in.read(buffer)) != -1) {
out.write(buffer,0,len);
}
in.close();
out.close();
}
}
public class Test2 {
public static void main(String[] args) throws IOException {
FileInputStream in1 = new FileInputStream("user.properties");
FileInputStream in2 = new FileInputStream("user2.properties");
FileInputStream in3 = new FileInputStream("yonghu2.properties");
SequenceInputStream in = new SequenceInputStream(in1, in2);
SequenceInputStream in5 = new SequenceInputStream(in, in3);
FileOutputStream out = new FileOutputStream("all2.properties");
int len = 0;
byte[] bytes = new byte[1024];
while ((len = in5.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
in5.close();
out.close();
}
}
节。*/
SequenceInputStream in = new SequenceInputStream(in1, in2);
FileOutputStream out = new FileOutputStream(“all.properties”);
int len=0;
byte[] buffer = new byte[1024];
while ((len = in.read(buffer)) != -1) {
out.write(buffer,0,len);
}
in.close();
out.close();
}
}
```java
public class Test2 {
public static void main(String[] args) throws IOException {
FileInputStream in1 = new FileInputStream("user.properties");
FileInputStream in2 = new FileInputStream("user2.properties");
FileInputStream in3 = new FileInputStream("yonghu2.properties");
SequenceInputStream in = new SequenceInputStream(in1, in2);
SequenceInputStream in5 = new SequenceInputStream(in, in3);
FileOutputStream out = new FileOutputStream("all2.properties");
int len = 0;
byte[] bytes = new byte[1024];
while ((len = in5.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
in5.close();
out.close();
}
}