0


《JavaSE-第十五章》之文件(二)

前言

在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!”

博客主页:KC老衲爱尼姑的博客主页

博主的github,平常所写代码皆在于此

刷题求职神器

共勉:talk is cheap, show me the code

作者是爪哇岛的新手,水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!


File(二)

文章目录

转换流

由于文件编码与代码文件编码不一致,从而会导致乱码,为了解决上述问题,可以使用转换流,在将数据输入和输出时指定流的编码格式与文件的编码格式保持一致。

字符输入转换流

字符输入转换流:InputStreamReader,可以把原始的字节流按照指定编码转换成字符输入流。
构造器说明public InputStreamReader(InputStream is ,String charset)可以把原始的字节流按照指定编码转换成字符输入流,这样字符流中的字符就不乱码了
代码示例

packagecom.kc.system.io;importjava.io.*;publicclassInputStreamReaderDemo01{//代码UTF-8publicstaticvoidmain(String[] args)throwsException{InputStream is =newFileInputStream("./bbb.txt");//GBK// 把原始字节流转换成字符输入流// Reader isr = new InputStreamReader(is); // 默认以UTF-8的方式转换成字符流。 还是会乱码的  跟直接使用FileReader是一样的Reader isr =newInputStreamReader(is ,"GBK");// 以指定的GBK编码转换成字符输入流  完美的解决了乱码问题BufferedReader br =newBufferedReader(isr);String line;while((line = br.readLine())!=null){System.out.println(line);}}}

字符输出转换流
字符输入转换流:OutputStreamWriter,可以把字节输出流按照指定编码转换成字符输出流。
构造器说明public OutputStreamWriter(OutputStream os,String charset)可以把原始的字节输出流按照指定编码转换成字符输出流(重点)
代码示例

packagecom.kc.system.io;publicclassOutputStreamWriterDemo02{publicstaticvoidmain(String[] args)throwsException{// 1、定义一个字节输出流OutputStream os =newFileOutputStream("./bbb.txt");// 2、把原始的字节输出流转换成字符输出流// Writer osw = new OutputStreamWriter(os); // 以默认的UTF-8写字符出去 跟直接写FileWriter一样Writer osw =newOutputStreamWriter(os ,"GBK");// 指定GBK的方式写字符出去// 3、把低级的字符输出流包装成高级的缓冲字符输出流。BufferedWriter bw =newBufferedWriter(osw);

        bw.write("今天天气真好");
        bw.write("今天天气真好");
        bw.write("今天天气真好");

        bw.close();}}

打印流

打印流可以实现方便、高效的打印数据到文件中去。打印流一般是指:PrintStream,PrintWriter两个类。这两个类分类继承FilerOutStream,Writer。打印流可以看做是输出流的升级版。可以实现打印什么数据就是什么数据,例如打印整数97写出去就是97,打印boolean的true,写出去就是true,打印Hello World,写出去就是Hello World。

PrintStream构造器
构造器说明public PrintStream(OutputStream os)打印流直接通向字节输出流管道public PrintStream(File f)打印流直接通向文件对象public PrintStream(String filepath)打印流直接通向文件路径
方法
方法说明public void print(Xxx xx)打印任意类型的数据出去
PrintWriter构造器
构造器说明public PrintWriter(OutputStream os)打印流直接通向字节输出流管道public PrintWriter (Writer w)打印流直接通向字符输出流管道public PrintWriter (File f)打印流直接通向文件对象public PrintWriter (String filepath)打印流直接通向文件路径
方法
方法说明public void print(Xxx xx)打印任意类型的数据出去
代码示例

packagecom.kc.system.io;importjava.io.*;/**
 * PrintWriter 继承Writer
 * PrintStream 继承自FilerOutStream
 */publicclassPrintDemo{publicstaticvoidmain(String[] args)throwsFileNotFoundException{//可追加数据//        PrintStream ps= new PrintStream(new FileOutputStream("bbb.txt",true));//        ps.println("Hello World");//        ps.print("今天是10月25日");//        ps.close();//PrintStream和PrintWriter的使用方式几乎一样PrintWriter pw=newPrintWriter("bbb.txt");
        pw.println("今天天气真好");
        pw.println(12);
        pw.println(12.09);
        pw.println('a');
        pw.println(true);
        pw.println(97);
        pw.close();}}

输出语句重定向

重定向:可以将输出语句打印位置改为某个文件

代码示例

packagecom.kc.system.io;importjava.io.FileNotFoundException;importjava.io.PrintStream;/**
 * PrintStream 继承自FilerOutStream
 */publicclassPrintDemo2{publicstaticvoidmain(String[] args)throwsFileNotFoundException{System.out.println("我为如来,又有何惧?");System.out.println("相遇皆是缘缘尽莫强求。");//重定向到bbb.txt文件PrintStream ps =newPrintStream("bbb.txt");//改变语句的重定向System.setOut(ps);System.out.println("他宁愿死,也不肯输。");System.out.println("如来是什么,如是道来。");}}

上述重定向前

重定向后

在这里插入图片描述

序列化

对象序列化

序列化:以堆内存为基准,将生活在这上面的对象,通过某种的方式,以二进制的形式保存到硬盘上。
在这里插入图片描述

对象序列化API

使用对象字节输出流:ObjectOutStream

ObjectOutStream构造器
构造器说明public ObjectOutputStream(OutputStream out)把低级字节输出流包装成高级的对象字节输出流
ObjectOutStream方法
方法说明public final void writeObject(Object obj)把对象写出去到对象序列化流的文件中去

对象反序列化

反序列化:以堆内存为基准,将存放在硬盘上的对象数据还原对象。

在这里插入图片描述

反序列化

使用对象字节输入流:ObjectInputStream

ObjectInputStream构造方法
构造器说明public ObjectInputStream(InputStream out)把低级字节输如流包装成高级的对象字节输入流
反序列化的方法
方法说明public Object readObject()把存储到磁盘文件中去的对象数据恢复成内存中的对象返回

序列化ID

通常在序列化的时候会给类加上一个字段serialVersionUID,这个字段就是序列化ID

privatestaticfinallong serialVersionUID =-4985775903060349049L;
序列化ID的作用

序列化ID是为了保证能够成功反序列化的成功,在进行反序列化的过程中,JVM会将来自输入流的当中的序列化ID和本地实体类的ID进行,若ID相同则说明保存在硬盘上的对象数据是该类所实例化的对象,反之则不能反序列化成功。如果在类中没有手动添加一个序列化ID,编译时会默认分配一个序列化ID,这样就会导致一个问题,那就是如果我们再次向类中添加字段时,重新编译就意味着重新分配一个序列化ID,假设没有添加字段前序列化后的对象数据为版本一,添加字段后,再次反序列化,此时由于实体类和序列化对象的ID不一致,就会导致序列化失败,为了解决上述问题可以一开始就手动添加一个类型为long的serialVersionUID,值保证不变,这种情况下,无论后序对类进行修改,编译时,总是使用自己手动加的,就不会出现反序列化失败了。

SerializeUtil

将上述序列化以及反序列化的方法封装成一个工具类,以便后续重复使用。

packagecom.kc.system.io;importjava.io.*;publicclassSerializeUtil{//序列化,将对象转换成二进制publicstaticvoidsaveObject(Object object)throwsIOException{ObjectOutputStream oos =null;OutputStream out =null;try{
            out =newFileOutputStream("D:/demo.txt");
            oos =newObjectOutputStream(out);
            oos.writeObject(object);}catch(FileNotFoundException e){
            e.printStackTrace();}catch(IOException e){
            e.printStackTrace();}finally{
            out.close();
            oos.close();}}//反序列化,还原成对象publicstaticObjectreadObject()throwsIOException{ObjectInputStream ois =null;InputStream is =null;try{
            is =newFileInputStream("D:/demo.txt");
            ois =newObjectInputStream(is);Object object = ois.readObject();return object;}catch(FileNotFoundException e){
            e.printStackTrace();}catch(IOException e){
            e.printStackTrace();}catch(ClassNotFoundException e){
            e.printStackTrace();}finally{
            is.close();
            ois.close();}returnnull;}}

Student

Studne类必须实现Serializable,Studnet才可以被序列化。Serializable一个空接口,可以将其视为可以序列化的标志。

packagecom.kc.system.io;importlombok.Data;importjava.io.Serializable;@DatapublicclassStudentimplementsSerializable{privateString name;privateint age;privateString address;privateString school;}

对Studnet序列化和反序列化

packagecom.kc.system.io;importjava.io.IOException;publicclassSerializeUtilDemo{publicstaticvoidmain(String[] args)throwsIOException{Student s =newStudent();
        s.setName("叶秋涵");
        s.setAge(18);
        s.setAddress("北海");
        s.setSchool("哔哩哔哩");SerializeUtil.saveObject(s);System.out.println("序列化完成了");System.out.println("-----");Student student =(Student)SerializeUtil.readObject();System.out.println(student);}}

Student序列化结果

在这里插入图片描述

Studnent反序列化结果

在这里插入图片描述

向Student中添加weight字段

packagecom.kc.system.io;importlombok.Data;importjava.io.Serializable;@DatapublicclassStudentimplementsSerializable{privateString name;privateint age;privateString address;privateString school;privatedouble weight;}

再次反序化

packagecom.kc.system.io;importjava.io.IOException;publicclassSerializeUtilDemo{publicstaticvoidmain(String[] args)throwsIOException{Student student =(Student)SerializeUtil.readObject();System.out.println(student);}}

控制台异常

java.io.InvalidClassException:com.kc.system.io.Student; local class incompatible: stream classdesc serialVersionUID =-2853823296530063815, local class serialVersionUID =6312346039733332667//流中的ID与本地的类中ID不一致

解决异常

向类中添加serialVersionUID

privatestaticfinallong serialVersionUID =-4985775903060349049L;

再次序列化覆盖上一个版本的对象数据,然后再反序列化

示例代码

packagecom.kc.system.io;importjava.io.IOException;publicclassSerializeUtilDemo{publicstaticvoidmain(String[] args)throwsIOException{Student s =newStudent();
        s.setName("叶秋涵");
        s.setAge(18);
        s.setAddress("北海");
        s.setSchool("哔哩哔哩");SerializeUtil.saveObject(s);System.out.println("序列化完成了");System.out.println("-----");Student student =(Student)SerializeUtil.readObject();System.out.println(student);}}//运行结果//序列化完成了//-----//Student(name=叶秋涵, age=18, address=北海, school=哔哩哔哩, weight=0.0)

再向Studnet中添加一个gender字段,在执行上述的代码就不会出异常了

在这里插入图片描述

properties

Properties是一个存储键值对数据的文件对象,该文件后缀为.properties。
构造器说明void load(Reader reader)从输入字符流读取属性列表(键和元素对)void store(Writer writer, String comments)将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流void load(InputStream inStream)从输入字节流读取属性列表(键和元素对)void store(OutputStream out, String comments)将此属性列表(键和元素对)写入此 Properties表中,以适合于使用 load(InputStream)方法的格式写入输出字节流public Object setProperty(String key, String value)保存键值对public String getProperty(String key)使用此属性列表中指定的键搜索属性值 (get)public Set stringPropertyNames()所有键的名称的集合 (keySet())
首先创建一个user.properties,再向user.properties文件中添加是数据

packagecom.kc.system.io;importjava.io.FileWriter;importjava.io.IOException;importjava.util.Properties;publicclassPropertiesDemo1{publicstaticvoidmain(String[] args)throwsIOException{Properties properties =newProperties();
        properties.setProperty("admin","123456");
        properties.setProperty("name","叶秋涵");
        properties.setProperty("pwassword","123456");System.out.println(properties);
        properties.store(newFileWriter("./user.properties"),"用户信息");//该文件必须是存在的}}

从user.properties获取数据

packagecom.kc.system.io;importjava.io.FileNotFoundException;importjava.io.FileReader;importjava.io.IOException;importjava.util.Properties;importjava.util.Set;publicclassPropertiesDemo2{publicstaticvoidmain(String[] args)throwsIOException{//读取properties文件中的键值对信息Properties properties =newProperties();System.out.println(properties);//加载属性文件中的键值对数据到属性对象properties中去
        properties.load(newFileReader("./user.properties"));System.out.println(properties);String name = properties.getProperty("name");System.out.println(name);String admin = properties.getProperty("admin");System.out.println(admin);String pwassword = properties.getProperty("pwassword");System.out.println(pwassword);//获取配置文件中所有的键Set<String> str = properties.stringPropertyNames();for(String s : str){System.out.print(s+" ");}}}

commons-io

commons-io是apache开源基金组织提供的一组有关IO操作的类库,就是对常见文件操作的封装,如文件的复制,删除,移动等。可以大的的提高效率。commons-io工具包提供了很多有关io操作的类。有两个主要的类FileUtils, IOUtils。

方法
方法说明String readFileToString(File file, String encoding)读取文件中的数据, 返回字符串void copyFile(File srcFile, File destFile)复制文件void copyDirectoryToDirectory(File srcDir, File destDir)复制文件夹
maven依赖

commons-io commons-io 2.6

代码示例

packagecom.kc.system.io;importorg.apache.commons.io.FileUtils;importorg.apache.commons.io.IOUtils;importjava.io.File;importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.IOException;publicclassFileUtilsDemo{publicstaticvoidmain(String[] args)throwsIOException{//完成文件的复制IOUtils.copy(newFileInputStream("./bbb.txt"),newFileOutputStream("./bbb2.txt"));//完成文件复制到某个文件夹下FileUtils.copyFileToDirectory(newFile("D:/picture/1.jpg"),newFile("D:/tools"));//完成文件夹复制到某个文件夹下FileUtils.copyDirectoryToDirectory(newFile("D:/picture"),newFile("D:/tools"));//读取文件中的数据String str =FileUtils.readFileToString(newFile("./bbb.txt"),"UTF-8");System.out.println(str);//复制文件FileUtils.copyFile(newFile("./bbb.txt"),newFile("./bbb3.txt"));//删除文件夹FileUtils.deleteDirectory(newFile("D:/demo"));}}

最后的话

各位看官如果觉得文章写得不错,点赞评论关注走一波!谢谢啦!

在这里插入图片描述

标签: java jvm linux

本文转载自: https://blog.csdn.net/qq_60308100/article/details/127530442
版权归原作者 KC老衲爱尼姑 所有, 如有侵权,请联系我们删除。

“《JavaSE-第十五章》之文件(二)”的评论:

还没有评论