参考

位、字节、字符

字节(Byte)是计量单位,表示数据量多少,是计算机信息技术用于计量存储容量的一种计量单位,通常情况下一字节等于八位。
字符(Character)计算机中使用的字母、数字、字和符号,比如’A’、‘B’、’$’、’&’等。
一般在英文状态下一个字母或字符占用一个字节,一个汉字用两个字节表示。
字节与字符:
ASCII 码中,一个英文字母(不分大小写)为一个字节,一个中文汉字为两个字节。
UTF-8 编码中,一个英文字为一个字节,一个中文为三个字节。
Unicode 编码中,一个英文为一个字节,一个中文为两个字节。
符号:英文标点为一个字节,中文标点为两个字节。例如:英文句号 . 占1个字节的大小,中文句号 。占2个字节的大小。
UTF-16 编码中,一个英文字母字符或一个汉字字符存储都需要 2 个字节(Unicode 扩展区的一些汉字存储需要 4 个字节)。
UTF-32 编码中,世界上任何字符的存储都需要 4 个字节。 

File

File:它是文件和目录路径名的抽象表示文件和目录是可以通过File封装成对象的
对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。它可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容转换为具体存在的

File对象

构造方法

pathname可以使用相对路径 , 相对于当前项目的路径
方法名 说明
File(File parent, String child) 根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
File(String pathname) 通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
File(String parent, String child) 根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
File(URI uri) 通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例

常用方法

方法名

说明

public boolean createNewFile()

当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件

public boolean mkdir()

创建由此抽象路径名命名的目录

public boolean mkdirs()

创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录

public boolean delete()

删除由此抽象路径名表示的文件或目录

public boolean isDirectory()

测试此抽象路径名表示的File是否为目录

public boolean isFile()

测试此抽象路径名表示的File是否为文件

public boolean exists()

测试此抽象路径名表示的File是否存在

public String getAbsolutePath()

返回此抽象路径名的绝对路径名字符串

public String getPath()

将此抽象路径名转换为路径名字符串

public String getName()

返回由此抽象路径名表示的文件或目录的名称

public String[] list()

返回此抽象路径名表示的目录中的文件和目录的名称字符串数组

public File[] listFiles()

返回此抽象路径名表示的目录中的文件和目录的File对象数组

 

创建文件

 //在路径下创建test.txt
//构造函数一
//File file = new File("G:\\test.txt");
//构造函数二
//File file = new File("G:\\","test.txt");
//构造函数三
File file0 = new File("G:\\");
File file = new File(file0,"test.txt");
try {
    boolean success = file.createNewFile();
} catch (IOException e) {
    e.printStackTrace();
}

创建目录

如果目录存在则不会创建
//在路径下创建java目录
File file = new File("G:\\java");
boolean success = file.mkdir();
//创建多级目录
//File file = new File("G:\\java\\javaweb\\web");
//file.mkdirs();

检查目录或文件是否存在

public boolean isDirectory() 测试此抽象路径名表示的File是否为目录
public boolean isFile() 测试此抽象路径名表示的File是否为文件
public boolean exists() 测试此抽象路径名表示的File是否存在

获取目录下全部文件路径

public static void main(String[] args) {
        File file = new File("G:\\java");
        getAllFilePath(file);
    }

    public static void getAllFilePath(File srcFile){
        File[] fileArray = srcFile.listFiles();
        if(fileArray !=null){
            for(File file : fileArray){
                if(file.isDirectory()){
                    getAllFilePath(file);
                }else{
                    System.out.println(file.getAbsoluteFile());
                }
            }
        }
    }

Stream

总结

InputStream与OutputStream是两个抽象类,是字节流的基类,所有具体的字节流实现类都是分别继承了这两个类。

字节流
	FileInputStream和FileOutputStream将文件转输入流和输出流
	为了提高效率,BufferedInputStream和BufferedOutputStream对此两个对象进行包装进行缓冲处理

	// 字节输出流
	FileOutputStream out = new FileOutputStream("filename/file", true);
	//字节缓冲输出流
	BufferedOutputStream bos = new BufferedOutputStream(out);

	//字节输入流
	FileInputStream fi = new FileInputStream("filename/file");
	//字节缓冲输入流
	BufferedInputStream in = new BufferedInputStream(fi);
	

字符流
	
	//字符输出流OutputStreamWriter借助字节输出流FileOutputStream实现
	FileOutputStream os = new FileOutputStream("filename/file", true);
	OutputStreamWriter writer = new OutputStreamWriter(os,"UTF-8");
	
	//字符输入流
	FileInputStream fi = new FileInputStream("filename/file");
	InputStreamReader in = new InputStreamReader(fi, "UTF-8");
	
字符流便捷类
	FileWriter和FileReader简化字符流的读写
	new FileWriter("filename/file",true)等同于new OutputStreamWriter(new FileOutputStream("filename/file", true))
	new FileWriter("filename/file")等同于new InputStreamReader(new FileInputStream("filename/file"))
	
转换流
	InputStreamReader和OutputStreamWriter  对字节流进行字符流转换,两个对象的构造函数需要借助
	FileInputStream和FileOutputStream
	
字符缓冲流
	//BufferedReader对InputStreamReader进行包装缓冲,BufferedWriter对OutputStreamReader进行包装缓冲
	InputStream is =new FileInputStream("filename/file");
	BufferedReader in  = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
	
	//http请求处理响应的一个例子
	URL realUrl = new URL(url);
	URLConnection conn = realUrl.openConnection();
	BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
	
	InputStream用InputStreamReader读取转换为字符,BufferedReader包装缓冲字符

流分类

字节流和字符流区别

字节流一般用来处理图像、视频、音频、PPT、Word 等类型的文件。字符流一般用于处理纯文本类型的文件,如TXT文件等,但不能处理图像视频等非文本文件。用一句话说就是:字节流可以处理一切文件,而字符流只能处理纯文本文件。
字节流本身没有缓冲区,缓冲字节流相对于字节流,效率提升非常高。而字符流本身就带有缓冲区,缓冲字符流相对于字符流效率提升就不是那么大了

IO流导图

「节点流」:直接操作数据读写的流类,比如FileInputStream

「处理流」:对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能,例如BufferedInputStream(缓冲字节流)

处理流和节点流应用了Java的装饰者设计模式。

下图就很形象地描绘了节点流和处理流,处理流是对节点流的封装,最终的数据处理还是由节点流完成的。

图片

释放资源

字节流

 流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输
IO流就是用来处理设备间数据传输问题的,常见的应用:文件复制;文件上传;文件下载
输入流是将文件或其它输入设备的数据加载到内存的过程; 输出流恰恰相反,是将内存中的数据保存到文件或其他输出设备
使用场景
如果操作的是纯文本文件,优先使用字符流
如果操作的是图片、视频、音频等二进制文件。优先使用字节流
如果不确定文件类型,优先使用字节流。字节流是万能的流

InputStream

这个抽象类是字节输入流,表示输入字节流的所有类的超类。
public abstract class InputStream
extends Object
implements Closeable 

FileInputStream

构造函数
FileInputStream(File file)
通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的 File对象 file命名。
FileInputStream(String name)
通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的路径名 name命名。
测试
一次读取一个字节,read读取最后是-1
 try (FileInputStream fi = new FileInputStream(new File("test.txt"))) {
     int by;
     while ((by = fi.read()) != -1) {
         char c = (char) by;
         System.out.print(c);
     }
 } catch (Exception e) {
 }

FileInputStream fi = new FileInputStream("G:\\java\\javase\\se1.txt");
int by;
while ((by = fi.read()) != -1) {
    System.out.println((char)by);
}
一次读一个字节数组数据
public static void read() throws IOException {
     File file = new File("D:\\io.txt");
     InputStream in = new FileInputStream(file);
     // 一次性取多少个字节
     byte[] bytes = new byte[1024];
     // 用来接收读取的字节数组
     StringBuilder sb = new StringBuilder();
     // 读取到的字节数组长度,为-1时表示没有数据
     int length = 0;
     // 循环取数据
     while ((length = in.read(bytes)) != -1) {
         // 将读取的内容转换成字符串
         sb.append(new String(bytes, 0, length));
     }
     // 关闭流
     in.close();
     System.out.println(sb.toString());
 }
字节流复制文件
FileInputStream fi = new FileInputStream("G:\\java\\javase\\1234.png");
FileOutputStream fo = new FileOutputStream("G:\\java\\javaweb\\456.png");
byte[] bytes = new byte[1024];//1024及其整数倍
int len;
while ((len = fi.read(bytes)) != -1) {
    fo.write(bytes, 0, len);
}
fi.close();
fo.close();

//文件复制
private static void copyFile(File srcfile, File destFile) {
    try(
        FileInputStream fis = new FileInputStream(srcfile);
        FileOutputStream fos = new FileOutputStream(destFile);
    ) {
        byte [] bytes = new byte[1024];
        int len = fis.read(bytes);
        while ( (len = fis.read(bytes)) != -1){
            fos.write(bytes, 0, len);
        }
    } catch (Exception e) {
        // TODO: handle exception
    }
}

//文件复制
private static void copyFile(String srcFileName, String destFileName) {
    try{
        BufferedInputStream fis = new BufferedInputStream(new FileInputStream(srcFileName));
        FileOutputStream fos = new FileOutputStream(destFileName);
        byte [] bytes = new byte[1024];
        int len = 0;
        while ( (len = fis.read(bytes)) != -1){
            fos.write(bytes, 0, len);
        }
        fis.close();
        fos.close();
    } catch (Exception e) {
        // TODO: handle exception
    }
}

OutputStream

这个抽象类是字节输出流,表示字节输出流的所有类的超类。 输出流接收输出字节并将其发送到某个接收器。 
public abstract class OutputStream
extends Object
implements Closeable, Flushable

FileOutputStream

将字节写入文件中
注意:boolean append
创建文件输出流以指定的名称写入文件。如果第二个参数为true ,则字节将写入文件的末尾而不是开头
write(int b)
将字节写进去文件,文件会写入a且覆盖原来的内容。如果不覆盖需要修改构造方法
 // 相对路径
try (FileOutputStream fo = new FileOutputStream("test.txt", true)) {
    // FileOutputStream fo = new FileOutputStream("test.txt") 覆盖此文件
    // 追加文本
    fo.write(97);
    fo.close();
} catch (Exception e) {
    e.printStackTrace();
}
write(byte[] b)
/**
 * 字节流写入
 */
public static void bytewrite() throws IOException {
    FileOutputStream os = new FileOutputStream("D:\\io.txt",true);
    // 要写入的字符串
    String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
    // 写入文件
    os.write(string.getBytes());
    // 关闭流
    os.close();
}

//下载文件的一个例子
 //输出到文件
File file = new File("文件名称");
FileOutputStream fos = new FileOutputStream(file);
InputStream is = conn.getInputStream();//http中获取流
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
    fos.write(buffer, 0, len);
}
fos.close();
bis.close();
is.close();
write(byte[] b, int off, int len)
设置偏移量,len需要减去off的值
try {
    FileOutputStream fo = new FileOutputStream("G:\\java\\javase\\se1.txt");
    try {
        byte[] bytes =  {97,98,99,100};
        //输出bcd
        fo.write(bytes,1,bytes.length-1);
        fo.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
}

字节流换行

windows:\r\n
linux:\n
mac:\r
String name = "ABCD\r\nEFG";
//输出bcd
fo.write(name.getBytes());

字符流

字符流只能复制文本数据,有5种方式,一般采用字符缓冲流的特有功能  「字符流适用于文本文件的读写」,OutputStreamWriter类其实也是借助FileOutputStream类实现的,故其构造方法是FileOutputStream的对象

Writer字符输出流

OutputStreamWriter

「字符流适用于文本文件的读写」,OutputStreamWriter类其实也是借助FileOutputStream类实现的,故其构造方法是FileOutputStream的对象
OutputStreamWriter(OutputStream out)
创建使用默认字符编码的OutputStreamWriter。
OutputStreamWriter(OutputStream out, String charsetName)
创建使用指定charset的OutputStreamWriter。

FileOutputStream fo = new FileOutputStream("文件名称");
OutputStreamWriter os = new OutputStreamWriter(fo,"UTF-8");

字符流写数据的方法

void write(int c)

写一个字符

void write(char[] cbuf)

写入一个字符数组

void write(char[] cbuf, int off, int len)

写入字符数组的一部分

void write(String str)

写一个字符串

void write(String str, int off, int len)

写一个字符串的一部分

flush()

刷新流,还可以继续写数据

close()

关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据

写文件

public static void write() throws IOException {
    File file = new File("D:\\io.txt");
    if(!file.exists()) {
        file.createNewFile();
    }
    OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8");
    // 要写入的字符串
    String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
    // 写入文件
    os.write(string);
    // 关闭流
    os.close();
}

Reader字符输入流

 
InputStreamReader是从字节流到字符流的桥:它读取字节,并使用指定的charset将其解码为字符 。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
每个调用InputStreamReader的read()方法之一可能会导致从底层字节输入流读取一个或多个字节。 为了使字节有效地转换为字符,可以从底层流读取比满足当前读取操作所需的更多字节。
为了最大的效率,请考虑在BufferedReader中包装一个InputStreamReader。 例如:
  BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 

InputStreamReader

InputStreamReader(InputStream in)
创建一个使用默认字符集的InputStreamReader。

字符流读取数据

int read()

一次读一个字符数据

int read(char[] cbuf)

一次读一个字符数组数据

读取文件

public static void read() throws IOException {
    File file = new File("D:\\io.txt");
    InputStreamReader in = new InputStreamReader(new FileInputStream(file), "UTF-8");
    // 一次性取多少个字符
    char[] bytes = new char[1024];
    // 用来接收读取的字符数组
    StringBuilder sb = new StringBuilder();
    // 读取到的字符数组长度,为-1时表示没有数据
    int length = 0;
    // 循环取数据
    while ((length = in.read(bytes)) != -1) {
        // 将读取的内容转换成字符串
        sb.append(new String(bytes, 0, length));
    }
    // 关闭流
    in.close();
    System.out.println(sb.toString());
}

FileWriter&FileReader

new FileWriter等同于new OutputStreamWriter(new FileOutputStream(file, true))
public static void write() throws IOException {
    File file = new File("D:\\io.txt");
    if(!file.exists()) {
        file.createNewFile();
    }
    //OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8");
    FileWriter os = new FileWriter(file,true);
    // 要写入的字符串
    String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
    // 写入文件
    os.write(string);
    // 关闭流
    os.close();
}


public static void read() throws IOException {
    File file = new File("D:\\io.txt");
    //InputStreamReader in = new InputStreamReader(new FileInputStream(file), "UTF-8");
    FileReader in = new FileReader(file);
    // 一次性取多少个字节
    char[] bytes = new char[1024];
    // 用来接收读取的字符数组
    StringBuilder sb = new StringBuilder();
    // 读取到的字节数组长度,为-1时表示没有数据
    int length = 0;
    // 循环取数据
    while ((length = in.read(bytes)) != -1) {
        // 将读取的内容转换成字符串
        sb.append(new String(bytes, 0, length));
    }
    // 关闭流
    in.close();
    System.out.println(sb.toString());
}

缓冲流

字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作

字节缓冲流

public static void read() throws IOException {
        File file = new File("D:\\io.txt");
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
        // 一次性取多少个字节
        byte[] bytes = new byte[1024];
        // 用来接收读取的字节数组
        StringBuilder sb = new StringBuilder();
        // 读取到的字节数组长度,为-1时表示没有数据
        int length = 0;
        // 循环取数据
        while ((length = in.read(bytes)) != -1) {
            // 将读取的内容转换成字符串
            sb.append(new String(bytes, 0, length));
        }
        // 关闭流
        in.close();
        System.out.println(sb.toString());
    }

private static void writeData() throws IOException {
    // 字节输出流
    FileOutputStream out = new FileOutputStream("D:\\io.txt", true);
    // 使用字节缓冲流对out字节流进行包装(缓冲)
    BufferedOutputStream bos = new BufferedOutputStream(out);
    //写入的数据
    String msg = "使用字节缓冲流保存数据到文件";
    //转换字节数组
    byte[] bytes = msg.getBytes();
    bos.write(bytes);
    bos.flush(); 
    bos.close();
}

字符缓冲流

BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途。
Java提供了FileWriter和FileReader简化字符流的读写,new FileWriter等同于
new OutputStreamWriter(new FileOutputStream(file, true))
/**
     * 字符缓冲流
     * @throws IOException
     */
    public static void charwrite() throws IOException {
        File file = new File("D:\\io.txt");
        if(!file.exists()) {
            file.createNewFile();
        }
        //BufferedWriter os = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8"));
        //等同上面
        BufferedWriter os = new BufferedWriter(new FileWriter(file,true));
        // 要写入的字符串
        String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
        // 写入文件
        os.write(string);
        // 关闭流
        os.close();
    }

    /**
     * 字符缓冲流
     * @throws IOException
     */
    public static void charread() throws IOException {
        File file = new File("D:\\io.txt");
        //BufferedReader in  = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
        BufferedReader in  = new BufferedReader(new FileReader(file));
        // 一次性取多少个字符
        char[] bytes = new char[1024];
        // 用来接收读取的字符数组
        StringBuilder sb = new StringBuilder();
        // 读取到的字符数组长度,为-1时表示没有数据
        int length = 0;
        // 循环取数据
        while ((length = in.read(bytes)) != -1) {
            // 将读取的内容转换成字符串
            sb.append(new String(bytes, 0, length));
        }
        // 关闭流
        in.close();
        System.out.println(sb.toString());
    }

/**
 * 字符缓冲输入流按行读取
 * @throws IOException
 */
public static void BufferedReader() throws IOException {
    File file = new File("D:\\io.txt");
    InputStream is =new FileInputStream(file);
    BufferedReader in  = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
    StringBuilder sb = new StringBuilder();
    String temp = null;
    while ((temp = in.readLine()) != null) {
        // 将读取的内容转换成字符串
        sb.append(temp);
        sb.append("\r\n");
    }
    // 关闭流
    in.close();
    System.out.println(sb.toString());
}

http的一个例子

conn.getInputStream()返回InputStream
InputStreamReader的构造函数InputStreamReader(InputStream in, Charset cs)
BufferedReader的构造函数BufferedReader(Reader in) 需要一个Reader的子类实例
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));

转换流

InputStreamReader  和 OutputStreamWriter  对字节流进行字符流转换
public static void write() throws IOException {
    File file = new File("D:\\io.txt");
    if(!file.exists()) {
        file.createNewFile();
    }
    //字节输出流
    FileOutputStream os = new FileOutputStream(file, true);
    //转为字符输出流
    OutputStreamWriter writer = new OutputStreamWriter(os,"UTF-8");
    // 要写入的字符串
    String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
    // 字符流输出
    writer.write(string);
    // 关闭流
    writer.close();
}


public static void read() throws IOException {
    File file = new File("D:\\io.txt");
    //字节流
    FileInputStream fi = new FileInputStream(file);
    //转字符流
    InputStreamReader in = new InputStreamReader(fi, "UTF-8");
    // 一次性取多少个字符
    char[] chars = new char[1024];
    // 用来接收读取的字符数组
    StringBuilder sb = new StringBuilder();
    // 读取到的字节数组长度,为-1时表示没有数据
    int length = 0;
    // 循环取数据
    while ((length = in.read(chars)) != -1) {
        // 将读取的内容转换成字符串
        sb.append(new String(chars, 0, length));
    }
    // 关闭流
    in.close();
    System.out.println(sb.toString());
}

打印流

PrintStream字节流

PrintWriter字符流

对象流

ObjectInputStream

ObejctInputStream类实现对象反序列化,从文件中读取01序列转换为对象

InputStream in = new FileInputStream("d:/obj.txt");
ObjectInputStream ois = new ObjectInputStream(in);
Object obj = ois.readObject();      //从文件中读取一个对象, readObject()方法的返回值是Object类型的
//文件中实际存储的是Person对象, 使用obj引用指向Person对象
System.out.println( obj );      //实际上调用的是Person对象的toString()方法
ois.close();

/*
* 在对象序列化之后 ,即把对象已经保存到文件中了,  又在Person类中添加了一个字段,修改了Person类结构,
*   再进行反序列化时, 出现了异常:
*  java.io.InvalidClassException:
*   com.wkcto.chapter06.objectstream.Person; local class incompatible: 
*       stream classdesc serialVersionUID = 3479771803741762411, 
*       local class serialVersionUID = 1549311491347595402
* 分析原因:
*       流中类的描述信息中 serialVersionUID的值与本地字节码文件中 serialVersionUID字段的值不相等引发的异常
* 
*       当类Person实现了Serializable接口后, 系统会自动的在Person类中增加一个serialVersionUID序列化版本号字段
*       在lisi对象序列化时, serialVersionUID字段的值是: 3479771803741762411
*       当序列化后, 又在Person类添加了gender字段, 编译后,在字节码文件中重新生成了一个serialVersionUID的值:1549311491347595402
*       在进行反序列化时, 系统会检查流中serialVersionUID序列化版本号字段与本地字节码文件中serialVersionUID字段的值是否一样
*           如果相等就认为是同一个类的对象, 如果这个serialVersionUID序列化版本号字段的值不相等,就认为是不同类的对象
* 解决方法:
*       保证反序列化时流中serialVersionUID字段 的值,与本地字节码文件中serialVersionUID字段的值相等即可
*       可以在Person类实现了Serializable接口后, 手动的添加一个serialVersionUID字段 
*/

ObjectOutputStream

ObjectOutputStream类可以实现对象序列化, 把对象转换为01序列保存到文件中
注意:
对象序列化/反序列化的前提是对象的类必须实现Serializable接口, 该接口是一个标志接口,没有任何方法,只是告诉编译器这个类的对象可以序列化。
//声明对象并实现接口
public class Person implements Serializable{}
//创建Person对象
Person lisi = new Person("lisi", 18);
//把lisi对象序列化, 就是把lisi对象保存到文件中
OutputStream out = new FileOutputStream("d:/obj.txt");
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(lisi);      //对象序列化
oos.close();

版权声明:本文为清歌王子原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wuyaoqing/p/16359142.html