java---文件操作
  P32LocODgHJ4 2023年11月02日 44 0

16.1 File

File文件类提供对文件操作的一系列的方法

构造方法

说明

File(String pathname)

给定一个文件路径(包括文件名),通过路径创建File对象

File(String parent, String child)

给定一个parent文件夹路径,给一个child文件名 创建File对象

File(File parent, String child)

给定一个File对象这个对象一定是一个文件夹,child文件名 创建File对象

File(URI uri)

URI是Java的中路径对象

API

方法名

说明

exists()

判断当前路径下的文件或文件夹是否存在,存在返回true

isDirectory()

判断当前的路径是不是一个文件夹

isFile()

判断当前的路径是不是一个文件

isHidden()

判断当前的路径是不是一个隐藏文件

lastModified()

返回文件上一次修改的时间

length()

返回文件的长度,返回文件的容量大小以字节为单位,返回的是一个long数据

list()

返回文件夹下的所有文件名和目录名

listFiles()

返回当前目录下所有的file对象包含文件和目录

mkdir()

创建指定路径的目录 如果指定的路径是一个目录且不存在的时候可以通过mkdir()创建,注意这个不存在的路径只有一层不存在,只能创建单层目录

mkdirs()

创建指定路径的目录,创建多层目录

delete()

删除文件或目录

getName()

返回当前文件或目录的名称

getParent()

返回上级目录的绝对路径

getPath()

返回当前文件和文件夹的绝对路径

案例一:

import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

public class Demo1 {
    public static void main(String[] args) {
        File file=new File("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.class");
        System.out.println("文件是否存在:"+file.exists());
        System.out.println("是否是文件夹:"+file.isDirectory());
        System.out.println("是否是文件:"+file.isFile());
        System.out.println("是否隐藏:"+file.isHidden());
        Date date=new Date(file.lastModified());
        DateFormat format=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        System.out.println("上一次修改的时间:"+format.format(date));
        System.out.println("文件的长度:"+file.length()+"B");

        System.out.println("========================================================================");

        File directory=new File("C:\\User\\Administrator\\Desktop\\新建文件夹");
        String[] list = directory.list();
        Arrays.stream(list).forEach(System.out::println);

    }
}

案例二:搜索指定目录下所有的文件

package com.qf.filedemo;

import java.io.File;

public class Demo2 {
    public static void main(String[] args) {
        File dir=new  File("D:\\javaProject\\ThreadDemoProject\\src\\main\\java");
        //请将该目录中所有的文件显示出来
        if(dir.exists()){
            queryFile(dir);
        }
    }
    //这个方法进行调用(递归)只能是目录对象进行递归
    private static void queryFile(File dir){
        String[] list = dir.list(); //获取当前目录下的文件名
        for(String f : list){
            //根据拿到的文件名创建当前目录下这个文件对应的file对象
            File childFile=new File(dir,f);
            if(childFile.isDirectory()){
                queryFile(childFile);
            }else{
                System.out.println(childFile.getParent()+"\\"+f);
            }
        }
    }
}

案例三:搜索文件

package com.qf.filedemo;

import java.io.File;

public class Demo3 {
    public static void main(String[] args) {
        File dir=new  File("D:\\javaProject\\ThreadDemoProject\\src\\main\\java");
        //请将该目录中所有的文件显示出来
        if(dir.exists()){
            queryFile(dir);
        }
    }
    //这个方法进行调用(递归)只能是目录对象进行递归
    private static void queryFile(File dir){
        //直接获取这个目录下所有的file对象 包含文件和目录
        File[] files = dir.listFiles();
        for(File f : files){

            if(f.isDirectory()){
                queryFile(f);
            }else{
                System.out.println(f);
            }
        }
    }
}

案例四:

public class Demo4 {
    public static void main(String[] args) {

        File file=new File("C:\\User\\Administrator\\Desktop\\新建文件夹\\abc");
        if(!file.exists()){
            //file.mkdir();//只能创建单层文件夹
            file.mkdirs();//可以创建多层文件夹
        }
    }
}

案例五:

public class Demo4 {
    public static void main(String[] args) {

        File file=new File("C:\\User\\Administrator\\Desktop\\新建文件夹\\abc");
        if(!file.exists()){
            //file.mkdir();//只能创建单层文件夹
            file.mkdirs();//可以创建多层文件夹
        }
        file.delete();//delete只能删除空文件夹,如果文件夹中有内容删除失败,失败返回false
    }
}

案例六:如果想要达到删除文件夹一起将文件夹中的内容也删除的话,需要自己写逻辑实现

package com.qf.filedemo;

import java.io.File;

public class Demo4 {
    public static void main(String[] args) {

        File file=new File("C:\\User\\Administrator\\Desktop\\新建文件夹\\abc");
        if(!file.exists()){
            file.mkdirs();
        }
        del(file);

    }
    //递归删除
    public static void del(File dir){
        //获取当前目录下的所有file对象
        File[] files = dir.listFiles();
        for (File f: files) {
            //判断当的file对象是不是一个文件夹,如果不是直接删除文件,
            if(f.isDirectory()){
                //如果是文件夹的话,先判断当前文件夹中是否还有内容
                if(f.listFiles()!=null&&f.listFiles().length>0) {
                    //如果有内容就递归进去先删除里面的内容后
                    del(f);
                }
                //再删除当前文件夹
                f.delete();
            }else{
                f.delete();//直接删除文件
            }
        }
    }
}

16.2 字节流

java---文件操作_Java---文件操作

InputStream输入流 是从程序外部将文件内容读入到程序中 InputStream是一个抽象类。

子类FileInputStream,专门用于文件的读取

FileInputStream(File file) 根据指定的File对象来创建该 对象对应的文件的输入流

FileInputStream(String name) 根据指定的文件路径来创建一个文件输入流

在构造FileInputStream对象时如果文件找不到,会引发FileNotFoundException 异常

int

read() 从该输入流读取一个字节的数据。

int

read(byte[] b) 从该输入流读取最多 b.length个字节的数据为字节数组。

int

read(byte[] b, int off, int len) 从该输入流读取最多 len字节的数据为字节数组。

read()可能会引发IO异常 读写异常

a.txt文件中的内容是"千锋教育重庆JavaEE-2202期开班典礼"
public class Demo5 {
    public static void main(String[] args) throws FileNotFoundException { 
        InputStream inputStream=new FileInputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt");
        try {
            while (true) {
                int read = inputStream.read();
                if(read==-1){
                    break;
                }
                System.out.print((char)read);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        inputStream.close();//关流
    }
}
运行结果:
啕镕敕蕲镕底JavaEE-2202敕引畕啸礼
 为什么会出现这种结果,那是因为汉字占三个字节,英文状态的字母,符号,数字都只占一个字节,inputStream.read();这里的读取就是只读一个字节,所以将整数以ASCII在转换为字符的时候一个字节的字符转换成功,3个字节的汉字只有1/3转换成了乱码了。
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class Demo5 {
    public static void main(String[] args) throws IOException {

        byte[] data=new byte[10];
        InputStream inputStream=new FileInputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt");
        while (true){
            //返回值是读取有效字符的长度
            int i=inputStream.read(data);
            if(i==-1){//读到-1的时候就代表读到了文件未必
                break;
            }
            /*
            前面两次都是将数组读满new String(data,0,i)转换成字符串就是从0到10,最后一次的时候只读了5个字符,
            数组后五个元素是上一次余留下来的,read(byte[])返回的结果是读取的有效字符的个数,所以可以从0到有效字符数为止,这样防止
            结果溢出
             */
            // System.out.print(new String(data));
            System.out.print(new String(data,0,i));
        }
        inputStream.close();//关流
    }
}
运算结果:
//public class HelloWorld{}lloWo  
   public class HelloWorld{}
public class Demo5 {
    public static void main(String[] args) throws IOException {

        InputStream inputStream=new FileInputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt");
        //inputStream.available() 是流的长度,文件大小的容量,创建了一个与文件大小一样的数组
        byte[] data=new byte[inputStream.available()];
        //一口气将文件所有内容读到数组中
        inputStream.read(data);  //文件特别大的时候,会很卡
        inputStream.close();
        System.out.println(new String(data));

    }
}

OutputStream输出流 是程序把程序中的内容写入到外部的文件中

FileOutputStream(File file) 创建文件输出流以写入由指定的 File对象表示的文件。

FileOutputStream(File file, boolean append) 创建文件输出流以写入由指定的 File对象表示的文件。

FileOutputStream(String name) 创建文件输出流以指定的名称写入文件。

FileOutputStream(String name, boolean append) 创建文件输出流以指定的名称写入文件。

void

write(byte[] b)b.length个字节从指定的字节数组写入此文件输出流。

void

write(byte[] b, int off, int len)len字节从位于偏移量 off的指定字节数组写入此文件输出流。

void

write(int b) 将指定的字节写入此文件输出流。

void

close() 关闭流

void

flush () 刷新缓冲区

public class Demo7 {
    public static void main(String[] args) throws IOException {
        //写入并覆盖以前的内容
        OutputStream outputStream=new FileOutputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt");
        String info="我爱中国,中国爱我!!!我是中国人。不骗中国人!!!";
        //info.getBytes()  是将字符转换成一个byte类型的数组 , 这个数组中的内容就是这段字符串对应的byte类型数据
        outputStream.write(info.getBytes());
        outputStream.flush();
        outputStream.close();
    }
}

追加写入

public class Demo7 {
    public static void main(String[] args) throws IOException {
        //写稿并覆盖以前的内容
        OutputStream outputStream=new FileOutputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt",true);
        String info="我爱中国,中国爱我!!!我是中国人。不骗中国人!!!";
        outputStream.write(info.getBytes());
        outputStream.flush();//刷新缓冲区
        outputStream.close();
    }
}

outputStream.flush();为什么要刷新缓冲区。

文件以byte的形式写入到OutputStream,写完以有可能内容有一部分并没有真正的写进文件里,而是停留在缓冲区中,这时刷新缓冲区的目的是为了将缓冲区中的内容强制性弹出来,写入文件,所以在关闭流之前,一定要先刷新缓冲区域。

复制文件

糊涂工具包:https://www.hutool.cn/docs/#/extra/%E4%BA%8C%E7%BB%B4%E7%A0%81%E5%B7%A5%E5%85%B7-QrCodeUtil

public class Demo9 {
    public static void main(String[] args) throws IOException {
        String str="中国重庆江北国际机场";
        byte[] bytes = str.getBytes();
        //编码解码,在安全框架中使用比较多,在生成base64编码的图片时用得比较多
        //BASE64Encoder 编码类
        BASE64Encoder encoder=new BASE64Encoder();
        //encoder.encode(bytes); 对字符串进行编码
        String encode = encoder.encode(bytes);
        System.out.println(encode);

        //解码类
        BASE64Decoder decoder=new BASE64Decoder();
        //decoder.decodeBuffer(encode) 解码操作
        byte[] bytes1 = decoder.decodeBuffer(encode);
        System.out.println(new String(bytes1));
    }
}

16.3 字符流

Reader和Writer父类

字符输入流

InputStreamReader

public class Demo10 {
    public static void main(String[] args) {
        try {
            InputStream inputStream=new FileInputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt");
            Reader reader=new InputStreamReader(inputStream);
            while (true) {
               int i= reader.read();
               if(i==-1){
                   break;
               }
                System.out.print((char)i);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Reader reader=new InputStreamReader(inputStream);Reader的创建需要一个InputStream作为构造的参数传入

InputStream是一个抽象,现在能创建他的方案只有使用FileInputStream来操作

InputStream inputStream=new FileInputStream("C:\User\Administrator\Desktop\新建文件夹\a.txt");

read()方法读不到数据返回-1 读到数据读的是一个字符的所有byte内容,所以直接使用强转的方式就能将内容打印出来

public class Demo10 {
    public static void main(String[] args) {
        try {
            InputStream inputStream=new FileInputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt");
            Reader reader=new InputStreamReader(inputStream);
            while (true) {
               int i= reader.read();
               if(i==-1){
                   break;
               }
                System.out.print((char)i);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

int len= reader.read(ch); 这时read参数有一个char数组后,返回值是读到的有效字符的个数,不再是具体的数据了,读不到的时候还是返回-1,用数组接收读取的数据时要注意,在读取的过程中最后一次的时候有可能要余留上一次读取的数据,在这一次又将数组读不满时,就会出现结果溢出,解决方案还是使用String的构造来限制生成的字符串个数,new String(ch,0,len);

public class Demo10 {
    public static void main(String[] args) {
        try {
            char[] ch=new char[10];
            InputStream inputStream=new FileInputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt");
            Reader reader=new InputStreamReader(inputStream);
            while (true) {
               int len= reader.read(ch);
               if(len==-1){
                   break;
               }
                System.out.print(new String(ch,0,len));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

字符输出流

OutputStreamWriter

OutputStreamWriter 创建 与InputStreamReader一样(转换流)

老是忘记关流,如果使用常规的try...catch层次套用太烦,所以使用try....Rescoure 的形式来进行流的自动关闭,能够进行自动关闭的类是必须要实现Closeable接口的。

try(创建流对象){

}catch(异常 e){

}

public class Demo11 {
    public static void main(String[] args) {

        try(Writer writer=new OutputStreamWriter(new FileOutputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt",true))){
            writer.write("重庆千锋教育");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

16.4 缓冲流

BufferedInputStream,BufferedOutputStream --> 字节缓冲流

BufferedInputStream:

public class BufferedDemo {
    public static void main(String[] args) {
       try( InputStream inputStream=new FileInputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt");BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream)){
           byte []data=new byte[10];
           while (true) {
               int i=bufferedInputStream.read(data);
               if (i==-1){
                   break;
               }
               System.out.print(new String(data,0,i));
           }
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }

    }
}
因为是字节流,结果和之前的一样
public class BufferedDemo {
    public static void main(String[] args) {
       try( InputStream inputStream=new FileInputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt");BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream)){
          byte[] data=new byte[inputStream.available()];
          bufferedInputStream.read(data);
           System.out.println(new String(data));
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }

    }
}

BufferedOutputStream :

public class BufferedDemo {
    public static void main(String[] args) {
       try(OutputStream outputStream=new FileOutputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt",true);BufferedOutputStream bufferedOutputStream=new Buffe redOutputStream(outputStream)){
            bufferedOutputStream.write("\r\n你好张鹏,你好谢兴灵".getBytes());
           //这里可以不用写刷新方法,因为try...Resource是自动关闭流,在关闭的时候会自去调用一次flush()方法 
           bufferedOutputStream.flush();
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }

    }
}

缓冲流:在其内部有一个缓冲区域,InputStream和OutputStream直接操作的文件没有中间缓冲地带,BufferedOutputStream拥有中间缓存地带

BufferedReader,BufferedWriter-->字符缓冲流

BufferedReader: 带有缓冲区域的增强型字符流

public class BufferedReaderAndWriter {
    public static void main(String[] args) throws IOException {
        //inputStream的创建需要使用FileInputStream
        InputStream inputStream=new FileInputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt");
        //Reader创建需要一个InputStream
        Reader reader=new InputStreamReader(inputStream);
        // BufferedReader的创建需要一个Reader  缓冲区
        BufferedReader bufferedReader=new BufferedReader(reader);
        while (true) {
            //一次读一行,\r\n行结束标志,如果读到文件末尾是得到一个null
            String data = bufferedReader.readLine();
            if(data==null){
                break;
            }

            System.out.println(data);

        }
        //会自动向上关闭,会自动去关闭reader inputStream
        bufferedReader.close();
    }
}

BufferedWriter: 带有缓冲区域的增强型字符流

try(OutputStream outputStream=new FileOutputStream("C:\\\\User\\\\Administrator\\\\Desktop\\\\新建文件夹\\\\a.txt",true);
            Writer writer=new OutputStreamWriter(outputStream);
            BufferedWriter bufferedWriter=new BufferedWriter(writer)){
            bufferedWriter.write("\r\n这是使用的缓冲字符流BufferedWriter在进行写操作");

       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }

16.5 文件字符流

FileReader:

public class FileReaderAndWriter {
    public static void main(String[] args) {
        try(Reader reader=new FileReader("C:\\\\User\\\\Administrator\\\\Desktop\\\\新建文件夹\\\\a.txt")){

            while (true) {
                int read = reader.read();
                if(read==-1){
                    break;
                }
                System.out.print((char)read);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class FileReaderAndWriter {
    public static void main(String[] args) {
        try(Reader reader=new FileReader("C:\\\\User\\\\Administrator\\\\Desktop\\\\新建文件夹\\\\a.txt")){
            char[] ch=new char[10];
            while (true) {
                int read = reader.read(ch);
                if(read==-1){
                    break;
                }
                System.out.print(new String(ch,0,read));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

FileWriter:

public class FileReaderAndWriter {
    public static void main(String[] args) {
        try(Writer writer=new FileWriter("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt")){
            writer.write("你好世界");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

16.6 打印流

字节打印流

PrintStream

public class PrintDemo {
    public static void main(String[] args) throws FileNotFoundException {
        //打印流  打印目的地是一个指定的文件
        OutputStream outputStream=new FileOutputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt");
        //打印流的创建需要一个FileOutputStream对象
        PrintStream printStream=new PrintStream(outputStream);
        printStream.println("hello world");
        printStream.flush();
        printStream.close();

        //创建一个打印流完成向控制台打印信息FileDescriptor.out打印目的地是控制台
        PrintStream out=new PrintStream(new FileOutputStream(FileDescriptor.out));
        out.println("hello world");
    }
}

字符打印流

PrintWriter

public class PrintDemo {
    public static void main(String[] args) throws FileNotFoundException {
        OutputStream outputStream=new FileOutputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\a.txt");
        Writer writer=new OutputStreamWriter(outputStream);
        PrintWriter printWriter=new PrintWriter(writer);
        printWriter.println("你好世界,直接很好");
        printWriter.flush();
        printWriter.close();
    }
}

16.7 数据流

主要是对常用的基本数据类型的数据进行文件的写入读取,使用DataInputStream进行写入的数据不是为了给别人看,而是为了程序的存储和读取,使用数据存储的文件类型一般.bat二进制形式的文件

DataInputStream 数据输入流

DataOutputStream 数据输出流

public class DataStreamDemo {
    public static void main(String[] args) {
        //out();
        read();
    }
    //读
    public static void read(){

       try( InputStream inputStream=new FileInputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\data.bat");
        DataInputStream dataInputStream=new DataInputStream(inputStream)){

        //读取的顺序个数,类型一定要与写入的时候一致,不然不是报错就是结果对不上
           System.out.println(dataInputStream.readInt());
           System.out.println(dataInputStream.readInt());
           System.out.println(dataInputStream.readByte());
           System.out.println(dataInputStream.readDouble());
           System.out.println(dataInputStream.readUTF());

       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }
    }
    //写
    public static void out(){
        try(OutputStream outputStream=new FileOutputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\data.bat");
        DataOutputStream dataOutputStream=new DataOutputStream(outputStream)){
        //dataOutputStream在写入数据的时候是根据选择的类型来确定存储的空间大小
        dataOutputStream.writeInt(10);
        dataOutputStream.writeInt(30);
        dataOutputStream.writeByte(9); //1
        dataOutputStream.writeDouble(3.14); //8
        dataOutputStream.writeUTF("你好世界"); //12   25
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

DataInputStream :

读取数据的API:

read数据类型();

readInt();

readDouble();

读取字符串

readUTF(); UTF--utf-8 以这种编码方式对数据进行读取

DataOutputStream 数据输出流

write数据类型

writeInt();

writeDouble();

writeChar().....

字符串

writeUTF(字符串)

注意的是:

1、一下情况下DataInputStream和DataOutputStream要一起配合使用。

2、存入的顺序,个数,类型在读取的时候要一致。

16.8 字节数组流

ByteArrayInputStream

ByteArrayOutputStream

字节数组流是在内存中直接开辟一块缓冲区域用于存放数据,与文件无关,用完就丢掉。

public class ByteArrayDemo {

    public static void main(String[] args) {
        //不产生文件,在内存中划一块缓冲区进行数据的写入和读取
        try {
            //数据在网络中进行传输只能是流  消息中间件的时候会这样去写  RabbitMQ
            ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
            outputStream.write("你好世界".getBytes());
            byte[] bytes = outputStream.toByteArray();


            //A端使用流发送的数据B端必然会使用一个流来进行接收
            ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(bytes);
            byte [] data=new byte[byteArrayInputStream.available()];
            byteArrayInputStream.read(data);
            System.out.println(new String(data));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}
package com.qf.filedemo;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class ByteArrayDemo {

    public static void main(String[] args) {
        ByteArrayOutputStream write = write();
        read(write.toByteArray());
    }
    //读数据
    public static void read(byte[] bytes){

        try {
            ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(bytes);
            byte [] data=new byte[byteArrayInputStream.available()];
            byteArrayInputStream.read(data);
            System.out.println(new String(data));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //写数据
    public static ByteArrayOutputStream write(){

        try {
            ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
            outputStream.write("你好世界".getBytes());
            return outputStream;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


}

16.9 序列化

序列化与反序列化。

序列化:是将程序中的数据,基本数据类型,引用数据类型(对象,集合,数组等等)将这些数据以Java格式存入到文件中。

反序列化:就是将文件中的数据,读取出来封装为Java中的对象,集合,数组等等。

这里的知识点会伴随我们一生。不单单只是将数据存入文件这么简单,MQ(消息中间件),Redis缓存,数据库....存一个对象都需要进行序列化。

序列化的文件是一个二进制文件,是存放数据的,不是给别人看的,bat,bin类型

//要进行序列化的数据类
package com.qf.filedemo.entitys;

public class Student {

    private int stuId;
    private String stuName;
    private int stuAge;
    private String phone;

    public Student() {
    }

    public Student(int stuId, String stuName, int stuAge, String phone) {
        this.stuId = stuId;
        this.stuName = stuName;
        this.stuAge = stuAge;
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "Student{" +
                "stuId=" + stuId +
                ", stuName='" + stuName + '\'' +
                ", stuAge=" + stuAge +
                ", phone='" + phone + '\'' +
                '}';
    }

    public int getStuId() {
        return stuId;
    }

    public void setStuId(int stuId) {
        this.stuId = stuId;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public int getStuAge() {
        return stuAge;
    }

    public void setStuAge(int stuAge) {
        this.stuAge = stuAge;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}
public static void write(){
        Student student=new Student(1,"张鹏",20,"13312345678");
        try(OutputStream outputStream=new FileOutputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\seri.bat");
            ObjectOutputStream objectOutputStream=new ObjectOutputStream(outputStream)){
            objectOutputStream.writeObject(student);
            objectOutputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
运行报错:
java.io.NotSerializableException: com.qf.filedemo.entitys.Student
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at com.qf.filedemo.ObjectStreamDemo.write(ObjectStreamDemo.java:20)
    at com.qf.filedemo.ObjectStreamDemo.main(ObjectStreamDemo.java:9)

Serializable : 接口标记形接口,用此接口描述的类才允许被序列化。Cloneable(以前讲的这个接口,允许被克隆),报错的原因是被序列化的类没有实现Serizlizable接口

public class Student implements Serializable {
    
}
添加上这个接口以后,就不报错了

案例:

public class ObjectStreamDemo {
    public static void main(String[] args) {
        //write();
        read();
    }

    public static void read(){
       try(InputStream inputStream=new FileInputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\seri.bat");
            ObjectInputStream objectInputStream=new ObjectInputStream(inputStream)){
            
            Student student= (Student) objectInputStream.readObject();

            System.out.println(student);
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       }
    }

    public static void write(){
        Student student=new Student(1,"张鹏",20,"13312345678");
        try(OutputStream outputStream=new FileOutputStream("C:\\User\\Administrator\\Desktop\\新建文件夹\\seri.bat");
            ObjectOutputStream objectOutputStream=new ObjectOutputStream(outputStream)){
            objectOutputStream.writeObject(student);
            objectOutputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ObjectInputStream objectInputStream=new ObjectInputStream(inputStream)

ObjectOutputStream objectOutputStream=new ObjectOutputStream(outputStream)创建这两个对象的时候需要InputStream和OutputStream的对象。

writeObject()序列化一个对象存储到文件中

readObject()将文件中的数据反序列为程序中的对象

一个文件最好,只存放一个对象

在不同的项目中去反序列化文件的时候需要注意一些问题:

1、类的内容必须一致

2、类的包结构必须一致

如果不一致java会认为这是两个不一样的类

java---文件操作_流_02

在序列化类的内部有一个UID标识,用于标记当前这个类的版本,反序列化的时候会对这个版本号进行判断,如果接收的对象的类中的版本号与文件中写入的对象的版本不一致时,会认为是两个不一样的类。如果标识没有写,系统会根据包,类名来默认生成一个。也可以显示的生成出来

1、对工具进行设置,打开UID的勾选。

java---文件操作_Java---文件操作_03

2、光标移动到序列化的类名上alt+回车:

java---文件操作_流_04

public class Student implements Serializable {

    private static final long serialVersionUID = 5260439563197151034L;
    private int stuId;
    private String stuName;
    private int stuAge;
    private String phone;
}
现在在类中显示的出现了serialVersionUID标记,它的作用是用于标记两边项目中的这个类是同一个,如果这个标记不一样时反序列将会失败。

java---文件操作_缓冲流_05

包结构不一样时反序列化不成功

标记不一样时反序列化也不成功,标记在以后的项目中,可能会有很多的项目配合执行,当一边对类进行修改以后,另一边不知道人家进行了修改,这时候就会造成一定数据的丢失,这样通过修改标记的版本号来让另一边反序列化不成功。

谢谢观看...请不要白嫖呀~~小龙我啊都没钱吃饭啦~~求求各位大佬点点赞吧!!!(跪谢!)

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  2Vtxr3XfwhHq   2024年05月17日   53   0   0 Java
  Tnh5bgG19sRf   2024年05月20日   108   0   0 Java
  8s1LUHPryisj   2024年05月17日   46   0   0 Java
  aRSRdgycpgWt   2024年05月17日   47   0   0 Java
P32LocODgHJ4