JavaSE高级开发之JavaIO

File文件操作类

JavaSE高级开发之JavaIO_第1张图片
在java.io包中,File类是唯一一个与文件本身操作(创建、删除、取得信息..)有关的程序类。
File类的基本使用
在windows下,路径记得加盘符如”C:”

  • File(”pathname“)//构造
  • createNewFile()//创建一个新文件
  • exist是()//存在否
  • delete()//删除
  • mkdirs()//创建路径
  • getParentFile()//取得父对象
  • isFile()//是文件否
  • isDirectory//是路径否
  • length()//文件大小(字节)
  • lastModified()//最后一次修改日期
public class TestDemo{
    public static void main(String[] args) throws IOException {
        File file = new File("C:"+File.separator+"Users"+File.separator+"wrinkle"+File.separator+"Desktop"+File.separator+"Test"+File.separator+"Test.txt");
        File file2 = new File("C:"+File.separator+"Users"+File.separator+"wrinkle"+File.separator+"Desktop"+File.separator+"HashMap与HashTable区别.png");
        if (!file.getParentFile().exists()) {
            //file.mkdirs();//全部当成文件夹
            file.getParentFile().mkdirs();
        }
        if(!file.exists()) {//不存在,创建
            file.createNewFile();
        }
        if(file.exists()) {
            file.delete();//先删除文件
            file.getParentFile().delete();//再删除路径
        }
        System.out.println(file2.exists());//存在否
        System.out.println(file2.length());//大小
        System.out.println(new Date(file2.lastModified()));//最后一次时间,是时间戳,转换一下
    }
}
//+++++++++++++++++++++++++++++++++++++++++++
true
352885
Mon May 21 17:56:00 GMT+08:00 2018

显示当前文件夹下文件

  • lsitFiles()
public class TestDemo{
public static void main(String[] args) throws IOException {
    File file = new File("C:"+File.separator+"Users"+File.separator+"wrinkle"+File.separator+"Desktop");//+File.separator+"Test.txt");
    File [] result = file.listFiles();//打印文件路径下文件
    for (File file2 : result) {
        System.out.println(file2);
    }
    }
}

//+++++++++++++++++++++++++++++++++++++++++++++
C:\Users\wrinkle\Desktop\360安全卫士.lnk
C:\Users\wrinkle\Desktop\360软件管家.lnk
C:\Users\wrinkle\Desktop\Advanced Archive Password Recovery.lnk
C:\Users\wrinkle\Desktop\Control Panel.lnk
C:\Users\wrinkle\Desktop\desktop.ini
C:\Users\wrinkle\Desktop\eclipse.exe - 快捷方式.lnk
C:\Users\wrinkle\Desktop\eclipse.exe.lnk
...

递归打印当前文件夹所有文件:

public class TestDemo{
public static void main(String[] args) throws IOException {
    File file = new File("C:"+File.separator+"Users"+File.separator+"wrinkle"+File.separator+"Desktop");//+File.separator+"Test.txt");
    listFiles(file);//递归函数
    }
    public static void listFiles(File file) {
        if (file.isDirectory()) {
            File[] result = file.listFiles();
            if(null != result) {
            for (File file2 : result) {//取出所有文件路径
                listFiles(file2);//开始递归
                }
            }
        }
        else {
            System.out.println(file);
        }
    }
}
//+++++++++++++++++++++++++++++++++
...



字节流与字符流

流操作简介:
File文件不支持文件内容处理,如果处理文件内容,必须要通过流操作模式来完成。流分为输入流和输出流。
在java.io包中,流又分为字节流和字符流:

  • 字节流:InputStream、OutputStream
  • 字符流:Reader、Writer

字符流和字节流的区别:

  • 字节流是原生操作,字节流是经过处理的

使用流程:
- 根据文件路径创建File类对象
- 根据字节流或字符流的子类实例化父类对象
- 进行数据读写操作
- 关闭流(close())

字节输出流 OutputStream
使用字节输出流需要使用Java.io.OutputStream

  • public abstract class OutputStream implements Closeable, Flushable

OutputStream实现了Closeable、Flushable接口,这两个接口中的方法:close(),flush()
此外,还有其他方法:

  • 将给定的字节数组内容全部输出:public void write(byte b[]) throws IOException
  • 将部分字节数组内容输出:public void write(byte b[], int off, int len) throws IOException
  • 输出单个字节:public abstract void write(int b) throws IOException;

由于OutputStream是一个抽象类,想要为父类实例化,就必须使用子类,父类已经声明好,只需要使用构造方法即可FileOutputStream(File)、FileOutputStream(File,boolean)。

public class TestDemo{
public static void main(String[] args) throws IOException {
    File file = new File("C:"+File.separator+"Users"+File.separator+"wrinkle"+File.separator+"Desktop"+File.separator+"Test"+File.separator+"Test.txt");
    if(!file.getParentFile().exists()) {
        file.getParentFile().mkdirs();
    }
    //OutputStream outputStream = new FileOutputStream(file);   //重复写
    OutputStream outputStream = new FileOutputStream(file,true);    //追加
    String string = "Hello Jan\r\n";
    outputStream.write(string.getBytes());//全部输出
    //outputStream.write(string.getBytes(),0,5);//部分输出
//  file.delete();//在这里是不能删除的,文件还在缓存区,还没有保存,所以无法删除,应当在close之后执行
//  file.getParentFile().delete();//还在操作,所以不能删除
    outputStream.close();
//  file.delete();//删文件
//  file.getParentFile().delete();//删路径
    }
}
//+++++++++++++++++++++++++++++
Hello Jan
Hello Jan

在进行文件输出时,文件会自动创建,所以不需要再手动createNewFile()
FileOutputStream(File,false)就相当于FileOutputStream(File)

AutoCloseable自动关闭
JDK1.7以后追加了自动关闭AutoCloseable接口,但是使用起来复杂,比较奇怪,要结合try catch,而且对象实例化的操作时放在try()上的,而不是在try内部。

字节输入流 InputStream
利用InputStream可以实现文件内容的读取

  • public abstract class InputStream implements Closeable

InputStrea只实现了Closeable接口

  • 读取数据到字节数组中,返回数据的读取个数。如果此时开辟的字节数组大小大于读取的数据大小,则返回的就是读取个数;如果要读取的数据大于数组的内容,那么这个时候返回的就是数组长度;如果没有数据了还在读,则返回-1: public int read(byte b[]) throws IOException.最常用方法
  • 读取部分数据到字节数组中,每次只读取传递数组的部分内容,如果读取满了则返回长度(len),如果没有读取满则返回读取的数据个数,如果读取到最后没有数据了返回-1:public int read(byte b[], int off,int len) throws IOException
  • 读取单个字节,每次读取一个字节的内容,直到没有数据了返回-1:public abstract int read() throws
    IOException

同样,操作时也需要使用FileInputStream类。

public class TestDemo{
public static void main(String[] args) throws IOException {
    File file = new File("C:"+File.separator+"Users"+File.separator+"wrinkle"+File.separator+"Desktop"+File.separator+"Test"+File.separator+"Test.txt");
    if(!file.getParentFile().exists()) {
        file.getParentFile().mkdirs();
    }
    if (file.exists()) {
        InputStream input = new FileInputStream(file);
        byte [] data = new byte [1024];//每次读取最大数量
        int len = input.read(data);//数据放到data中
        String str = new String(data, 0, len);//转为String
        System.out.println(str);
        input.close();
    }
}
}
//+++++++++++++++++++++++++++
Hello Jan
Hello

流操作一定记得Close()。

字符输出流 Writer
字符的特点是适合处理中文。

  • public abstract class Writer implements Appendable, Closeable, Flushable

它比OutputStream多了一个Appendable接口。
在Writer类里也提供了Write()方法,但是接收类型是char,Writer类提供了一个直接输出字符串的write()方法。
操作文件需要使用FileWriter子类。

public class TestDemo{
    public static void main(String[] args) throws IOException {
    File file = new File("C:"+File.separator+"Users"+File.separator+"wrinkle"+File.separator+"Desktop"+File.separator+"Test"+File.separator+"Test.txt");
    if(!file.getParentFile().exists()) {
        file.getParentFile().mkdirs();
    }
        String str = "Hello Jan \r\n";
        Writer writer = new FileWriter(file);//创建对象
        writer.write(str);//输出
        writer.close();//关闭
    }
}

字符输入流 Reader
使用FileReader,在Reader类中没有直接读取字符串的方法,需要通过字符数组进行读取操作。

public class TestDemo{
    public static void main(String[] args) throws IOException {
    File file = new File("C:"+File.separator+"Users"+File.separator+"wrinkle"+File.separator+"Desktop"+File.separator+"Test"+File.separator+"Test.txt");
        if (file.exists()) {
            Reader reader = new FileReader(file);//创建对象
            char [] data = new char[1024];//用data装数据
            //int len = reader.read(data);
            //String str = new String(data, 0, len);
            //System.out.println(str);
            reader.read(data);//输入
            for (char c : data) {//foreach打印
                System.out.print(c);
            }
            reader.close();//关闭
        }
    }
}
//+++++++++++++++++++++++++++++++++++++
Hello Jan 

字符留适合处理中文,字节流适合处理一切数据(但对中文不友好)

字节流与字符流的区别
字节流与字符流区别不大,一般优先考虑字节流,有中文是才考虑字符流,字符需要通过内存缓冲进行处理。如果字符流不关闭,数据就有可能存于缓冲而位输出,需要强制刷新才能得到完整数据。

public class TestDemo{
    public static void main(String[] args) throws IOException {
    File file = new File("C:"+File.separator+"Users"+File.separator+"wrinkle"+File.separator+"Desktop"+File.separator+"Test"+File.separator+"Test.txt");
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        String  mse = "HaHa Jan \r\n";//输出内容
        Writer  out =new FileWriter(file);//创建对象
        out.write(mse);//输出
        out.flush();//刷新,无close()
    }
}

在没有中文处理时,优先选择字节流。

转换流

转换流的基本使用
实际上字节流与字符流是可以相互转换的OutputStreamWriter、InputStreamReader(),在实际开发中并没有什么用处。

public class TestDemo{
    public static void main(String[] args) throws IOException {
    File file = new File("C:"+File.separator+"Users"+File.separator+"wrinkle"+File.separator+"Desktop"+File.separator+"Test"+File.separator+"Test.txt");
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        OutputStream out = new FileOutputStream(file,true);//创建

        String  mse = "Hello Jan \r\n";//输出内容
        Writer  out2 =new OutputStreamWriter(out);//创建对象,转换
        out2.write(mse);//输出
        out2.flush();//刷新,无close()
        out2.close();
    }
}

实例:文件拷贝
实现把给定文件路径的文件拷贝另一个路径,如果路径不存在则创建

class CopyFileUtil{//工具类
    private CopyFileUtil() {};//构造方法私有化
    //路径检测
    public static boolean   fileIsExists(String path) {
        return new File(path).exists();
    }
    //路径创建
    public static void createParentDir(String path) {
        File file = new File(path);
        if(!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
    }
    //拷贝文件
    public static boolean copyFile(String srcPath,String desPath) {
        File inputFile = new File(srcPath);//文件取得
        File outputFile = new File(desPath);
        FileInputStream fileInputStream= null;//输入流
        FileOutputStream fileOutputStream= null;//输出流
        try {
            fileInputStream = new FileInputStream(inputFile);
            fileOutputStream = new FileOutputStream(outputFile);
            copyFileHandle(fileInputStream,fileOutputStream);//真 拷贝操作
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }finally {
            try {
                fileInputStream.close();
                fileOutputStream.close();
            } catch (IOException e2) {
                e2.printStackTrace();
            }
        }
        return true;
    }
    //拷贝核心操作
    private static void copyFileHandle(InputStream inputStream,OutputStream outputStream) throws IOException {
//      byte[] data = new byte[1024];//缓冲区
        byte[] data = new byte[10240000];//缓冲区
        int len = 0;
        //read()读完返回-1
        long start = System.currentTimeMillis();
        while ((len = inputStream.read(data)) != -1) {
            outputStream.write(data, 0, len);//0~len是因为万一不满时。
        }
        long end = System.currentTimeMillis();
        System.out.println("Time: "+(end-start));
    }
}
public class TestDemo{
    public static void main(String[] args) throws IOException {
    String srcPath = "G:"+File.separator+"BaiduYunDownload"+File.separator+"生存家族.Survival.Family.2017.BD720P.日语中字.mp4";
    String desPath = "G:"+File.separator+"生存家族.Survival.Family.2017.BD720P.日语中字.mp4";
    if(CopyFileUtil.fileIsExists(srcPath)) {
        CopyFileUtil.createParentDir(desPath);
        System.out.println(CopyFileUtil.copyFile(srcPath, desPath));
    }else {
        System.out.println("源文件不存在");
    }
    }
}

这个拷贝的实质其实就是读取数据,然后将文件输出。

字符编码

常用字符编码
常用的有:

  • GBK、GB2312,国标编码,GBK包含简体和繁体,GB2312只含简体中文
  • UNICODE,java提供的16进制编码,能描述所有文字,但是太大
  • ISO8859-1,国际通用编码,但是需要转换
  • UTF编码,相当于结合了UNICODE和ISO8859-1,如常用的UTF-8

乱码的产生
乱码产生的原因一般是因为编码与解码不统一。

public class TestDemo{
    public static void main(String[] args) throws IOException {
        File file = new File("C:"+File.separator+"Users"+File.separator+"wrinkle"+File.separator+"Desktop"+File.separator+"Test.txt");
        OutputStream out = new FileOutputStream(file);
        out.write("今晚没听懂".getBytes("ISO8859-1"));
        out.close();
    }
}
//+++++++++++++++++++++++++++
???????

内存操作流

概念
IO操作发生在内存中,而不管之后这个数据是否被保留。
即:需要IO操作,但不希望产生文件,这时就可以使用内存作为操作终端
分类:

  • 字节内存了:ByteArrayInputStream、ByteArrayOutputStream
  • 字符内存流:CharArrayReader、CharArrayWriter

通过内存流实现大小写转换

public class TestDemo{
    public static void main(String[] args) throws IOException {
        String str = "Hello Jan";
        //实例化的内容保存在内存中,而不是FileInputStream
        InputStream input = new ByteArrayInputStream(str.getBytes());
        OutputStream output = new ByteArrayOutputStream();
        int tmp = 0;
        while ((tmp = input.read())!= -1) {
            output.write(Character.toUpperCase(tmp));
        }
        System.out.println(str);
        System.out.println(output);
        input.close();
        output.close();
    }
}
//++++++++++++++++++++++++++++++++
Hello Jan
HELLO JAN

内存流操作
将两个小文件合并

public class TestDemo{
    public static void main(String[] args) throws IOException {
        File [] files = new File [] {new File("C:/Users/wrinkle/Desktop/one.txt"),new File("C:/Users/wrinkle/Desktop/two.txt")};
        String [] data = new String [2];
                File [] files = new File [] {new File("C:/Users/wrinkle/Desktop/one.txt"),new File("C:/Users/wrinkle/Desktop/two.txt")};
        String [] data = new String [2];//用来放读取的数据
        StringBuffer buffer = new StringBuffer();//用来合并后的数据
        for (int i = 0; i < files.length; i++) {
            data [i]  = readFile(files[i]);//读文件
            buffer.append(data[i]);//合并
            buffer.append(" ");//用空格分隔
        }
        System.out.println(buffer);
    }
    //读文件操作
    public static String readFile(File file) throws IOException{
        if (file.exists()) {
            InputStream input = new FileInputStream(file);//输入流
            ByteArrayOutputStream byt = new ByteArrayOutputStream();//内存输出流,保存读取的数据
            int tmp = 0;
            byte [] data = new byte [10];
            while ((tmp =input.read(data)) != -1) {//读取
                byt.write(data,0,tmp);//输出到内存
            }
            byt.close();
            input.close();
            return new String(byt.toByteArray());
        }
        return null;
    }
}

buffer.append(data[i])里append()的作用是追加String内容到buffer,因为buffer是StringBuffer类型,所以是可以追加的。之所以只能合并小文件就是String的大小是有限的,不能放太大的文件。

打印流

打印流是为了解决OutputStream的设计缺陷,属于的OutputStream的加强,如果操作的不是二进制数据,只是想向目标终端输出信息的话,OutputStream就不是很方便,其缺点:

  • 所有数据必须转换为字节数组
  • 输出int、double类的数据不便

打印流概念
为了解决OutputStream的设计缺陷
自定义打印流

class PrintUtil{
    private OutputStream out;
    public PrintUtil(OutputStream out) {
        this.out = out;
    }
    //核心操作,输出流,后面都是调用此方法或者重载
    public void print(String string) {
        try {
            this.out.write(string.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void println(String string) {
        this.print(string+"\r\n");
    }
    public void print(int data) {
        this.print(String.valueOf(data));
    }
    public void println(int data) {
        this.println(String.valueOf(data));
    }
    public void print(double data) {
        print(String.valueOf(data));
    }
    public void println(double data) {
        this.print(String.valueOf(data));
    }
}
public class TestDemo{
    public static void main(String[] args) throws IOException {
        PrintUtil printUtil = new PrintUtil(new FileOutputStream(new File("C:/Users/wrinkle/Desktop/Print.txt")));
            printUtil.print(1);
            printUtil.println(2);
            printUtil.print("Hello");
            printUtil.println("Jan");
            printUtil.print(6.0);
    }
}
//
12
HelloJan
6.0

打印流的本质就是对OutputStream进行封装

使用系统打印流
打印流分为

  • 字节打印流:PrintStream
  • 字符打印流:PrintWriter

PrintStream使用几率比较高
打印流的设计模式属于装饰者设计模式:核心功能是某个类的功能,但是为了得到更好的操作效果,让支持的功能更多一些。

格式化输出
类似于C语言中的printf,不太常用。

public static String format(String format, Object... args)
public class TestDemo{
    public static void main(String[] args) {
        String name = "Jan";
        int age = 20;
        double money = 0.005892525;
        //格式化
        String str = String.format("name: %s age: %d money: %1.5f",name,age,money);
        System.out.println(str);
    }
}
//++++++++++++++++++++++++++++++++
name: Jan age: 20 money: 0.00589

System类对IO的支持

实际上我们使用的系统输出就是利用了IO流的模式完成的,在System类中定义了三个操作常量。
- 标准输出(显示器) : public final static PrintStream out
- 错误输出 : public final static PrintStream err
- 标准输入(键盘):public final static InputStream in

系统输出
系统输出一共有两个常量:out、err,都是PrintStream类的对象。
out输出是希望用户看到的内容
err输出是不希望用户看到的内容
在实际开发中其实都用日志代替了log
System.err只是作为一个保留属性,平时几乎不会用到,更多的则是System.out,如System.out.println()
由于System.out是PrintStream的实例化对象,而PrintStream又是OutputStream的子类,所以可以直接使用System.out直接为OutputStream实例化,这个时候的OutputStream输出的位置将变为屏幕。
修改前面的自定义打印

class PrintUtil{
    private OutputStream out;
    public PrintUtil(OutputStream out) {
        this.out = out;
    }
    public void print(String string) {
        try {
            this.out.write(string.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void println(String string) {
        this.print(string+"\r\n");
    }
    public void print(int data) {
        this.print(String.valueOf(data));
    }
    public void println(int data) {
        this.println(String.valueOf(data));
    }
    public void print(double data) {
        print(String.valueOf(data));
    }
    public void println(double data) {
        this.print(String.valueOf(data));
    }
}
public class TestDemo{
    public static void main(String[] args) throws IOException {
        PrintUtil printUtil = new PrintUtil(System.out);
            printUtil.print(1);
            printUtil.println(2);
            printUtil.print("Hello");
            printUtil.println("Jan");
            printUtil.print(6.0);
    }
}
//++++++++++++++++++++++++++
12
HelloJan
6.0

输出内容没有任何变化,只是输出流从写入文件变成了输出到屏幕。

系统输入:in
System.in对应的是InputStream,而这种输入流指的是用户通过键盘进行输入,java本身并没有直接的用户输入处理,如果想要实现这种操作,必须使用java.io的模式完成。

public class TestDemo{
    public static void main(String[] args) throws IOException {
        InputStream in = System.in;//将键盘值作为输入流
        byte[] data = new byte[4];//缓存区
        System.out.println("input:>");//提示
        int tmp = in.read(data);//输入操作
        in.close();
        System.out.println(new String(data,0,tmp));//打印
    }
}
//++++++++++++++++++++++++++++++++++++++++
input:>
你好啊
你好

当输入时,程序进入阻塞状态,直到用户输入回车才继续运行,另外,就如上面打印结果所示,缓存区是固定值,太小的话会造成数据确实。
所以引用内存流。

public class TestDemo{
    public static void main(String[] args) throws IOException {
        InputStream in = System.in;//屏幕接收输入流
        ByteArrayOutputStream bb = new ByteArrayOutputStream();//内存输出流
        byte[] data = new byte[4];//缓存
        System.out.println("input:>");//提示
        int tmp = 0;
        while ((tmp = in.read(data)) != -1) {//读到内存流
            bb.write(data,0,tmp);//写到内存流
            if (tmp < data.length) {//手动检测读取结束
                break;
            }
        }
        in.close();//记得关闭流
        bb.close();
        System.out.println(new String(bb.toByteArray()));//
    }
}

两种输入流

BufferedReader类
BufferedReader类属于一个缓冲输入流,而且是一个字符流的操作对象,在java中对于缓冲流也分为两类

  • 字节缓冲流:BufferedInputStream
  • 字符缓冲流:BufferedReader

BufferedReader类的一个方法:

String readLine() throws IOException

这个方法可以直接读取一行数据,(回车)

public class TestDemo{
    public static void main(String[] args) throws IOException {
        BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));//InputReader();
        System.out.println("input:>");
        String str = buf.readLine();//读行
        System.out.println(str);
    }
}

这是多年以前的标准输入格式,早已被Scanner取代。

java.util.Scanner类
打印流解决的是OutputStream类的缺陷,BufferedReader解决的是InputStream类的缺陷。而Scanner解决的是BufferedReader类的缺陷(替换了BufferedReader类)
Scanner是一个专门进行输入处理的程序类,可以结合正则表达式进行各项处理,常用方法:

  • 判断是否有指定类型数据: public boolean hasNextXxx()
  • 取得指定类型的数据: public 数据类型 nextXxx()
  • 定义分隔符:public Scanner useDelimiter(Pattern pattern)
  • 构造方法:public Scanner(InputStream source)

实例

public class TestDemo{
    public static void main(String[] args) throws IOException {
        Scanner scn = new Scanner(System.in);
        System.out.println("Input:>");
        if(scn.hasNext()) {//是否有输入内容
            System.out.println(scn.next());
        }
        scn.close();
    }
}

接收其他数据类型

public class TestDemo{
    public static void main(String[] args) throws IOException {
        Scanner scn = new Scanner(System.in);
        System.out.println("Input:>");
        if(scn.hasNext()) {
            int age = scn.nextInt();//输入int,如果是非int程序会抛出异常
            System.out.println(age);
        }else {
            System.out.println("input error");
        }
        scn.close();
    }
}

文件操作

public class TestDemo{
    public static void main(String[] args) throws IOException {
        Scanner scn = new Scanner(new FileInputStream(new File("C:/Users/wrinkle/Desktop/Localhost名字问题.txt")));
//      scn.useDelimiter("\n");//自定义当前文件
        while (scn.hasNext()) {
            System.out.println(scn.next());
        }
        scn.close();
    }
}

总结:以后出来二进制文件拷贝处理之外,那么只要是针对程序的信息输出都用打印流(PrintStream、PrintWriter),信息输出用Scanner。

序列化

所有的开发都涉及到序列化
概念
将内存中的对象转为二进制数据流的形式进行传输,或是将其保存在文本中。不过,并非所有的对象都可以被实例化,一般要进行传输的才进行实例化,需要实例化java.io.Serializable接口,这个接口并没有任何方法定义,只是一个标识。

序列化与反序列化操作
需要用到java.io中的两个类

  • ObjectOutputStream
  • ObjectInputStream
class Person implements Serializable{
    private String name;
    private int age;
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}
public class TestDemo{
    public static final File FILE = new File("C:/Users/wrinkle/Desktop/test.txt");
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ser(new Person("Jan", 23));
    }
    public static void ser(Object obj)throws FileNotFoundException,IOException, ClassNotFoundException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(FILE));
//      ObjectOutputStream out = new ObjectOutputStream(System.out);
        out.writeObject(obj);
        out.close();
        //反序列化操作
        ObjectInputStream oin = new ObjectInputStream(new FileInputStream(FILE));
        System.out.println(oin.readObject());
        oin.close();
    }
}

transient关键字
使某些属性不被序列化,不会保存

class Person implements Serializable{
    private transient String name;
    private int age;
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}
public class TestDemo{
    public static final File FILE = new File("C:/Users/wrinkle/Desktop/test.txt");
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ser(new Person("Jan", 23));
    }
    public static void ser(Object obj)throws FileNotFoundException,IOException, ClassNotFoundException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(FILE));
//      ObjectOutputStream out = new ObjectOutputStream(System.out);
        out.writeObject(obj);
        out.close();
        ObjectInputStream oin = new ObjectInputStream(new FileInputStream(FILE));
        System.out.println(oin.readObject());
        oin.close();
    }
}
//++++++++++++++++++++++++++++++++++++
Person [name=null, age=23]

name的属性加了transient关键字,最后结果为null,因为没有被序列化保存。

你可能感兴趣的:(学习,经验,Java基础,java,IO)