Java学习笔记:IO流

File

File类概述和构造方法

File:它是文件和目录路径名的抽象表示

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

构造方法

  • File(String pathname)通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
    File f1= new File("E:\\itcast\\java.txt");
  • File(String parent, String child)从父路径名字符串和子路径名字符串创建新的File实例
    File f2= new File("E:\\itcast","java.txt");
  • File(File parent,String child)从父抽象路径名和子路径名字符串创建新的File实例
    File f3= new File("E:\\itcast");
    File f4= new File(f3,"java.txt");

File类创建功能

  • public boolean createNewFile()当具有该名称文件不存在是,创建一个由该抽象路径名命名的新空文件
File f = new File("E:\\itcast\\java.txt");
System.out.println(f.createNewFile());//文件存在返回false,不存在返回true
  • public boolean mkdir()创建由此抽象路径名命名的目录
File f = new File("E:\\itcast\\JavaSE");
System.out.println(f.mkdir());//目录存在返回false,不存在返回true,但无法创建多级目录
  • public boolean mkdirs()创建由此抽象路径名命名的目录,包括任何必须但不存在的父目录
File f = new File("E:\\itcast\\JavaWEB\\Html");
System.out.println(f.mkdirs());//目录存在返回false,不存在返回true,可以创建多级目录

File类的判断和获取功能

  • public boolean isDirectory()测试此抽象路径名表示的File是否为目录
  • public boolean isFile()测试此抽象路径名表示的File是否为文件
  • public boolean exists()测试此抽象路径名表示的File是否存在
  • public String getAbsolutePath()返回此抽象路径名的绝对路径名字符串
  • public String getPath()将此抽象路径名转换为路径名字符串
  • public String getName()返回由此抽象路径名表示的文件或目录的名称
  • public String[] list()返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
    String[] strArray = f.list();//当前目录下所有内容存入字符串数组中,可以通过输出字符串数组输出内容
  • public File[] listFiles()回此抽象路径名表示的目录中的文件和目录的File对象数组
File[] fileArray = f.listFiles();//当前目录下所有内容存入File型数组中
for(File file:fileArray){
      if(file.isFile()){
             System.out.println(file.getName());
      }
}

File类的删除功能

  • public boolean delete()删除由此抽象路径名表示的文件或目录
    若是目录下有内容(文件或目录)不能直接删除目录,要先删除内容
  • 绝对路径和相对路径
    绝对路径:完整的路径名,不需要其他信息就可以定位它表示的文件
    eg:E:\\itcast\\java.txt
    相对路径:必须使用取自其他路径名的信息进行解释
    eg:myFile\\java.txt 这里的myFile是project的模块名

递归

  • 递归解决问题需要找到的内容
    递归出口:否则会出现内存溢出
    递归规则:转换为与原问题相似的规模较小问题
  • 递归求阶乘
public static void main(String[] args) {
        int result=jc(5);
        System.out.println("5的阶乘是:"+result);
}
public static int jc(int n){
        if(n==1){
            return 1;
        }else{
            return n*jc(n-1);
        }
}
  • 用递归遍历目录
public static void main(String[] args) {
        //根据给的的路径创建一个file对象
        File srcfile=new File("D:\\itcast");
        //调用方法
        getAllFilePath(srcfile);
}
//定义1个方法,用于获取给的目录下的所有内容,参数为第1步创建的File对象
public static void getAllFilePath(File srcFile){
        //获取给定的File目录下所有文件或者目录的File数组
        File[] fileArray=srcFile.listFiles();
        //遍历该File数组,得到每1个File对象
        if(fileArray!=null){
            for(File file :fileArray){
                //判断该File对象是否是目录
                if(file.isDirectory()){
                    //是:递归调用
                    getAllFilePath(file);
                }else{
                    //不是,获取绝对路径输出在控制台
                    System.out.println(file.getAbsolutePath());
                }
            }
        }
}

字节流

IO流概述和分类

IO流概述

  • IO:输入/输出(Input/Output)
  • 流:是一种抽象的概念,是对数据传输的总称。数据在设备间传输称为流,流的本质是数据传输
  • IO流就是用来处理数据传输问题的(eg:文件复制,文件上传,文件下载)

IO流分类

  • 按照数据的流向
    输入流:读数据;输出流:写数据;
  • 按照数据类型来分
    字节流:字节输入流、字节输出流;
    字符流:字符输入流、字符输出流;
    区分方式:数据用windows自动记事本软件打开,我们可以读懂,就使用字符流,否则使用字节流。不知道使用哪种流,就使用字节流

字节流写数据

字节流抽象基类

  • InputStream:此抽象类是表示字节输入流的所有类的超类
  • OutputStream:此抽象类是表示字节输出流的所有类的超类
  • 子类名特点:子类名称都是以其父类名作为子类名的后缀

构造方法:
FileOutputStream:文件输出流用于将数据写入File

  • FileOutputStream(String name)创建文件输出流以指定的名称写入文件
  • void write(int b)将指定字节写入此文件输出流
  • void close()关闭此文件输出流并释放与此相关联的任何系统资源
//创建字节流输出对象
FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt");

FileOutputStream fos = new FileOutputStream(new File("myByteStream\\fos.txt"));

File file = new File("myByteStream\\fos.txt");
FileOutputStream fos = new FileOutputStream(file);
//上述3个创建方式效果一致
/*
     完成了3个操作:A.调用系统功能创建了文件
                   B.创建了字节输出流对象
                   C.让字节输出流对象指向创建好的文件
*/
fos.write(97);//输入的不是97,而是97的ascII码对应的内容a
fos.close();

字节流写数据3种方式

  • void write(int b)将指定的字节写入此文件输出流,1次写1个字节数据
  • void write(byte[] b)将b.length长度字节数组写入此文件输出流,1次写1个字节数组数据
byte[ ] bys = {97,98,99,100,101};
fos.write(bys);//将字符数组“abcde”写入文件中
//byte[ ] getBytes():返回字符串对应的字节数组
byte[ ] bys="abcde".getBytes();
fos.write(bys);
  • void write(byte[] b,int off,int len)对指定字节数组b,从偏移量off(索引位置)开始,取长度为len的字符数据,写入此文件输出流,1次写1个字节数组的部分数据
byte[ ] bys = "abcde".getBytes();
fos.write(bys,1,3);
fos.close();//完成操作后一定要释放资源

字节流写数据的两个小问题

  • 字节流写数据如何实现换行
    windows:\r\n
    linux:\n
    mac:\r
    eg:fos.write("\r\n".getBytes());
  • 字节流写数据如何实现追加写入
    public FileOutputStream(String name,boolean append)
    创建文件输出流以指定的名称写入文件
    如果第二个参数为true,则字节将写入文件的末尾而不是开头
    eg:FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt",true)

字节流写数据加入异常处理
finally:在异常处理时提供finally块来执行所有的清除操作,例如IO流中释放资源
finally控制的语句一定会执行,除非jvm退出

格式
try{
      可能出现异常的代码;
}catch(异常类名  变量名){
      异常的处理代码;
}finally{
      执行所有的清楚操作;
}
eg:
FileOutputStream fos = null;
try{
      fos=new FileOutputStream("myByteStream\\fos.txt");
      fos.write("hello".getBytes());
}catch(IOException e){
      e.printStackTrace();
}finally{
      if(fos != null);{
            try{
                 fos.close()
            }catch(IOException e){
                 e.printStackTrace();
            }
      }
}

字节流读数据

FileInputStream:从文件系统中的文件获取输入字节

  • FileInputStream(String name)通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名
  • 1次读1个字节步骤
    1.创建字节输入流对象
    2.调用字节输入流对象的读数据方法
    3.释放资源
FileInputStream fis = new FileInputStream("myByteStream\\fos.txt");
int by;
/*
    read():方法读到空数据会返回-1
    fis.read():读数据
    by=fis.read():把读取到的数据赋给by
    by != -1 :判断读到的数据是否是-1
*/
while((by=fis.read())!=-1){
     System.out.print((char)by)//可以读取到换行,不需要加ln,需要char强制字符转换
}
fis.close();
  • 1次读1个字节数组
FileInputStream fis = new FileInputStream("myByteStream\\fos.txt");
//int read(byte[] b);从该输入流读取最多b.length个字节的数据到1个字节数组
byte[] bys = new byte[1024]
int len;
while((len=fis.read(bys))!=-1){
     System.out.print(new String(bys,0,len));
}
fis.close();

复制文本文件

//根据数据源创建字节输入流对象
FileInputStream fis = new FileInputStream("E:\\itcast\\窗里窗外.txt");
//根据目的地创建字节输出流对象
FileOutputStream fos= new FileOutputStream("myByteStream\\窗里窗外.txt");
//读写数据,复制文本文件(1次读取1个字节,1次写入1个字节)
int by;
while((by=fis.read())!=-1){

            fos.write(by);
}
//释放资源
fos.close();
fis.close();

复制图片

//根据数据源创建字节流输入对象
FileInputStream fis=new FileInputStream("E:\\itcast\\mn.jpg");
//根据目的地创建字节输出流对象
FileOutputStream fos=new FileOutputStream("myByteStream\\mn.jpg");
//读写数据,复制图片(1次读取1个字节数组,1次写入1个字节数组)
byte[] bys=new byte[1024];
int len;
while((len=fis.read(bys))!=-1){
            fos.write(bys,0,len);
}
fos.close();
fis.close();

字节缓冲流

字节缓存流

  • BufferOutputStream:该类实现缓冲输出流。通过设置这样的输出流,应用程序向底层写入字节时,不必为每个字节进行底层系统调用
  • BufferedInputStream:创建此将创建一个内部缓冲区数组。当从流中读取或跳过字节时,内部缓冲区会根据需要从所包含的输入流中重新填充。

构造方法

  • 字节缓冲输出流:BufferedOutputStream(OutputStream out)
  • 字节缓冲输入流:BufferedInputStream(InputStream in)
  • 方法需要的是字节流,而非文件或路径:
    字节缓冲流仅仅提供缓冲区,真正读写数据还要依靠基本的字节流对象进行操作
写入数据
FileOutputStream fos = new FileOutputStream("myByteStream\\bos.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
/*等同于BufferedOutputStream bos = 
new BufferedOutputStream(new FileOutputStream("myByteStream\\bos.txt"));*/
bos.write("hello\r\n".getBytes());
bos.write("write\r\n".getBytes());
bos.close();

读出数据
BufferedInputStream bis = 
new BufferedInputStream(new FileInputStream("myByteStream\\bos.txt"));
//1次读取1个字节数据
int by;
while((by=bis.read())!=-1){
      System.out.println((char)by);
}
//1次读取1个字节数组数据
byte[] bys = new byte[1024];
int len;
while((len=bis.read(bys))!=-1){
       System.out.println(new String(bys,0,len));
}
bis.close();

复制视频
4种方式,其中基本字节流1次读取1个字节数据最慢

public static void main(String[] args) throws IOException {
        //记录开始时间
        long startTime = System.currentTimeMillis();
        //复制视频
        method1();
        method2();
        method3();
        method4();
        //记录结束时间
        long endTime=System.currentTimeMillis();
        System.out.println("共耗时:"+(endTime-startTime)+"毫秒");
    }
    //基本字节流1次读写1个字节
    public static void method1() throws IOException {
        FileInputStream fis = new FileInputStream("E:\\itcast\\字节复制.avi");
        FileOutputStream fos=new FileOutputStream("myByteStream\\字节复制.avi");
        int by;
        while((by=fis.read())!=-1){
            fos.write(by);
        }
        fos.close();
        fis.close();
    }
    //基本字节流1次读写1个字节数组
    public static void method2() throws IOException {
        FileInputStream fis = new FileInputStream("E:\\itcast\\字节复制.avi");
        FileOutputStream fos=new FileOutputStream("myByteStream\\字节复制.avi");
        byte[] bys=new byte[1024];
        int len;
        while((len=fis.read(bys))!=-1){
            fos.write(bys,0,len);
        }
        fos.close();
        fis.close();
    }
    //字节缓冲流1次读写1个字节
    public static void method3() throws IOException {
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream("E:\\itcast\\字节复制.avi"));
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("myByteStream\\字节复制.avi"));
        int by;
        while((by=bis.read())!=-1){
            bos.write(by);
        }
        bos.close();
        bos.close();
    }
    //字节缓冲流1次读写1个字节数组
    public static void method4() throws IOException {
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream("E:\\itcast\\字节复制.avi"));
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("myByteStream\\字节复制.avi"));
        byte[] bys=new byte[1024];
        int len;
        while((len=bis.read(bys))!=-1){
            bos.write(bys,0,len);
        }
        bos.close();
        bis.close();
}

字符流

字符流出现原因

  • 字节流操作中文不便,java提供字符流
    字符流 = 字节流 + 编码表
  • 字节流复制文本文件时对中文解决方案
    汉字存储:GBK编码,占2个字节;UTF-8编码,占3个字节
    底层操作自动进行字节拼接成中文,且汉字存储时,第一个字节总是负数

编码表

  • GBK:最常用的中文码表,GB2312标准基础上的扩展规范,双字节编码方法,支持繁体简体,日韩文汉字
  • UTF-8编码:表示Unicode标准(能表达任意语言,业界统一标准,有UTF-8,UTF-16,UTF-32三种编码方案)中任意字符。电子邮件,网页和其他存储或传输文字应用中优先采用的编码,所有互联网协议都必须支持UTF-8编码。使用1-4字节为每个字符编码。

ps:1.128ASCII码-1字节;拉丁文等-2字节;大部分常用文字包括中文-3字节
2.采用任何规则编码,就要采用对应规则解码,否则会出现乱码

字符串中编码解码问题

编码

  • byte[] getBytes():
    使用平台默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中
String s="中国";
byte[] bys=s.getBytes();
  • byte[] getBytes(String charsetName):
    使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中
String s="中国";
byte[] bys=s.getBytes("UTF-8");
byte[] bys=s.getBytes("GBK");

解码

  • String(byte[] bytes):
    通过使用平台的默认字符集解码指定的字节数组来构造新的String
String ss = new String(bys)//bys是存储编码后信息的字节数组
  • String(byte[] bytes,String charsetName):
    通过指定的字符集解码指定的字节数组来构造新的String
byte[] bys=s.getBytes("UTF-8");//怎么编码就怎么解码
String ss = new String(bys,"UTF-8");
byte[] bys=s.getBytes("GBK");
String ss = new String(bys,"GBK");

字符流的编码解码问题

字符流抽象基类

  • Reader:字符输入流的抽象类
  • Writer:字符输出流的抽象类

字符流和编码解码问题相关的两个类

  • InputStreamReader字节流到字符流的桥梁
    读取字节,并使用指定的编码将其解码为字符
    使用字符集可以由名称指定,也可以被明确指定,或者可以接收平台默认字符集
InputStreamReader isr=new InputStreamWriter(new FileOutputStream("myChartStream\\osw.txt"),"xxxx")
//可以自选编码方式,或者不写采用默认编码
//1次读取1个字符数据
int ch
while((ch=isr.read())!=-1){
       System.out.print((char)ch);
}
isr.close();
  • OutputStreamWriter字符流到字节流的桥梁
    使用指定的编码将写入的字符编码为字节
    使用字符集可以由名称指定,也可以被明确指定,或者可以接收平台默认字符集
OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("myChartStream\\osw.txt"),"xxxx")
//可以自选编码方式,或者不写采用默认编码
osw.write("中国");
osw.close();

字符流写数据的5种方式

  • void write(int c)写一个字符
  • void write(char[] cbuf)写入一个字符数组
  • void write(char[] cbuf,int off,int len)写入字符数组的一部分(索引位置off开始,长度len)
  • void write(String str)写一个字符串
  • void write(String str,int off,int len)写一个字符串的一部分索引位置off开始,长度len)
  • void flush()刷新流,还可以继续写数据
  • void close()关闭流,释放资源,但在关闭前会先刷新流。一旦关闭就不能再写数据
//创建1个使用默认字符编码的OutputStreamWriter
OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("FileIO\\osw.txt"));
//void write(int c)写1个字符
osw.write(97);
osw.flush();//void flush():刷新流
//写入一个字符数组
char[] chs={'a','b','c','d','e'};
osw.write(chs);
//写入字符数组的一部分
osw.write(chs,1,3);
//写一个字符串
osw.write("abcde");
//写一个字符串一部分
osw.write("abcde",1,3);
osw.close();

字符流读数据的2种方式

  • int read()一次读一个字符数据
  • int read(char[] cbuf)一次读一个字符数组数据
//创建1个使用默认字符集的InputStreamReader
 InputStreamReader isr=new InputStreamReader(new FileInputStream("FileIO\\osw.txt"));
//1次读1个字符数据
int ch;
while((ch=isr.read())!=-1){
     System.out.println((char)ch);
}
//1次读1个字符数组数据
char[] chs=new char[1024];
int len;
while((len=isr.read(chs))!=-1){
      System.out.println(new String(chs,0,len));
}
isr.close();

案例:复制java文件

//根据数据源创建字符输入流对象
 InputStreamReader isr=new InputStreamReader(new FileInputStream("FileIO\\isw.java"));
//根据目的地创建字符输出流对象
OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("FileIO\\osw.java"));
//1次读1个字符数组数据
char[] chs=new char[1024];
int len;
while((len=isr.read(chs))!=-1){
      osw.write(chs,0,len);
}
isr.close();
osw.close();

复制java文件改进

  • FileReader(String fileName)用于读取字符文件的便捷类,InputStreamReader子类
  • FileWriter(String fileName)用于写入字符文件的便捷类,OutputStreamWriter子类
//根据数据源创建字符输入流对象
FileReader fr=new FileReader("FileIO\\fr.java");
//根据目的地创建字符输出流对象
FileWriter fw=new FileWriter("FileIO\\fw.java");
//1次读1个字符数组数据
char[] chs=new char[1024];
int len;
while((len=fr.read(chs))!=-1){
      fw.write(chs,0,len);
}
isr.close();
osw.close();

字符缓冲流

  • BufferedWriter(Writer out)将文本写入字符输出流,缓冲字符,以提供单个字符、数组和字符串的高效写入,可以指定缓冲区大小,或默认大小。
BufferedWriter bw=new BufferedWriter(new FileWriter("FileIO\\bw.txt"));
bw.write("hello\r\n");
bw.write("world\r\n");
bw.close();
  • BufferedReader(Reader in)从字符输入流读取文本,缓冲字符,以提供字符、数组和行的高效读取,可以指定缓冲区大小,或默认大小。
BufferedReader br=new BufferedReader(new FileReader("FileIO\\br.txt"));
//1次读1个字符数据
int ch;
while((ch=br.read())!=-1){
            System.out.println((char)ch);
}
//1次读1个字符数组数据
char[] chs=new char[1024];
int len;
while((len=br.read(chs))!=-1){
            System.out.println(new String(chs,0,len));
}
br.close();

用缓冲流进行java文件复制和上面案例一致,只是创建的输入流和输出流对象不同
字符缓冲流特有功能
BufferedWriter

  • void newLine():写一行,行分隔符,行分隔符字符串由系统属性定义

BufferedReader:

  • public String readLine():读一行文字。结果包含行的内容的字符串,不包括任何行终止字符,如果流已经到达结尾,则为null

用特有功能复制java文件

//根据数据元源创建字符缓冲输入流对象
BufferedReader br=new BufferedReader(new FileReader("FileIO\\br.java"));
//根据目的地创建字符缓冲输出流对象
BufferedWriter bw=new BufferedWriter(new FileWriter("FileIO\\bw.java"));
//读写数据,复制文件
//使用字符缓冲流特有功能实现
String line;
while((line=br.readLine())!=null){
      bw.write(line);
      bw.newLine();
      bw.flush();
}
//释放资源
bw.close();
br.close();

IO流小结

Java学习笔记:IO流_第1张图片
2021-01-31_172450.jpg

字节输入流2种读数据方式,字节输出流也是两种写数据方式
字节流可以复制任意文件数据,4种方式一般采用字节缓冲流1次写1个字节数组方式


Java学习笔记:IO流_第2张图片
2021-01-31_172631.jpg

字符流涉及编码问题只能用InputStream
字符流只能复制文本数据,5种方式一般采用字符缓冲流的特有功能

特殊操作流

标准输入流

System类中有两个静态的成员变量

  • public static final InputStream in
    标准输入流,通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源
  • public static final PrintStream out
    标准输出流,通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标

在不用Scanner的情况下实现键盘录入数据

  • BufferedReader br = new BufferedReader(new InputStreamReader(System.in))
    将键盘录入转化为字节流再转化为字符缓冲输出流,就可以读中文和数字

输出语句的本质:是一个标准的输出流

  • PrintStream ps = System.out
  • PrintStream类有的方法,System.out都可以使用

打印流

打印流分类

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

打印流特点

  • 只负责输出数据,不负责读取数据
  • 有自己的特有方法

字节打印流

  • PrintStream(String fileName):使用指定的文件名创建新的打印流
  • 使用继承父类的方法write()方法写数据,查看的时候会转码;
    使用自己特有的方法print(),println()写数据,查看的数据原样输出;
PrintStream ps = new PrintStream("FileIO\\ps.txt");
ps.write(97);//输出a
ps.print(97);//输出97

字符打印流
构造方法

  • PrintWriter(String fileName)用指定的文件名创建1个新的PrintWriter,不需要自动执行刷新
PrintWriter pw=new PrintWriter("FileIO\\pw.txt");
此类pw,write()写数据不刷新,println()写数据换行但不刷新
  • PrintWriter(Writer out,boolean autoFlush)创建1个新的PrintWriter
    out:字符输出流
    autoFlush:一个布尔值,如果为真,则println,printf,format方法将刷新输出缓冲区
PrintWriter pw=new PrintWriter(new FileWriter("FileIO\\pw.txt",true));
此类pw,println()写数据换行且刷新

打印流改进复制java文件

//把模块目录下的PrintStreamDemo.java文件复制到模块目录下Copy.java
public class CopyJavaDemoImprove {
    public static void main(String[] args) throws IOException {
        //根据数据源创建字符输入流对象
        BufferedReader br=new BufferedReader(new FileReader("FileIO\\PrintStreamDemo.java"));
        //根据目的地创建字符输出流对象
        PrintWriter pw=new PrintWriter(new FileWriter("FileIO\\Copy.java"),true);
        //读写数据,复制文件
        String line;
        while((line=br.readLine())!=null){
            pw.println(line);
        }
        //释放文件
        pw.close();
        br.close();
    }
}

对象序列化流

对象序列化:将对象保存在磁盘中,或者在网络中传输对象
这种机制就是使用1个字节序列表示1个对象

字节序列

  • 包含:对象的类型、对象的数据、对象中存储的属性等
  • 字节序列写到文件后,相当于文件中持久保存了1个对象的信息,因此可以从文件中读取字节序列,重构对象,并对它进行反序列化

对象序列化流

  • ObjectOutputStream将Java对象原始数据类型和图型写入OutputStream
    可以使用其读取重构对象,也可以通过流的文件来实现对象的持久存储
    如果流是网络套接字流,则可以在另一主机或进程中重构对象
  • 构造方法ObjectOutputStream(OutputStream out)
    创建一个写入指定的OutputStream的ObjectOutputStream
  • 序列化对象的方法void writeObject(Object obj)
    将指定的对象写入ObjectOutputStream
public class Student implements Serializable {
     ......
}
public static void main(String[] args) throws IOException {
        //创建1个写入指定OutputStream的ObjectOutputStream
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("FileIO\\oos.txt"));
        //创建对象
        Student s=new Student("Jack",20);
        //将指定的对象写入ObjectOutputStream
        oos.writeObject(s);
        //释放资源
        oos.close();
}

ps
1.类的序列化由实现java.io.Serializable接口的类启用,不实现此接口的类将不会使任何状态序列化或反序列化
2.Serializable是一个标记接口,实现该接口,不需要重写任何方法

对象反序列化流

  • 对象反序列化流ObjectInputStream
    反序列化先前使用ObjectOutputStream编写的原始数据和对象
  • 构造方法ObjectInputStream(InputStream in)
    创建从指定的InputStream读取的ObjectInputStream
  • 反序列化对象的方法Object readProject()
    从ObjectInputStream读取一个对象
public static void main(String[] args) throws IOException, ClassNotFoundException {
        //创建从指定的InputStream读取的ObjectInputStream
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("FileIO\\oos.txt"));
        //从ObjectInputStream中读取一个对象
        Object obj=ois.readObject();
        Student s=(Student)obj;
        System.out.println(s.getName()+","+s.getAge());
        ois.close();
}

对象序列化流操作中的3个问题

  • 对象序列化流序列化1个对象后,加入修改了对象所属的类文件,读取数据是否会出问题?
    会,当序列化运行是检测到类中的以下问题之一时抛出
    1.类的串行版本与从留中读取的类描述符的类型不匹配
    2.该类包含未知的数据类型
    3.该类没有可访问的无参数构造函数

  • 出了第一个问题如何处理?
    给对想所属的类加一个序列化ID值
    private static final long serialVersionUID = 42L

  • 1个对象中的某个成员变量的值不想被序列化,该如何实现?
    使用transient来修饰成员变量
    eg: private transient int age

Properties

Properties概述

  • 是一个Map体现的集合类
  • Properties可以保存到流中或从流中加载

作为Map集合使用

//创建集合对象
Properties prop=new Properties();
//存储元素
prop.put("jack",30);
prop.put("tom",26);
prop.put("mary",35);
//遍历集合
//不知道泛型,所以每个键和值都是Objcet型
Set keySet=prop.keySet();
for(Object key:keySet){
       Object value=prop.get(key);
       System.out.println(key+","+value);
}
 
 

Properties作为集合的特有方法

  • Object setProperty(String key,String value)
    设置集合的键和值,都是String型,底层调用Hashtable方法put
    prop.setProperty("B17041634","张三")
  • String getProperty(String key)
    使用此属性列表中指定的键搜索属性
    prop.getProperty("B17041634")
  • Set stringPropertyNames()
    从该属性列表返回一个不可修改的键集,其中键及其对应的值是字符串
Set names=prop.stringPropertyNames();
for(String key:names){
     System.out.println(key);
}

Properties和IO流结合的方法

  • 与字节流结合
    void load(InputStream inStream)从输入字节流读取属性列表(键和元素对)
    void store(OutputStream out,String comments)
    将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(InputStream)方式的格式写入输出字节流

  • 与字符流结合
    void load(Reader reader)从输入字符流读取属性列表(键和元素对)
    void store(Writer writer,String comments)
    将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(Reader)方式的格式写入输出字符流

public static void main(String[] args) throws IOException {
        //把集合中的数据保存到文件
        myStore();
        //把文件中的数据加载到集合
        myload();
    }

    private static void myload() throws IOException{
        Properties prop=new Properties();
        FileReader fr=new FileReader("FileIO\\fr.txt");
        prop.load(fr);
        fr.close();
        System.out.println(prop);
    }

    private static void myStore() throws IOException {
        Properties prop=new Properties();
        prop.setProperty("B17041723","Jack");
        prop.setProperty("B17041743","Tom");
        prop.setProperty("B17041712","Mary");
        FileWriter fw=new FileWriter("FileIO\\fw.txt");
        prop.store(fw,null);
        fw.close();
}

你可能感兴趣的:(Java学习笔记:IO流)