JAVA高级特性——流

一、概念

1、概念:是一组有序的数据序列(字节数组)
在这里插入图片描述

二、分类

(1)按方向分类

1、输入流

硬盘中的数据读取到内存中。
(1)XxxInputStream
(2)XxxReader

2、输出流

内存里的数据保存到硬盘中。
(1)XxxOutputStream
(2)XxxWriter

(2)按内容分类

1、字节流

  • 一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一 样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底 层传输的始终为二进制数据。
    (1)XxxInputStream
    (2)XxxOutputStream

2、字符流

  • 当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为 一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文 件。
    (1)XxxReader
    (2)XxxWriter

(3)按功能分类

1、节点流

  • 直接面向数据源的流(基础流)

2、处理流

  • 扩展了节点流在某些特性领域的操作

(4)是否依赖网络

1、本地流(文件流)

2、网络流

三、文件流

(1)目录

public class Test {
    public static void main(String[] args) {
        //-----------------目录
        File dir = new File("C:/Users/Administrator/Desktop/中博学习/java");  //创建目录对象
        boolean exists = dir.exists();   //判断目录是否存在
        System.out.println(exists);
        boolean isDir = dir.isDirectory();  //判断是否为目录
        System.out.println(isDir);
        boolean isFile = dir.isFile(); //判断是否为文件
        System.out.println(isFile);

	File dir = new File("copy/unload");
        boolean mkdir = dir.mkdirs(); //创建所有不存在的的目录
        System.out.println(mkdir)
	
	//相对路径:项目的根路径
	//绝对路径:从分区根目录开始的路径
     }
}  

(2)文件

public class Test {
    public static void main(String[] args) {
	 //-----------------文件
        File file = new File("C:/Users/Administrator/Desktop/中博学习/java/story.txt");  //创建文件对象
        //判断文件是否存在
        System.out.println(file.exists());
        //判断是否为目录
        System.out.println(file.isDirectory());
        //判断是否为文件
        System.out.println(file.isFile());
        //获取父目录对象
        System.out.println(file.getParentFile());
        //获取父目录字符串
        System.out.println(file.getParent());
        //获取文件所在路径
        System.out.println(file.getPath());
        //获取文件名称
        System.out.println(file.getName());
        //获取文件实际的字节数
        System.out.println(file.length());
        //获取文件可存剩余字节数
        System.out.println(file.getFreeSpace());

	//创建一个文件,如果该工程的所有目录下没有该文件
        File file = new File("test.txt");
        if(!file.exists()){
            if(file.createNewFile()){
                System.out.println(file.getName()+"文件创建成功!");
                System.out.println(file.getPath());
                System.out.println(file.getAbsolutePath());
            }else{
                System.out.println(file.getName()+"文件创建失败")
            }
        }else{
            System.out.println(file.getName()+"文件已存在");
        }

    }
}

(3)文件流

1)字节文件流

1、字节输入流:

/*
java.io.InputStream:字节输入流	
	此抽象类是表示字节输入流的所有类的超类

定义了所有子类共性的方法:
   	int read() 从输入流中读取数据的下一个字节
    	int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中
   	void close() 关闭此输入流并释放与该流关联的所有系统资源

java.io.FileInputStream extends InputStream
	FileInputStream:文件字节输入流
	作用:把硬文件中的数据,读取到内存中使用

构造方法:
   	FileInputStream(String name)
   	FileInputStream(File file)
    	参数:读取文件的数据源
        	String name:文件的路径
       		File file: 文件
构造方法的作用:
        1、会创建一个FileInputStream对象
        2、会把FileInputStream对象指定构造方法中要读取的文件

读取数据的原理:(硬盘---->内存)
        java程序-->JVM-->OS-->OS读取数据的方法-->读取文件

字节输入流的使用步骤(重点):
    	1、创建FileInputStream对象,构造方法中绑定要读取的数据源
    	2、使用FileInputStream对象中的方法read,读取文件
    	3、释放资源
 */
 
public class Dmeo01InputStream {
    public static void main(String[] args) throws IOException {
        //1、创建FileInputStream对象,构造方法中绑定要读取的数据源
        FileInputStream fis = new FileInputStream("files/a.txt");
        //2、使用FileInputStream对象中的方法read,读取文件
        
        //共性方法一:int read() 从输入流中读取数据的一个字节并返回,读取到文件的末尾返回-1
        int len = fis.read();
        System.out.println(len);
        
        len = fis.read();
        System.out.println(len);
        len = fis.read();
        System.out.println(len);
        len = fis.read();
        System.out.println(len);
        len = fis.read();
        System.out.println(len);

        /*
        发现以上读取文件是一个重复的过程,使用循环优化
        不知道文件有多少字节,使用while循环
        循环结束条件:读取到-1的时候结束

        布尔表达式:-1!=(len=fis.read())
            1、fis.read():读取一个字节
            2、len = fis.read():把读取到的字节赋值给变量len
            3、-1!=(len=fis.read());判断变量len是否不等于-1
         
        int len =0;//记录读取到的字节
        while(-1!=(len=fis.read())){
            System.out.println(len);
        }
        */

	//共性方法二:int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中
	byte[] bytes = new byte[1024];
	int len = 0;
	while(-1!=(len=fis.read(bytes))){
    		System.out.println(new String(bytes,0,5));
	}
        
        // 3、释放资源
        fis.close();
    }
}

在这里插入图片描述
2、字节输出流:

  • 文件存储原理:
    在这里插入图片描述
  • 一次写入一个字节的方法写入:
/*
    java.io.OutputStream:字节输出流
         此抽象类是表示输出字节流的所有类的超类

    定义了一些子类共性的成员方法
         public void close();    关闭此输出流并释放与此流相关联的任何系统资源
         public void flush();    刷新此输出流并强制任何缓冲的输出字节被写出
         public void write(byte[] b);   将b.length字节从指定的字节数组写入此输出流
         public void write(byte[] b,int off, int len);   从指定的字节数组写入len字节,从偏移量off开始输出到此输出流
         public abstract void write(int b);  将指定的字节输出流

    java.io.FileOutputStram extends  OutputStream
    FileOutputStream:文件字符输出流
   	 作用:把内存中的数据写到硬盘的文件中

    构造方法:
         FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流
         FileOutputStream(File file)  创建一个向指定File对象表示的文件中写入数据的文件输出流
         参数:写入数据的目的:
             String name: 目的地是一个文件的路径
             File file : 目的地是一个文件
         构造方法的作用:
             1、创建一FileOutputStream对象
             2、会根据构造方法中传递的文件/文件路径,创建一个空文件
             3、会把FileOutputStream对象指向创建好的文件

        写入数据的原理(内存-》硬盘):
            java程序-->JVM虚拟机-->OS(操作系统)-->OS调入写数据的方法-->把数据写入到文件中

        字节输出流的使用步骤(重点)
            1、创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
            2、调用FileOutputStream对象中的方法write,把数据写到文件中
            3、释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提高程序效率)
 */
 
public class Demo01OutputStream {
    public static void main(String[] args) throws IOException {
        //1、创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
        FileOutputStream fos = new FileOutputStream("files/a.txt");
        // 2、调用FileOutputStream对象中的方法write,把数据写到文件中
        fos.write(97);
        // 3、释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提高程序效率)
        fos.close();
    }
}
  • 一次写入多个字节的方法写入:
/*
一次写多个字节的方法
         public void write(byte[] b);   将b.length字节从指定的字节数组写入此输出流
         public void write(byte[] b,int off, int len);   从指定的字节数组写入len字节,从偏移量off开始输出到此输出流
 */
public class Demo02OutputStream {
    public static void main(String[] args) throws IOException {
        // 1、创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
        FileOutputStream fos = new FileOutputStream(new File("files/b.txt"));
        //2、调用FileOutputStream对象中的方法write,把数据写到文件中
        //在文件中显示100,写几个字节?
        fos.write(49);
        fos.write(48);
        fos.write(48);

         /*
        public void write(byte[] b);   将b.length字节从指定的字节数组写入此输出流
        一次写多个字节:
            如果写的第一个字节是正数(0~127),显示的时候会查询ASCII码表
            如果写的第一个字节是负数,那么第一二个字节会组成一个中文显示,查询GBK
         */
         byte[] bytes = {65,66,67,68,69};  //ABCDE
         //byte[] bytes = {-65,-66,-67,68,69}; //烤紻E
         fos.write(bytes);

         /*
          public void write(byte[] b,int off, int len);
          从指定的字节数组写入len字节,从偏移量off开始输出到此输出流
          */
         fos.write(bytes,1,2); //BC

        /*
        写入字符串的方法:可以使用String类中的方法把字符串转化为字节数组
            byte[] getBytes()     把字符串转化为字符数组
         */
        byte[] bytes2 = "你好".getBytes();
        System.out.println(Arrays.toString(bytes2));  //[-28, -67, -96, -27, -91, -67]
        fos.write(bytes2);


        // 3、释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提高程序效率)
        fos.close();
        
    }
}
  • 追加写/续写
/*
追加写/续写:使用两个参数的构造方法
    FileOutputStream(String name,boolean append) 创建一个向具有指定name的文件中写入数据的输出文件流
    FileOutputStream(File file,boolean append) 创建一个向指定file对象表示的文件中写入数据的文件输出流
    参数:
        String name,File file:写入数据的目的地
        boolean append: 追加写开关
        true:创建对象不会覆盖源文件,继续在文件末尾追加写数据
        false:创建一个新文件,覆盖源文件
    写换行:写换行符
        windon:\r\n
        linux;\n
        mac:\r
 */
public class Demo03OutputStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("files/c.txt",true);
        for (int i = 0; i < 10; i++) {
            fos.write("你好".getBytes());
            fos.write("\r\n".getBytes());
        }
        fos.close();
    }
}
  • 文件复制的原理:
    在这里插入图片描述

2)字符文件流

1、字符输入流:

/*
java.io.Reader:字符输入流:是字符输入流的最顶层的父类,定义了一些共性的成员方法,是一个抽象类

共性的成员方法:
    int read():读取单个字符并返回
    int read(char[] char):一次读取多个字符,将字符读入数组
    void close():关闭该流并释放与之关联的所有资源

java.io.FileReader extends InputStreamReader extends Reader
FileReader:文件字符输出流:
    作用:把硬盘文件中的数据以字符的方式读取到内存中
    构造方法:
        FileReader(String fileName):
        FileReader(File file):
        参数:读取文件的数据源
            String FileName:文件的路径
            File file: 一个文件
        FileReader构造方法的作用:
            1、创建一个FileReader对象
            2、将FileReader对象指向要读取的文件
     字符输入流使用步骤:
        1、创建FileReader对象, 构造方法中绑定压要读取的数据源
        2、使用FileReader对象中的read方法读取文件
        3、释放资源
 */
public class Demo01Reader {
    public static void main(String[] args) throws IOException {
        //1、创建FileReader对象, 构造方法中绑定压要读取的数据源
        FileReader fr = new FileReader("files/c.txt");
        //2、使用FileReader对象中的read方法读取文件
       
        //共性方法一:int read():读取单个字符并返回
        int len=0;
        while(-1!=(len=fr.read())){
            System.out.print((char)len);
        }

        //共性方法二:int read(char[] char):一次读取多个字符,将字符读入数组
        char[] chars =new char[1024];
        int len=0;
        while(-1!=(len=fr.read(chars))){
            /*
            String类的构造方法
            String(char[] value):字符数组转化为字符串
            String(char[] value,int offset,int count):把字符数组的一部分转化为字符串,offset:数组的开始索引,count:转换的个数
             */
            System.out.println(new String(chars,0,len));
        }
        //3、释放资源
        fr.close();
        
    }
}

2、字符输出流:

  • 一次写入单个字符
/*
java.io.Writer:字符输出流:所有字符输出流的最顶层的父类,是一个抽象类

共性的成员属性:
    void write(int c): 写入单个字符
    void write(char[] chars):写入字符数组
    abstract void write(char[] cahrs,int offset, int len):写入字符数组的一部分
    void write(String str):写入字符串
    void writechar[] cahrs,int offset, int len):写入字符数组的一部分
    void flush():刷新该流的缓冲
    void close():关闭此流,先刷新它

java.io.FileWriter extends OutputStreamWriter extends Writer

FileWriter:文件字符输出流

作用:把内存中的字符数据写入到文件中

构造方法:
    FileWriter(File file):根据给定的File对象构造一个FileWriter对象
    FileWriter(String FileName):根据给定的文件名构造一个FileWriter对象
    参数:写入数据的目的地
         fileName:文件的路径
         File file:一个文件
 构造方法的作用:
        1、会创建一个FileWriter对象
        2、会根据构造方法中传递的文件或者文件的路径,创建文件
        3、会把FileWriter对象指向创建好的文件
 使用步骤:
    1、创建一个FileWriter对象,构造方法中写入数据的目的地
    2、使用FileWriter中的write方法,把数据写到内存缓冲区中,字符转化为字节的过程
    3、使用FileWriter中的flush方法,将内存缓冲区的数据,刷新到文件中
    4、释放资源(会把内存缓冲区中的数据刷新到文件中)
 */
 
public class Demo01Writer {
    public static void main(String[] args) throws IOException {
        //1、创建一个FileWriter对象,构造方法中写入数据的目的地
        FileWriter fw = new FileWriter("files/d.txt");
        //2、使用FileWriter中的write方法,把数据写到内存缓冲区中,字符转化为字节的过程
        //void write(int c): 写入单个字符
        fw.write(97);
        //3、使用FileWriter中的flush方法,将内存缓冲区的数据,刷新到文件中
        fw.flush();
        //4、释放资源(会把内存缓冲区中的数据刷新到文件中)
        fw.close();
    }
}
  • 字符输出流其他写入方式
/*
字符输出流写入数据的其他方法:
    void write(char[] chars):写入字符数组
    void write(char[] cahrs,int offset, int len):写入字符数组的一部分
    void write(String str):写入字符串
    void write(String str,int offset, int len):写入字符串的一部分
 */
 
public class Demo02Writer {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("files/f.txt");
        //void write(char[] chars):写入字符数组
        char[] cs = {'a','b','c','d','e'};
        fw.write(cs);//abcde

        //void write(char[] cahrs,int offset, int len):写入字符数组的一部分
        fw.write(cs,1,3);

        //void write(String str):写入字符串
        fw.write("课工场");//课工场

        //void write(String str,int offset, int len):写入字符串的一部分
        fw.write("我爱你中国",3,2);//中国

        fw.close();
    }
}

  • 追加写/续写
/*
续写与换行:
    续写,追加写:使用两个参数的构造方法
        FileWriter(String fileName,boolean append)
        FileWriter(File file,boolean append)
        参数:
            String fileName,File file:写入数据的目的地
            boolean append:续写开关  true:不会创建新的文件覆盖源文件,可以续写  false:会创建新的文件覆盖源文件
     换行:换行符号
            windows:\r\n
            linux:\n
            mac:\n
 */
public class Demo03Writer {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("files/g.txt",true);
        for (int i = 0; i <10 ; i++) {
            fw.write("HelloWorld"+i+"\r\n");
        }
        fw.close();
    }
}
  • flushclose方法的区别
/*
flush和close方法的区别
    flush:刷新缓冲区,流对象可以继续使用
    close:先刷新缓冲区,然后告知系统释放资源,流对象不可以再被使用
 */
 
public class Demo02FlushAndClose {
    public static void main(String[] args) throws IOException {
        //1、创建一个FileWriter对象,构造方法中写入数据的目的地
        FileWriter fw = new FileWriter("files/e.txt");
        //2、使用FileWriter中的write方法,把数据写到内存缓冲区中,字符转化为字节的过程
        //void write(int c): 写入单个字符
        fw.write(97);
        //3、使用FileWriter中的flush方法,将内存缓冲区的数据,刷新到文件中
        fw.flush();
        //刷新之后,流可以继续使用
        fw.write(98);
        //4、释放资源(会把内存缓冲区中的数据刷新到文件中)
        fw.close();
        //close方法之后流已经关闭,从内存中消失了,流就不能再使用了
        //fw.write(99);//报异常:java.io.IOException: Stream closed
    }
}

3)缓冲流

  • 缓冲流的原理
    在这里插入图片描述
  • 字节缓冲输入流:
/*
java.io.BufferedInputStream  extends InputStream
    BufferedInputStream: 字节缓冲输入流:

    继承自父类的成员方法:
        int read() 从输入流中读取数据的下一个字节
        int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中
        void close() 关闭此输入流并释放与该流关联的所有系统资源

    构造方法:
        BufferedInputStream(InputStream in):创建一个BufferedInputStream并保存其参数,即输入流in,以便将来使用
        BufferedInputStream(InputStream in,int size):创建具有缓冲区大小的BufferedInputStream并保存其参数,即输入流in,以便将来使用
        参数:
            InputStream in:字节输入流
                我们可以传递FileInputStream,缓冲流会给FileInputStream增加一个缓冲区,提高FileInputStream读取效率
            int size:指定缓冲流内部缓冲区的大小,不指定就默认的大小
    使用步骤:(重点)
        1、创建FileInputStream对象,构造方法中绑定要读取的数据源
        2、创建BufferedInputStream对象,构造方法中传递FileInputStream对象,提高FileInputStream对象的读取效率
        3、使用BufferedInputStream对象的read方法,读取文件
        4、释放资源
 */
 
public class Demo02BufferedInputStream {
    public static void main(String[] args) throws IOException {
        // 1、创建FileInputStream对象,构造方法中绑定要读取的数据源
        FileInputStream fis = new FileInputStream("files/a.txt");
        //  2、创建BufferedInputStream对象,构造方法中传递FileInputStream对象,提高FileInputStream对象的读取效率
        BufferedInputStream bis = new BufferedInputStream(fis);
        //3、使用BufferedInputStream对象的read方法,读取文件

        // int read() 从输入流中读取数据的下一个字节
//        int len = 0;
//        while(-1!=(len=bis.read())){
//            System.out.println(len);
//        }

        //int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中
        byte[] bytes = new byte[1024];//存储每次读取的数据
        int len = 0;//记录每次读取的有效字节个数
        while(-1!=(len=bis.read(bytes))){
            System.out.println(new String(bytes,0,len));
        }

        //4、释放资源
        bis.close();
    }
}
  • 字节缓冲输出流
/*
java.io.BiufferedOutputStream :字节缓冲输出流  (extends OutputStream)

继承自父类的共性成员方法:
    public void close();    关闭此输出流并释放与此流相关联的任何系统资源
    public void flush();    刷新此输出流并强制任何缓冲的输出字节被写出
    public void write(byte[] b);   将b.length字节从指定的字节数组写入此输出流
    public void write(byte[] b,int off, int len);   从指定的字节数组写入len字节,从偏移量off开始输出到此输出流
    public abstract void write(int b);  将指定的字节输出流

构造方法:
    BufferedOutputStream(OutputStream out):创建一个新的缓冲输出流,将数据写入指定的底层输出流
    BufferedOutputStream(OutputStream out,int size):创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流
    参数:
        OutputStream out:字节输出流
            我们可以传递FileOutputStream,缓冲流会给FileOutputStream增加一个缓冲区,提高FileOutputStream的写入效率
        int size:指定缓冲流内部缓冲区的大小,不指定就默认的大小

使用步骤:(重点)
    1、创建FileOutputStream对象,构造方法中绑定要输出的目的地
    2、创建BufferedFileOutputStream对象,构造方法中传递FileOutputStream的对象,提高FileOutputStream对象效率
    3、使用BufferedFileOutputStream对象中write方法,将数据写入到内部的缓冲区当中
    4、使用BufferedFileOutputStream对象中flush方法,把内部缓冲区的数据,刷新到文件中
    5、释放资源(会先调用flush方法刷新数据,第四步骤给以省略)
 */
 
public class Demo01BufferedOutputStream {
    public static void main(String[] args) throws IOException {
        // 1、创建FileOutputStream对象,构造方法中绑定要输出的目的地
        FileOutputStream fos = new FileOutputStream("files/a.txt");
        // 2、创建BufferedFileOutputStream对象,构造方法中传递FileOutputStream的对象,提高FileOutputStream对象效率
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        // 3、使用BufferedFileOutputStream对象中write方法,将数据写入到内部的缓冲区当中
        bos.write("我把数据写到内部缓冲区中".getBytes());
        // 4、使用BufferedFileOutputStream对象中flush方法,把内部缓冲区的数据,刷新到文件中
        bos.flush();
        // 5、释放资源(会先调用flush方法刷新数据,第四步骤可以省略)
        bos.close();
    }
}
  • 文件复制练习:
/*
文件复制练习:

    明确:
        数据源:files/g.txt
        数据的目的地:files/f.txt

    文件复制的步骤:
        1、创建字节缓冲输入流对象,构造方法中绑定要读取的数据源
        2、创建字节缓冲输出流对象,构造方法中绑定要写入的目的地
        3、使用字节缓冲输入流对象中的read方法读取文件
        4、使用字节缓冲输出流的write方法,把要读取的数据写入到内存缓冲区中
        5、释放资源(先把缓冲区的数据刷新到文件中)
 */
 
public class Demo01CopyFile {
    public static void main(String[] args) throws IOException {
        long begin = System.currentTimeMillis();
        // 1、创建字节缓冲输入流对象,构造方法中绑定要读取的数据源
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("files/g.txt"));
        // 2、创建字节缓冲输出流对象,构造方法中绑定要写入的目的地
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("files/f.txt"));
        // 3、使用字节缓冲输入流对象中的read方法读取文件
        //一次读取一个字节写入一个字节的方式
//        int len = 0;
//        while(-1!=(len=bis.read())){
//            bos.write(len);
//        }

        //一次读取多个字节写入多个字节的方式
        byte[] bytes = new byte[1024];
        int len=0;
        while(-1!=(len=bis.read(bytes))){
            bos.write(bytes,0,len);
        }

        bos.close();
        bis.close();
        long end = System.currentTimeMillis();
        System.out.println("复制文件耗时:"+(end-begin)+"毫秒");

    }
}
  • 字符缓冲输入流:
/*
java.io.BufferedReader extends Reader

继承自父类的共性的成员方法:
    int read():读取单个字符并返回
    int read(char[] char):一次读取多个字符,将字符读入数组
    void close():关闭该流并释放与之关联的所有资源

构造方法:
    BufferedReader(Reader in):创建一个使用默认大小输入缓冲区的缓冲字符输入流
    BufferedReader(Reader in,int size):创建一个指定大小输入缓冲区的缓冲字符输入流
    参数:
       Reader in :字符输入流
       	   我们可以传递FileWriter,缓冲流会给FileReader增加一个缓冲区,提高效率

特有的成员方法:
    String readline():读取一个文本行,读取一行数据
        行的终止符号:通过下列字符之一即可认为某行已终止:换行('\n')、回车('\r')或者或回车后直接换行(\r\n)
    返回值:包含该行内容的字符串,不包含任何终止符,如果以达到流末尾,则返回null

使用步骤:
    1、创建字符缓冲输入流对象,构造方法中传递字符输入流
    2、调用字符输入流对象的read/readline方法,读取文本
    3、释放资源

 */
public class Demo04BufferedReader {
    public static void main(String[] args) throws IOException {
        // 1、创建字符缓冲输入流对象,构造方法中传递字符输入流
        BufferedReader br = new BufferedReader(new FileReader("files/c.txt"));
        //2、调用字符输入流对象的read/readline方法,读取文本
//        String line = br.readLine();
//        System.out.println(line);
//
//        line = br.readLine();
//        System.out.println(line);
//
//        line = br.readLine();
//        System.out.println(line);
//
//        line = br.readLine();
//        System.out.println(line);

        /*
        循环优化,不知道文件中有多少行数据,所以使用while循环
        while的结束条件:读取到null结束
         */
        String line;
        while(null!=(line=br.readLine())){
            System.out.println(line);
        }
        //3、释放资源
        br.close();
        
    }
}

  • 字符缓冲输出流:
/*
java.io.BufferedWriter extends Writer

BufferedWriter:字符缓冲输出流

继承自父类共性的成员方法:
    void write(int c): 写入单个字符
    void write(char[] chars):写入字符数组
    abstract void write(char[] cahrs,int offset, int len):写入字符数组的一部分
    void write(String str):写入字符串
    void writechar[] cahrs,int offset, int len):写入字符数组的一部分
    void flush():刷新该流的缓冲
    void close():关闭此流,先刷新它

构造方法:
    BufferedWriter(writer out):创建一个使用默认大小输出缓冲区的缓冲字符输出流
    BufferedWriter(writer out,int size):创建一个使用给定大小输出缓冲区的新缓冲字符输出流
    参数:
        writer out:字符输出流
            我们可以传递FileWriter.缓冲流会给FileWriter增加一个缓冲区,提高xiaolv
        int size:指定缓冲区的大小,不写默认大小

 特有的成员方法:
        void newline():写入一个行分隔符。会根据不同的操作系统,获取不同的行分隔符
        
使用步骤:
        1、创建字节缓冲输出流对象,构造方法中传递字符输出流
        2、调用字节缓冲输出流中的writer方法,把数据写入到内存缓冲区中
        3、调用字节缓冲输出流中的flush方法,把内存缓冲区中的数据刷新到文件中
        4、释放资源
 */
 
public class Demo03BufferedWriter {
    public static void main(String[] args) throws IOException {
        //1、创建字节缓冲输出流对象,构造方法中传递字符输出流
        BufferedWriter bw = new BufferedWriter(new FileWriter("files/c.txt"));
        // 2、调用字节缓冲输出流中的writer方法,把数据写入到内存缓冲区中
        for (int i = 0; i <10 ; i++) {
            bw.write("课工场"+i);
            //bw.write("\r\n");
            bw.newLine();
        }
        // 3、调用字节缓冲输出流中的flush方法,把内存缓冲区中的数据刷新到文件中
        bw.flush();
        // 4、释放资源
        bw.close();
    }
}

4)序列化与反序列化

  • 概念:
    在这里插入图片描述
  • 序列化:
/*
java.io.ObjectOutputStream extends OutputStream

ObjectOutputStream :对象的序列化流

作用:把对象以流的方式写入到文件中保存

构造方法:
    ObjectOutputStream(OutputStream out) 创建写入指定OutputStream的ObjectOutputStream
    参数:
        OutputStream out:字节输出流

    特有的成员方法:
        void writerObject(Object obj)将指定的对象写入ObjectOutputStream

    使用步骤:
        1、创建ObjectOutputStream对象,构造方法中传递字节输出流
        2、使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
        3、释放资源
 */
 
public class Demo01ObjectOutputStream {
    public static void main(String[] args) throws IOException {
        // 1、创建ObjectOutputStream对象,构造方法中传递字节输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("files/person.txt"));
        //2、使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
        oos.writeObject(new Person("小美女",18));
        //3、释放资源
        oos.close()
    }
}
/*
序列化与反序列化的时候,会抛出NotSerializableException没有序列化异常
类通过实现java.io.Serializable接口以启用其序列化功能。未实现此接口的类将无法使用其任何状态序列化或反序列化
Serializable接口也叫标记型接口
    要进行序列化和反序列化的类必须实现Serializable接口,就会给类添加一个标记
    当我们进行序列化和反序列化的时候,就会检测类上是否有这个标记。
        如果有,就可以序列化或者反序列化
        如果没有,就会抛出NotSerializableException
 */

public class Person implements Serializable {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    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 +
                '}';
    }
}
  • 反序列化:
/*
java.io.ObjectInputStream extends InputStream

ObjectInputStream :对象的反序列化流

作用:把文件中保存的对象,以流的方式读取出来使用

构造方法:
    ObjectInputStream(InputStream in):创建从指定InputStream 读取的 ObjectInputStream
    参数:
        InputStream in:字节输入流

特有的成员方法:
    Object readObject() 从ObjectInputStream 读取对象

使用步骤:
    1、创建ObjectInputStream对象,在构造方法中传递字节输入流
    2、使用ObjectInputStream对象的readObject方法,读取保存对象的文件
    3、释放资源
    4、使用读取出来的对象,直接打印

   readObject()方法声明抛出了ClassNotFoundException异常:class文件找不到异常
   当不存在对象的calss文件时,抛出此异常
   反序列化的前提:
        1、类必须实现serializable接口
        2、必须存在类对应的class文件
 */
 
public class Demo02ObjectInputStream {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1、创建ObjectInputStream对象,在构造方法中传递字节输入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("files/person.txt"));
        //2、使用ObjectInputStream对象的readObject方法,读取保存对象的文件
        Object o = ois.readObject();
        //3、释放资源
        ois.close();
        //4、使用读取出来的对象,直接打印
        System.out.println(o);
        //也可强转成Person类打印
        Person p=(Person)o;
        System.out.println(p.getName()+p.getAge());
    }
}

四、流的异常处理

一、try catch finally

/*
在jdk1.7之前可以使用try catch finally处理异常

格式:
    try{
        可能会产生异常的代码
    }catch(异常类的变量 变量名){
        异常的处理逻辑
    }finally{
        一定会指定的代码
        资源释放
    }
 */
 
public class Demo01TryCatch {
    public static void main(String[] args) {
        
        //提高变量fw的作用域,让finally可以使用
        //变量在定义的时候可以没有值,在使用的时候必须有值
        //fw = new FileWriter("files/g.txt",true);如果执行失败,fw没有值,fw.close就会报错
        
       FileWriter fw=null ;
       try{
           //可能会产生异常的代码
           fw = new FileWriter("files/g.txt",true);
           for (int i = 0; i <10 ; i++) {
               fw.write("HelloWorld"+i+"\r\n");
           }
           fw.close();
       }catch(IOException e){
           //异常的处理逻辑
           System.out.println(e);
       }finally{
           //一定会指定的代码
           //创建对象失败了,fw的默认值为null,null是不能调用方法的,会抛出NullPointerException异常,需要增加一个判断,不是null再把资源释放了
           if(fw!=null){
               try {
                   //fw.close方法声明抛出IOException异常,所以要处理这个异常对象,要么trycatch,要么throws,
                   fw.close();
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }
       }
    }
}

二、JDK1.7之后

/*
JDK7的新特性
    在try的后面可以增加一个(),在括号中可以定义流对象
    那么这个流对象的作用域就在try中有效
    try中的代码执行完毕后,就会自动的把流对象释放,不用写finally
    
    格式:
        try(定义流对象....){
        可能会产生异常的代码
    }catch(异常类的变量 变量名){
        异常的处理逻辑
    }
 */
 
public class Demo01JDK07Exception {
    public static void main(String[] args) {
        try(FileInputStream fis = new FileInputStream("files/b.txt");
            FileOutputStream fos = new FileOutputStream("files/test1.txt");){

            //可能会出现异常的代码
            //一次读取一个字节fangfa
            int len = 0;
            while((len=fis.read())!=-1){
                fos.write(len);
            }
        }catch(IOException e){
            //异常的处理逻辑
            System.out.println(e);
        }
    }
}

三、JDK1.9之后

/*
JDK9新特性
    try的前面可以定义流对象,
    在try后面的()中可以直接引入流对象的名称(变量名)
    在try代码块执行完毕后,流对象也可以释放掉,不用写finally
   
    格式:
        A a = new A();
        B b = new B();
        try(a;b){
            可能会产生异常的代码
        }catch(异常类的变量 变量名){
            异常的处理逻辑
        }
 */
 
public class Demo01JDK09Exception {
    public static void main(String[] args) throws FileNotFoundException {
        FileInputStream fis = new FileInputStream("files/b.txt");
        FileOutputStream fos = new FileOutputStream("files/test1.txt");
        
        try(fis;fos){
            //一次读取一个字方法
            int len = 0;
            while((len=fis.read())!=-1){
                fos.write(len);
            }
        }catch(IOException e){
            System.out.println(e);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值