Java IO技术

IO技术

_01. IO技术概述

  • Output
    把内存中的数据存储到持久化设备上这个动作称为输出(写)Output操作
  • Input
    把持久设备上的数据读取到内存中的这个动作称为输入(读)Input操作

_02. File类

1、File类的概述和作用

File类是文件和目录路径名的抽象表示形式。
Java中把文件或者目录(文件夹)都封装成File对象
我们要去操作硬盘上的文件,或者文件夹只要找到File这个类即可。


2、File类静态的成员变量
  1. pathSeparator
    与系统有关的路径分隔符:
是一个分号;
目录的分割(window中环境变量配置各个路径用分号分割,表示一个完整的路径结束) 
Linux中是冒号 :
  1. separator
    与系统有关的默认名称分隔符:
向右 \  目录名称分割  Linux / 

3、File类的构造方法
  1. File(String pathname)
通过将给定路径名字符串转换为一个File对象,之后可以使用File中的方法.
windows中的路径或文件名不区分大小写.
  1. File(String parent, String child)
传递路径,传递字符串父路径,字符串子路径
好处: 单独操作父路径和子路径
  1. File(File parent, String child)
传递路径,传递File类型父路径,字符串子路径
好处: 父路径是File类型,父路径可以直接调用File类方法

4、File类创建文件功能

public boolean createNerFile()

File创建文件的功能:
创建的文件路径和文件名,在File构造方法中给出
文件已经存在了,不在创建

5、File类创建目录功能
  1. public boolean mkdir()
创建文件夹 如果存在这样的文件夹,就不创建了,返回false
创建的路径也在File构造方法中给出
  1. public boolean mkdirs()
创建的路径也在File构造方法中给出
文件夹已经存在了,不在创建
可以递归创建多层文件夹

6、File类删除功能

public boolean delete()

删除的文件或者是文件夹,在File构造方法中给出
删除成功返回true,删除失败返回false
删除方法,不走回收站,直接从硬盘中删除
删除文件夹时:文件夹不能有内容

7、File获取功能
  1. String getName()
    返回路径中表示的文件或者文件夹名
  2. long length()
    返回路径中表示的文件的字节数
  3. String getAbsolutePath()
    获取绝对路径,返回String对象
  4. String getAbsoluteFile()
    获取绝对路径,返回File对象. eclipse环境中,写一个相对路径,绝对位置工程根目录
  5. String getParent()
    获取父路径,返回String对象
  6. File getParentFile()
    获取父路径,返回File对象

8、文件的判断功能
  1. boolean exists()
    判断File构造方法中封装路径是否存在
  2. boolean isDirectory()
    判断File构造方法中封装的路径是不是文件夹,如果是文件夹,返回true,不是文件返回false
  3. boolean isFile()
    判断File构造方法中封装的路径是不是文件

9、File类list获取功能
  1. String[] list()
    获取到,File构造方法中封装的路径中的文件和文件夹名 (遍历一个目录)
    返回只有名字.
  2. File[] listFiles()
    获取到,File构造方法中封装的路径中的文件和文件夹名 (遍历一个目录)
    返回的是目录或者文件的全路径

  3. static File[] listRoots()
    获取系统中的所有根目录.
    windows中即盘符 C:\

例:

@Test 
    public void testFileList(){
        File[] fileArr = File.listRoots();
        for(File f: fileArr){
            System.out.println(f);
        }
        File file = new File("c:");
        fileArr = file.listFiles();
        for (File f : fileArr){
            System.out.println(f);
        }
        String[] strArr = file.list();
        System.out.println(strArr.length);
        for(String str : strArr){
            System.out.println(str);
        }
    }

10、文件过滤器

作用:
过滤一个目录下的指定扩展名的文件,或者包含某些关键字的文件夹。

方法介绍:
1. public String[] list(FilenameFilter filter)
2. public File[] listFiles(FileFilter filter)

例:

/*
 * 自定义过滤器
 * 实现FileFilter接口,重写抽象方法
 */
public class MyFilter implements FileFilter{
    @Override
    public boolean accept(File pathname) {
        /*
         * pathname 接受到的也是文件的全路径
         * c:\\demo\\1.txt
         * 对路径进行判断,如果是java文件,返回true,不是java文件,返回false
         * 文件的后缀结尾是.java
         */
        return pathname.getName().endsWith(".java");
    }
}

    /*
     *  File类的获取,文件获取过滤器
     *  遍历目录的时候,可以根据需要,只获取满足条件的文件
     *  遍历目录方法 listFiles()重载形式
     *  listFiles(FileFilter filter)接口类型
     *  传递FileFilter接口的实现类
     *  自定义FileFilter接口实现类,重写抽象方法,
     *  接口实现类对象传递到遍历方法listFiles
     */
    @Test
    public void testFileFilter(){
        File file = new File("j:\\");
        File[] fileArr = file.listFiles(new MyFilter());
        for (File f : fileArr) {
            System.out.println(f);
        }
    }

文件过滤器_原理分析:

    *listFiles()遍历目录的同时,获取到了文件名全路径,调用过滤器的方法accept,将获取到的路径  传递给accept方法的参数pathname
    * accept方法接收了参数pathname,参数是listFiles传递来的
    * 在accept方法中,进行判断,如果这个路径是Java文件,返回true,走着返回false
    * 一旦方法返回了true
    * listFiles将路径保存到File数组中

11、递归遍历全目录
    @Test
    public void testGetAllDir(){
        File dir = new File("j:\\develop");
        getAllDir(dir);
    }
    public void getAllDir(File dir){
        System.out.println(dir);
        //调用方法listFiles()对目录,dir进行遍历
        File[] fileArr = dir.listFiles();
        for (File f : fileArr) {
            //判断变量f表示的路径是不是文件夹
            if(f.isDirectory()){
                getAllDir(f);
            }else {
                System.out.println(f);
            }
        }
    }

12、遍历目录下的所有java文件
/*
 * 自定义过滤器
 * 实现FileFilter接口,重写抽象方法
 */
public class MyFilter implements FileFilter{
    @Override
    public boolean accept(File pathname) {
        //判断获取的是目录,直接返回true
        if(pathname.isDirectory())
            return true;
        return pathname.getName().toLowerCase().endsWith(".java");
    }
}

    @Test
    public void testFilterJava(){
        getAllJava(new File("j:\\"));
    }
    public static void getAllJava(File dir){
        //调用File对象方法listFiles()获取,加入过滤器
        File[] fileArr = dir.listFiles(new MyFilter());
        for (File f : fileArr){
            if(f.isDirectory()){
                //递归进入文件夹遍历
                getAllJava(f);
            }else{
                System.out.println(f);
            }
        }
    }


_03字节输出OutputStream流/字节输入InputStream流

java

1、字节输出流OutputStream
* A: 字节输出流OutputStream
    * a.概念
        * IO流用来处理设备之间的数据传输
        * Java对数据的操作是通过流的方式
        * Java用于操作流的类都在IO包中
        * 流按流向分为两种:输入流,输出流。
        * 流按操作类型分为两种:
            * 字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
            * 字符流 : 字符流只能操作纯字符数据,比较方便,(即处理文本文件)。
    * b.IO流常用父类
        * 字节流的抽象父类:
            * InputStream 
            * OutputStream
        * 字符流的抽象父类:
            * Reader 
            * Writer        
    * c.IO程序书写
        * 使用前,导入IO包中的类
        * 使用时,进行IO异常处理
        * 使用后,释放资源
    * d: 方法介绍
        *  void close(): 关闭此输出流并释放与此流有关的所有系统资源。
        *  void write(byte[] b): 将 b.length 个字节从指定的 byte 数组写入此输出流
        *  void write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
        * abstract  void write(int b) : 将指定的字节写入此输出流。
2、字节输出流FileOutputStream写字节 与 写字节数组
* A: 字节输出流FileOutputStream写字节
    * a: FileOutputStream
        * 写入数据文件,学习父类方法,使用子类对象
    * b: FileOutputStream构造方法
        * 作用:绑定输出的输出目的
        * FileOutputStream(File file) 
            * 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
        * FileOutputStream(File file, boolean append) 
            * 创建一个向指定 File 对象表示的文件中写入数据的文件输出流,以追加的方式写入。
        * FileOutputStream(String name) 
            * 创建一个向具有指定名称的文件中写入数据的输出文件流。
        * FileOutputStream(String name, boolean append) 
            * 创建一个向具有指定 name 的文件中写入数据的输出文件流,以追加的方式写入。
    * c: 流对象使用步骤
        *  1. 创建流子类的对象,绑定数据目的
        *  2. 调用流对象的方法write写
        *  3. close释放资源
    * d: 注意事项
        * 流对象的构造方法,可以创建文件,如果文件存在,直接覆盖
* B: 字节输出流FileOutputStream写字节数组
    * a: 方法介绍
        *  void write(byte[] b): 将 b.length 个字节从指定的 byte 数组写入此输出流
        *  void write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。

例:写字节

    @Test
    public void testFileOutputStream() throws IOException{
        FileOutputStream fos = new FileOutputStream("j:\\test1.txt");
        //流对象的方法write写数据
        //写1个字节
        fos.write(98);
        fos.close();
    }

例:写字节数组

    @Test
    public void testFileOutputStreamBtyes() throws IOException{
        FileOutputStream fos = new FileOutputStream("j:\\test.txt");
        //流对象的方法write写数据
        //写字节数组
        byte[] bytes = {65,66,67,68};
        fos.write(bytes);

        //写字节数组的一部分,开始索引,写几个
        fos.write(bytes, 1, 2);

        //写入字节数组的简便方式
        //写字符串
        fos.write("hello".getBytes());
        fos.close();
    } 

3、文件的续写和换行符号
    * a: 文件的续写
        *  FileOutputStream构造方法, 的第二个参数中,加入true
    * b: 换行符号
        * 在文件中,写入换行,符号换行  \r\n
        * \r\n 可以写在上一行的末尾, 也可以写在下一行的开头
        * linux中为 \n

例:

    @Test
    public void testXuxie() throws IOException{
        File file = new File("j:\\test.txt");
        FileOutputStream fos = new FileOutputStream(file, true);
        fos.write("nihao\r\n".getBytes());
        fos.write("yanshuang".getBytes());
        fos.close();
    }

4、字节输入流InputStream
* a: 方法介绍
        * abstract  int read() :
            * 从输入流中读取数据的下一个字节。
        * int read(byte[] b)  
            * 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
        * int read(byte[] b, int off, int len) 
            * 将输入流中最多 len 个数据字节读入 byte 数组。
        * void close() 
            * 关闭此输入流并释放与该流关联的所有系统资源。
*     java.io.InputStream 所有字节输入流的超类
5、字节输入流FileInputStream读取字节 与 字节数组
* A: 字节输入流FileInputStream读取字节
    * a: 方法介绍
        * abstract  int read() :
            * read()执行一次,就会自动读取下一个字节
            * 返回值,返回的是读取到的字节, 读取到结尾返回-1
        * int read(byte[] b)  
            * 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
            * 读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1。
        * int read(byte[] b, int off, int len) 
            * 将输入流中最多 len 个数据字节读入 byte 数组。
        * void close() 
            * 关闭此输入流并释放与该流关联的所有系统资源。
* B: 字节输入流FileInputStream读取字节数组
    * a: 方法介绍
        * int read(byte[] b)  
            * 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
            * 读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1。
        * int read(byte[] b, int off, int len) 
            * 将输入流中最多 len 个数据字节读入 byte 数组。

例:读字节

    @Test
    public void testFileInputStream() throws IOException{
        FileInputStream fis = new FileInputStream("j:\\test1.txt");
        //读取一个字节,调用方法read 返回int
        int len = 0;//接受read方法的返回值
        while((len = fis.read()) != -1) {
            System.out.print((char)len);
        }
        fis.close();
    }

例:读字节数组

    @Test
    public void testFileInputStreambytes() throws IOException{
        FileInputStream fis = new FileInputStream("j:\\test.txt");
        // 创建字节数组
        byte[] b = new byte[2];
        int len = fis.read(b);
        System.out.println(new String(b));  //ab
        System.out.println(len);            //2
        len = fis.read(b);
        System.out.println(new String(b));  //cd
        System.out.println(len);            //2
        len = fis.read(b);  
        System.out.println(new String(b));  //ed
        System.out.println(len);            //1
        len = fis.read(b);  
        System.out.println(new String(b));  //ed
        System.out.println(len);            //-1
        fis.close();
    }

以上代码充分说明:字节数组b时一个缓存区。


读取文件:

    @Test
    public void testFileInputStreambytes() throws IOException{
        FileInputStream fis = new FileInputStream("j:\\test1.txt");
        // 创建字节数组
        byte[] b = new byte[1024];
        int len = 0;
        while((len = fis.read(b)) != -1){
            System.out.print(new String(b));
        }
        fis.close();
    }

6、文件复制
    @Test
    public void fileCopy(){
        long s = System.currentTimeMillis();
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            // 建立两个流的对象,绑定数据源和数据目的
            fis = new FileInputStream("j:\\1.zip");
            fos = new FileOutputStream("h:\\1.zip");
            // 定义字节数组,缓冲
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, len);
            }
        } catch (IOException e) {
            throw new RuntimeException("文件复制失败");
        }finally {
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    throw new RuntimeException("释放资源失败");
                }finally {
                    try {
                        fos.close();
                    } catch (IOException e) {
                        throw new RuntimeException("释放资源失败");
                    }
                }
            }
            long e = System.currentTimeMillis();
            System.out.println(e-s);
        }
    }

7、编码表
* 分类
        * 1、ascii: 一个字节中的7位就可以表示。对应的字节都是正数。0-xxxxxxx
        * 2、iso-8859-1:拉丁码表 latin,用了一个字节用的8位。1-xxxxxxx  负数。
        * 3、GB2312:简体中文码表。包含6000-7000中文和符号。用两个字节表示。两个字节第一个字节是负数,第二个字节可能是正数
            * GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,其中的一部分文字,第一个字节开头是1,第二字节开头是0
            * GB18030:最新的中文码表,目前还没有正式使用。
        * 4、unicode:国际标准码表:无论是什么文字,都用两个字节存储。
            * Java中的char类型用的就是这个码表。char c = 'a';占两个字节。
            * Java中的字符串是按照系统默认码表来解析的。简体中文版 字符串默认的码表是GBK。
        * 5、UTF-8:基于unicode,一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息(后期到api中查找)。
        * 6、能识别中文的码表:GBK、UTF-8;正因为识别中文码表不唯一,涉及到了编码解码问题。
            * 对于我们开发而言;常见的编码 GBK  UTF-8  ISO-8859-1
            * 文字--->(数字) :编码。 “abc”.getBytes()  byte[]
            * (数字)--->文字  : 解码。 byte[] b={97,98,99}  new String(b) 

_04字符输出流与字符输出流

字符输出流:
- * java.io.Writer* 所有字符输出流的超类
- 写文件,写文本文件
- 字符输出流写数据时,必须要运行一个刷新功能,flush()


1、字符输出流写文本FileWriter类
* a: 方法介绍
        *  void write(int c)
            *  写入单个字符
        * void write(String str)  
            * 写入字符串
        * void write(String str, int off, int len) 
            * 写入字符串的某一部分
        * void write(char[] cbuf)  
            * 写入字符数组
        * abstract  void write(char[] cbuf, int off, int len)  
            *  写入字符数组的某一部分

例:

    @Test
    public void testFileWriter1() throws IOException{
        FileWriter fw = new FileWriter("j:\\1.txt");
        //写1个字符
        fw.write(100);
        fw.flush();
        //写一个字符数组
        char[] c = {'a','b','c','d','e'};
        fw.write(c);
        fw.flush();
        //写字符数组的一部分
        fw.write(c, 0, 2);
        fw.flush();
        //写字符串
        fw.write("hello");
        fw.flush();
        fw.close();
    }

2、字符输入流读取文本FileReader类
* a: 方法介绍
        *  int read() 
            * 读取单个字符
        * int read(char[] cbuf) 
            * 将字符读入数组
        * abstract  int read(char[] cbuf, int off, int len)  
            * 将字符读入数组的某一部分。

例:

    @Test 
    public void testFileReader() throws IOException{
        FileReader fr = new FileReader("j:\\test1.txt");
        char[] ch = new char[1024];
        int len = 0;
        while((len = fr.read(ch)) != -1){
            System.out.println(new String(ch));
        }
        fr.close();
    }

3、flush()方法和close()方法区别
    *a: flush()方法
        * 用来刷新缓冲区的,刷新后可以再次写出,只有字符流才需要刷新
    *b: close()方法
        * 用来关闭流释放资源的的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出 

4、字符流复制文本文件
@Test
    public void copyTxtFile(){
        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader("j:\\test1.txt");
            fw = new FileWriter("j:\\test1_1.txt");
            char[] ch = new char[1024];
            int len = 0;
            while ((len = fr.read(ch)) != -1) {
                fw.write(ch, 0, len);
                fw.flush();
            }
        } catch (IOException e) {
            throw new RuntimeException("复制文本文件失败");
        }finally{
            if(fw != null){
                try {
                    fw.close();
                } catch (IOException ex) {
                    throw new RuntimeException("释放资源失败");
                } finally {
                    try{
                        fr.close();
                    }catch (IOException e) {
                        throw new RuntimeException("释放资源失败");
                    }
                }
            }
        }
    }

_05转换流

1、字符转字节的过程
* OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节
* 将字符串按照指定的编码表转成字节,在使用字节流将这些字节写出去

即:OutputStreamWriter >> OutputStream >> 文件
* OutputStreamWriter
* java.io.OutputStreamWriter 继承Writer类
* 就是一个字符输出流,写文本文件
* write()字符,字符数组,字符串
* 字符通向字节的桥梁,将字符流转字节流
* OutputStreamWriter 使用方式
* 构造方法:
* OutputStreamWriter(OuputStream out)接收所有的字节输出流
* 字节输出流: FileOutputStream
* OutputStreamWriter(OutputStream out, String charsetName)
* String charsetName 传递编码表名字 GBK UTF-8
* OutputStreamWriter 有个子类, FileWriter

例:

    @Test 
    public void testWrite() throws IOException{
        //创建字节输出流,绑定文件
        FileOutputStream fos = new FileOutputStream("j:\\utf.txt");
        //创建转换流对象,构造方法保证字节输出流,并指定编码表是UTF-8
        OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
        osw.write("你好");
        osw.close();

        osw = new OutputStreamWriter(new FileOutputStream("j:\\gbk.txt"),"gbk");
        osw.write("你好");
        osw.close();
    }

注:默认编码与工作空间的编码一致。


2、字节转字符流过程
*  InputStreamReader            
    * java.io.InputStreamReader 继承 Reader
    * 字符输入流,读取文本文件
    * 将字节流转字符流
    * 读取的方法:
        * read() 读取1个字符,读取字符数组
    * 技巧
        * OuputStreamWriter写了文件
        * InputStreamReader读取文件
    * OutputStreamWriter(OutputStream out)所有字节输出流
    * InputStreamReader(InputStream in) 接收所有的字节输入流
    * 可以传递的字节输入流: FileInputStream
    * InputStreamReader(InputStream in,String charsetName) 传递编码表的名字

例:

    @Test
    public void testReader() throws IOException{
        //创建自己输入流,传递文本文件
        FileInputStream fis = new FileInputStream("j:\\utf.txt");
        //创建转换流对象,构造方法中,包装字节输入流,同时写编码表名
        InputStreamReader isr = new InputStreamReader(fis);
        char[] ch = new char[1024];
        int len = isr.read(ch);
        System.out.println(new String(ch,0,len));
        isr.close();

        isr = new InputStreamReader(new FileInputStream("j:\\gbk.txt"),"gbk");
        len = isr.read(ch);
        System.out.println(new String(ch,0,len));
        isr.close();
    }

3、转换流子类父类的区别
* A: 转换流子类父类的区别
    * a: 继承关系
        OutputStreamWriter:
            |--FileWriter:
        InputStreamReader:
            |--FileReader;
    * b: 区别
        * OutputStreamWriter和InputStreamReader是字符和字节的桥梁:也可以称之为字符转换流。字符转换流原理:字节流+编码表。
        * FileWriter和FileReader:作为子类,仅作为操作字符文件的便捷类存在。
            当操作的字符文件,使用的是默认编码表时可以不用父类,而直接用子类就完成操作了,简化了代码。
        * 以下三句话功能相同
            * InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));//默认字符集。
            * InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"utf-8");//指定GBK字符集。
            * FileReader fr = new FileReader("a.txt");

_05缓冲流

提高IO流的读写速度,包括字节缓冲流和字符缓冲流。

1、字节输出流缓冲流BufferedOutputStream
* a: BufferedOutputStream
    * 字节输出流的缓冲流
    * java.io.BufferedOuputStream 作用: 提高原有输出流的写入效率
    * BufferedOuputStream 继承 OutputStream
    * 方法,写入 write 字节,字节数组            
    * 构造方法:
        * BufferedOuputStream(OuputStream out)
        * 可以传递任意的字节输出流, 传递的是哪个字节流,就对哪个字节流提高效率  

例:

    @Test
    public void testBufferOutputStream() throws IOException{
        //创建字节输出流缓冲流的对象,构造方法中,传递字节输出流
        BufferedOutputStream bos = new
                BufferedOutputStream(new FileOutputStream("j:\\buffer.txt"));
        bos.write(55);

        byte[] bytes = "HelloWord哎".getBytes();
        bos.write(bytes);
        bos.write(bytes,0,5);

        bos.close();
    }

2、字节输入流缓冲流BufferedInputStream
* a: BufferedInputStream
    * 字节输入流的缓冲流
    * 继承InputStream,标准的字节输入流
    * 读取方法  read() 单个字节,字节数组              
    * 构造方法:
        * BufferedInputStream(InputStream in)
        * 可以传递任意的字节输入流,传递是谁,就提高谁的效率
        * 可以传递的字节输入流 FileInputStream

例:

    @Test 
    public void testBufferInputStream() throws IOException{
        BufferedInputStream bis = new
                BufferedInputStream(new FileInputStream("j:\\buffer.txt"));
        byte[] bytes = new byte[10];
        int len = 0;
        while((len = bis.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }
        bis.close();
    }
3、字节缓冲流文件复制
    @Test
    public void testBufferedCopy(){
        bufferedCopy("j:\\1.zip", "j:\\2.zip");
    }
    public void bufferedCopy(String src,String desc){
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(src));
            bos = new BufferedOutputStream(new FileOutputStream(desc));
            int len = 0;
            byte[] bytes = new byte[1024];
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
            }
        } catch (IOException e) {
            throw new RuntimeException();
        }finally {
            if(bis!=null){
                try{
                    bis.close();
                }catch (IOException ex){
                    throw new RuntimeException();
                }finally {
                    try{                
                        bos.close();
                    }catch(IOException ex){
                        throw new RuntimeException();
                    }
                }
            }
        }

    }

4、字符输出流缓冲流BufferedWriter
*  字符输出流缓冲流BufferedWriter

    * a: BufferedWriter

        * 字符输出流缓冲区流

        * java.io.BufferedWriter 继承 Writer

        * 写入方法 write () 单个字符,字符数组,字符串

        * 构造方法:

            * BufferedWriter(Writer w)传递任意字符输出流

            * 传递谁,就高效谁

            * 能传递的字符输出流 FileWriter, OutputStreamWriter

例:

public class BufferWriterDemo {
    public static void main(String[] args) throws IOException {
        BufferedWriter bfw = new BufferedWriter(new FileWriter("j:\\buf.txt"));
        bfw.write(100);
        bfw.flush();
        bfw.write("你好");
        bfw.flush();
        //文本中的换行,系统无关性
        bfw.newLine();
        bfw.flush();
        bfw.write("严霜".toCharArray());
        bfw.close();
    }
}

5、字符输出流缓冲流BufferedWriter
public class BufferedReaderDemo{
    public static void main(String[] args) throws IOException{
        int lineNumber = 0;
        BufferedReader bfr = new BufferedReader(new FileReader("j:\\buf.txt"));
        //调用缓冲流的方法 readLine()读取文本行
        String line = null;
        while((line = bfr.readLine()) != null){
            lineNumber++;
            System.out.println(lineNumber+" "+line);
        }
        bfr.close();
    }
}

_06 Properties集合

1、Properties集合简介:
* A: Properties集合的特点
    * a: Properties类介绍
        * Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串
    * b: 特点
        * Hashtable的子类,map集合中的方法都可以用。
        * 该集合没有泛型。键值都是字符串。
        * 它是一个可以持久化的属性集。键值可以存储到集合中,也可以存储到持久化的设备(硬盘、U盘、光盘)上。键值的来源也可以是持久化的设备。
        * 有和流技术相结合的方法。
    * c: 方法介绍
        * load(InputStream inputStream)  把指定流所对应的文件中的数据,读取出来,保存到Propertie集合中
        * load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)
        * store(OutputStream outputStream,String commonts) 把集合中的数据,保存到指定的流所对应的文件中,参数commonts代表对描述信息
        * stroe(Writer writer,String comments) 以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符

2、Properties集合存储键值对
    /*
     * 使用Properties集合,存储键值对
     * setProperty等同于Map接口中的put
     * setProperty(String key, String value)
     * 
     * 获取键值对,getProperty(String key)
     */
    @Test
    public void testProperties1(){
        Properties pro = new Properties();
        pro.setProperty("a","1");
        pro.setProperty("b", "2");
        pro.setProperty("c", "3");
        System.out.println(pro);

        String value = pro.getProperty("c");
        System.out.println(value);

        //方法stringPropertyNames,将集合中的键存储到Set集合,类似于Map接口的方法keySet
        Set<String> set = pro.stringPropertyNames();
        for (String key : set){
            System.out.println(key+"..."+pro.getProperty(key));
        }
    }
}

3、Properties集合的方法load
    /*
     * Properties 集合特有方法 load
     * load(InputStream in)
     * load(Reader r)
     * 传递任意的字节或字符流
     * 流对象兑取文件中的键值对,保存到集合中
     */
    @Test
    public void testProperties_load()throws IOException{
        Properties pro = new Properties();
        FileReader fr= new FileReader("j:\\test.properties");
        //调用集合的方法load,传递字符输入流
        pro.load(fr);
        fr.close();
        System.out.println(pro);
    }

4、Properties集合的方法store
    @Test
    public void testProperties_store()throws IOException{
        Properties pro = new Properties();
        pro.setProperty("nihao", "hello");
        pro.setProperty("email", "joelovealonge@163.com");

        FileWriter fw = new FileWriter("j:\\test.properties");
        //键值对,存回文件,使用集合的方法store传递字符输出流
        pro.store(fw, "");
        System.out.println(pro);
    }
}

_07 对象的序列化与反序列化

* A: 对象的序列化与反序列化
    * a: 基本概念
        * 对象的序列化
            * 对象中的数据,以流的形式,写入到文件中保存过程称为写出对象,对象的序列化
            * ObjectOutputStream将对象写到文件中,实现序列化
        * 对象的反序列化
            * 在文件中,以流的形式,将对象读出来,读取对象,对象的反序列化
            * ObjectInputStream 将文件对象读取出来

注:
- 静态不能序列化:

    * 原因:
        *  序列化是把对象数据进行持久化存储
        *  静态的东西不属于对象,而属于类
  • transient关键字
    * 作用:
        *   被transient修饰的属性不会被序列化
        *  transient关键字只能修饰成员变量

1、ObjectOutputStream流写对象与ObjectInputStream流读对象
    @Test
    public void testObjectStream() throws IOException, ClassNotFoundException{
        /*
         * ObjectOutputStream
         * 构造方法: ObjectOutputStream(OutputSteam out)
         * 传递任意的字节输出流
         * void writeObject(Object obj)写出对象的方法
         */
        //创建字节输出流,封装文件
        FileOutputStream fos = new FileOutputStream("j:\\person.txt");
        //创建写出对象的序列化流的对象,构造方法传递字节输出流
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        Person p = new Person("ailisi",19);
        //调用序列化流的方法writeObject,写出对象
        oos.writeObject(p);
        oos.close();

        /*
         * ObjectInputStream
         * 构造方法:ObjectInputStream(InputStream in)
         * 传递任意的字节输入流,输入流封装文件,必须是序列化的文件
         * Object readObject()  读取对象
         */
        FileInputStream fis = new FileInputStream("j:\\person.txt");
        //创建反序列化流,构造方法中,传递字节输入流
        ObjectInputStream ois = new ObjectInputStream(fis);
        //调用反序列化流的方法 readObject()读取对象
        Object obj = ois.readObject();
        System.out.println(obj);
        ois.close();
    }

给需要序列化的类上加标记。该标记中没有任何抽象方法


2、Serializable接口的含义
  • 作用:给需要序列化的类上加标记。该标记中没有任何抽象方法
    • 给需要序列化的类上加标记。该标记中没有任何抽象方法
    • 只有实现了 Serializable接口的类的对象才能被序列化
3、序列化中的序列号冲突问题
  • 问题产生原因:
    • 当一个类实现Serializable接口后,创建对象并将对象写入文件,之后更改了源代码(比如:将成员变量的修饰符有private改成public),再次从文件中读取对象时会报异常。
    • 编译器,根据类的定义,会在class文件中计算一个序列号出现
    • 新编译后的class文件中序列号,与原来的文件person.txt中的序列号不同。
3、序列化中自定义的序列号
public class Person implements Serializable{
    public String name;
    public /*transient阻止成员变量序列化*/ int age;
    //类,自定义了序列号,编译器不会计算序列号
    private static final long serialVersionUID = 1478652478456L;
    public Person(String name, int age){
        this.name=name;
        this.age = age;
    }
    public Person(){}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}

_08 打印流

1、打印流和特性
  • a: 概述
    • 打印流添加输出数据的功能,使它们能够方便地打印各种数据值表示形式.
    • 打印流根据流的分类:
      • 字节打印流 PrintStream
      • 字符打印流 PrintWriter
    • 方法:
      • void print(String str): 输出任意类型的数据,
      • void println(String str): 输出任意类型的数据,自动写入换行操作
  • b: 特点
    • 此流不负责数据源,只负责数据目的
    • 为其他输出流,添加功能
    • 永远不会抛出IOException,但是可能抛出别的异常
    • 两个打印流的方法,完全一致
    • 构造方法,就是打印流的输出目的端
    • PrintStream构造方法
      • 接收File类型,接收字符串文件名,接收字节输出流OutputStream
    • PrintWriter构造方法
      • 接收File类型,接收字符串文件名,接收字节输出流OutputStream, 接收字符输出流Writer
2、打印流输出目的是File对象
    @Test
    public void testPrintWriter() throws FileNotFoundException{
        /*
         * 打印流,向File对象的数据目的写入数据
         * 方法print println  原样输出
         * write方法走码表
         */
        File file = new File("j:\\file.txt");
        PrintWriter pw = new PrintWriter(file);
        pw.println(true);
        pw.write(100);
        pw.close();
    }
3、输出语句是char数组
    @Test
    public void testPrintWriterDemo(){
        int[] arr={1};
        System.out.println(arr);
        char[] ch = {'a','b','c'};
        System.out.println(ch);
        byte[] b = {};
        System.out.println(b);
    }
  • 结果分析
    • println数组,只有打印字符数组时只有容,其余均打印数组的地址
    • 因为api中定义了打印字符数组的方法,其底层是在遍历数组中的元素
    • 而其他打印数组的方法,都是将数组对象编程Object,其底层再将对象编成String,调用了String s = String.valueOf(x);方法

4、打印流开启自动刷新
    @Test
    public void testPrint() throws FileNotFoundException{
        /*
         * 打印流,可以开启自动刷新功能
         * 满足2个条件:
         *  1. 输出的数据目的必须是流对象
         *      OutputStream  Writer
         *  2. 必须调用println,printf,format三个方法中的一个,启用自动刷新
         */
        FileOutputStream fos = new FileOutputStream("j:\\6.txt");
        PrintWriter pw = new PrintWriter(fos,true);
        pw.println("I");
        pw.println("love");
        pw.println("you");
        pw.close();
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值