io流不关闭会内存溢出吗_IO流——学习笔记

一、简介

  • IO:

    • 输入(读文件):表示将文件数据从文件当中输到内存当中

    • 输出(写文件):表示将数据从内存当中写到文件当中去

    • 流(stream):

    • 就是一串不段连续的数据集,其实就是管道

  • 作用:

    • 数据的载体

    • 将数据从一端传输到另一端的功能实现

二、IO流的分类

1、按方向分类

  • 输入流

    • 输入流他是针对读数据而言

4bdde85c12506692788577a3b045038e.png

输出流

  • 输出流他是针对写数据而言

4ea4439857e3f370e2eb82e637d5842d.png

2、按数据单位

  • 字符流

    • 2个字节为一个数据单元来传输

  • 字节流

    • 一个字节为一个数据单元来传输

3、按角色分类

  • 节点流

    • FileOutputStream

    • FileInputStream

    • 他是直接对接物理节点的流对象,称为节点流

    • 例如

  • 处理流

    • 他是在节点流的基础上,进一步装饰及包装,形成一个处理流

三、输出/输入流体系

595931f05c65fd8d991991fe6be39b30.png

四、分析FileInputStream类

1、所属的类

  • 输入流

    • 将数据从文件当中读取到内存中,可以在控制台输出

  • 字节流

    • 注意:读取文本文档时可能会出现乱码(一个汉字为2个字节)

    • 以字节单元读数据(byte)

  • 节点流

    • 直接对接文件

2、具体用法

  1. 创建File类的对象,指明所读文件(读文件一定要事先建好文件,写文件可以不用)

  2. 创建相应流的对象,把File类对象放进去

  3. 进行相应流的操做(读和写)

  4. 资源关闭

package FileInputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;public class MainTest2 {    public static void main(String[] args) {        // TODO Auto-generated method stub        FileInputStream fileInputStream=null;        try {            //1.创建File类对象,指明读取的文件            File file = new File("C:\\Users\\WQW\\Desktop\\wqw\\test.txt");            //2.创建相应 的流对象            fileInputStream = new FileInputStream(file);            //3.进行流的相应操作,这里进行读的操作                        //这是一种最先的方式//            int c1 = fileInputStream.read();//          //输出的是Scall码//          System.out.println(c1);//          int c2 = fileInputStream.read();//          System.out.println(c2);//          int c3 = fileInputStream.read();//          //可以强转为字符//          System.out.println((char)c3);            //改进后的方式//          //新建一个字节数组//          byte[] buf = new byte[32];//          //read(buf),此方法也就是当前读取的字节个数,将数据读取到buf数组//          int len = fileInputStream.read(buf);                        //再次改进的方式//          int buf;//          while ((buf=fileInputStream.read())!=-1) {//              System.out.print((char) buf);//          }            //或者            byte[] buf = new byte[5];            int len;            while ((len=fileInputStream.read(buf))!=-1) {//              for (int i = 0; i < len; i++) {//                  System.out.println(buf[i]);//              }                //或者直接转化成String类型                String string = new String(buf,0,len);                System.out.print(string);            }        } catch (Exception e) {            // TODO: handle exception            e.printStackTrace();        }finally {            //4资源的关闭        try {            if(fileInputStream!=null)            fileInputStream.close();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        }}}

五、分析FileOutputStream类

1、此IO流所属分类

  • 输出流

    • 将内存中数据写到文件中去

  • 字节流

    • 他是以字节为位置写数据

  • 节点流

    • 直接面向文件操作

2、FileOutputStream用法

093d8b2321f33910f7bd5364fb018652.png

package FileOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;public class MainTest2 {    public static void main(String[] args) {        FileOutputStream fileOutputStream =null;        try {            //创建File类的对象,指明文件            File file = new File("C:\\Users\\WQW\\Desktop\\wqw\\test2.txt");            //2.创建相应流的对象            fileOutputStream = new FileOutputStream(file,true);            //3.进行流的相关操作                        //方式一            //fileOutputStream.write(97);            //方式二            String content = "welcome come to china";            //将字符串转换成字节数组            byte[] buf = content.getBytes();            fileOutputStream.write(buf);            fileOutputStream.flush();//刷新                        //方式三            fileOutputStream.write("helloworld123".getBytes());//转化成字节的形式            fileOutputStream.flush();        } catch (Exception e) {            // TODO: handle exception            e.printStackTrace();        }finally {            //4.资源的关闭        try {            if(fileOutputStream!=null)            fileOutputStream.close();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        }}}

六FileReader用法

1、所属的IO流分类

  • 输入流

    • 从文件读取数据到内存

  • 字符流

    • 以字符为传输数据单元

  • 节点流

    • 直接面向文件操作

2、注意事项

  • 注意乱码问题

    • 控制台编码格式必须跟文件编码一致

3、具体用法

package FileReader;import java.io.File;import java.io.FileReader;import java.io.IOException;public class MainTest {    public static void main(String[] args) {        // TODO Auto-generated method stub//      FileReader fileReader = null;//      try {//          //1.实例化File类的对象,指明要操作的文件//          File file = new File("test.txt");////          //2.提供具体的流//          fileReader = new FileReader(file);//          //          //3.数据的读入//          int date = -1;//          while ((date = fileReader.read()) != -1) {//              System.out.print((char) date);//          } //      } catch (Exception e) {//          e.printStackTrace();//      }finally {//          //4.关闭流//      try {//          if (fileReader !=null) {//              fileReader.close();//          }//          //      } catch (IOException e) {//           e.printStackTrace();//         }//      }        FileReader fileReader = null;        try {            //1.File类的实例化            File file = new File("test.txt");            //2.流的实例化            fileReader = new FileReader(file);            //3.读入的操作            char[] cbuf = new char[5];            int len;            while ((len = fileReader.read(cbuf)) != -1) {//              for (int i = 0; i < len; i++) {//                  System.out.print(cbuf[i]);//              }                //或者                String str = new String(cbuf, 0, len);                System.out.print(cbuf);            }         } catch (Exception e) {            e.printStackTrace();        }finally {            //4.资源 的关闭            try {                if(fileReader!=null)                fileReader.close();            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }}}

七、FileWriter的用法

1、所属的IO流分类

  • 输出流

    • 将内存的数据写到文件

  • 字符流

    • 以字符为数据单元来传输数据

  • 节点流

    • 直接面向文件操作

2、注意事项

  • 输出操作,如果对应的file不存在,则会创建

  • 如果存在,fileWriter = new FileWriter(file,true);

  • 这里写入true的的话,则会在原先内容的上再次添加

  • 如果不写或者为false则会进行文件的覆盖

3、具体用法

package FileWriter;import java.io.File;import java.io.FileWriter;import java.io.IOException;public class MainTest {    public static void main(String[] args) {        // TODO Auto-generated method stub        FileWriter fileWriter=null;        try {            //提供File的类,指明写入文件            File file = new File("test2.txt");            //2.提供需要的流            fileWriter = new FileWriter(file,true);            //3.写出的操作            fileWriter.write("I love Java".toCharArray());        } catch (Exception e) {            // TODO: handle exception            e.printStackTrace();        }finally {            //4.资源 的关闭            try {                fileWriter.close();            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }}}

4、读取和写入的综合操作

package FileWriter;import java.io.File;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class Test {    public static void main(String[] args)  {        // TODO Auto-generated method stub        FileReader fileReader=null;        FileWriter fileWriter=null;        try {            //创建file类的对象             File file = new File("test.txt");            File file2 = new File("test2.txt");            //创建流的对象            fileReader= new FileReader(file);            fileWriter = new FileWriter(file2);            //数据的读入和写出操作            char[] cbuf = new char[5];            int len;//每次读入到cbuf数组中的字符            while ((len =fileReader.read(cbuf))!=-1 ) {                //每次写出len个字符                fileWriter.write(cbuf, 0, len);            }        } catch (Exception e) {            // TODO: handle exception            e.printStackTrace();        }finally {            //资源的关闭        try {            if(fileReader!=null)            fileReader.close();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        try {            if(fileWriter!=null)            fileWriter.close();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        }}}

八、转换流

1、概述

  • 将字节流----》字符流

  • 将一个字节 的输入流转换成字符的输入流

2、InputStreamReader类作用

  • 输入流

    • 能够将字节输入流的内容以字符的形式读取内存

  • 字符流

  • 处理流

package InputStreamReader用法;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;public class MainTest {    public static void main(String[] args) throws IOException {        File file=new File("file2.txt");        //以文件输入字节流读取文件        FileInputStream fileInputStream=new FileInputStream(file);        //通过转换流将输入字节流----》输入字符流        InputStreamReader reader=new InputStreamReader(fileInputStream);        char []cbuf=new char[32];        int len=reader.read(cbuf);        //创建一个字符串对象        String content=new String(cbuf,0,len);        System.out.println(content);}}

3、OutputStreamWriter的用法

  • 所属的IO流的分类

    • 输出流

    • 字符流

    • 处理流

  • 作用

    • 将一个字符的输出流转换为字节的输出流

package OutputStreamWriter用法;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;public class MainTest {    public static void main(String[] args) throws IOException {        File file = new File("file3.txt");        FileOutputStream fileOutputStream = new FileOutputStream(file);        //将输出字节流---->输出字符流        //将数据以字符方式写到文件里面        OutputStreamWriter writer=new OutputStreamWriter(fileOutputStream);        writer.write("欢迎来到粤嵌,学习java");        writer.flush();        writer.close();        fileOutputStream.close();}}

九、缓冲流

1、简介

  • 最大的特点就是它有一个缓存区

    • 默认分配一个8k大小的缓存区,来存储数据

  • 作用

    • 针对大量的读取及写入数据,提高操作效率

  • 处理流之一

  • 不能直接对接文件

2、BufferedReader类的用法

  • 将从缓存区读取到内存(默认分配8k)

  • 缓存区

    • 批量读取数据

    • 按行读取

    • 反复读

package BufferedReader用法;import java.io.BufferedReader;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;public class MainTest {    public static void main(String[] args) throws IOException {        FileReader reader=new FileReader(new File("file4.txt"));        BufferedReader br=new BufferedReader(reader);        System.out.println((char)br.read());//a        System.out.println((char)br.read());//b        //设置一个mark:标记一个位置        System.out.println("mark 操作");        br.mark(2);        System.out.println((char)br.read());//c        System.out.println((char)br.read());//d        System.out.println("reset 操作");        br.reset();        System.out.println((char)br.read());//c        System.out.println((char)br.read());//d        //按行读取/*      String line1=br.readLine();        String line2=br.readLine();        String line3=br.readLine();        String line4=br.readLine();        System.out.println(line1);        System.out.println(line2);        System.out.println(line3);        System.out.println(line4);*/        //流}}

3、BufferedWriter用法

package BufferedWriter用法;import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;import java.io.IOException;public class MainTest {    public static void main(String[] args) throws IOException {        //构造器一个File对象        File file=new File("file4.txt");        //构造器Writer对象        FileWriter fileWriter=new FileWriter(file);        //使用缓存流针对文件进行读、写        BufferedWriter writer=new BufferedWriter(fileWriter);        writer.write("欢迎来到粤嵌!!!");        //刷新一下        writer.flush();        //资源关闭        //要求:先关闭外层的流,在关闭内层的流        writer.close();        //说明:内层的流会自动关闭        // fileWriter.close();}}

4、封装一个用Buffered实现文本复制的方法

package BufferedTest;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class MainTest {    //这是我们常用的方法//public static void main(String[] args) {//      // TODO Auto-generated method stub//      //实现非文本文件的复制//      FileInputStream fileInputStream=null;//      FileOutputStream fileOutputStream=null;//      BufferedInputStream bufferedInputStream=null;//      BufferedOutputStream bufferedOutputStream=null;//      try {//          //1、造文件//          File file = new File("C:\\Users\\WQW\\Desktop\\bj.jpg");//          File file2 = new File("C:\\Users\\WQW\\Desktop\\bj2.jpg");//          //2.造流//          //2.1造节点流//          fileInputStream = new FileInputStream(file);//          fileOutputStream = new FileOutputStream(file2); //          //2.2造缓冲流//          bufferedInputStream = new BufferedInputStream(fileInputStream);//          bufferedOutputStream = new BufferedOutputStream(fileOutputStream);//          //3.复制的细节:读取,写入//          byte[] buf = new byte[10];//          int len;//          while((len=bufferedInputStream.read(buf))!=-1) {//              bufferedOutputStream.write(buf, 0, len);//              bufferedOutputStream.flush();//          }//      } catch (IOException e2) {//          e2.printStackTrace();//      }//      //资源的关闭//      //要求:先关外层,在关内层//      try {//          if(bufferedInputStream!=null)//          bufferedInputStream.close();//      } catch (IOException e1) {//          // TODO Auto-generated catch block//          e1.printStackTrace();//      }//      try {//          if(bufferedOutputStream!=null)//          bufferedOutputStream.close();//      } catch (IOException e) {//          // TODO Auto-generated catch block//          e.printStackTrace();//      }//      //说明:关闭外层流的时候会自动关闭内层的流        fileInputStream.close();        fileOutputStream.close();//}    //在这里我们把上面的方法进行封装    //封装一个实现文件复制的方法    public  void copyFileWriterBuffered(String srcPath,String destPath) {        //实现非文本文件的复制        FileInputStream fileInputStream=null;        FileOutputStream fileOutputStream=null;        BufferedInputStream bufferedInputStream=null;        BufferedOutputStream bufferedOutputStream=null;        try {            //1、造文件            File file = new File(srcPath);            File file2 = new File(destPath);            //2.造流            //2.1造节点流            fileInputStream = new FileInputStream(file);            fileOutputStream = new FileOutputStream(file2);             //2.2造缓冲流            bufferedInputStream = new BufferedInputStream(fileInputStream);            bufferedOutputStream = new BufferedOutputStream(fileOutputStream);            //3.复制的细节:读取,写入            byte[] buf = new byte[10];            int len;            while((len=bufferedInputStream.read(buf))!=-1) {                bufferedOutputStream.write(buf, 0, len);                bufferedOutputStream.flush();            }        } catch (IOException e2) {            e2.printStackTrace();        }        //资源的关闭        //要求:先关外层,在关内层        try {            if(bufferedInputStream!=null)            bufferedInputStream.close();        } catch (IOException e1) {            // TODO Auto-generated catch block            e1.printStackTrace();        }        try {            if(bufferedOutputStream!=null)            bufferedOutputStream.close();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        //说明:关闭外层流的时候会自动关闭内层的流//      fileInputStream.close();//      fileOutputStream.close();}}

5、调用上面封装的方法,并测试复制文件所需要的时间

package BufferedTest;public class TestCopyFileWriteBuffered {    public static void main(String[] args) {        // TODO Auto-generated method stub        //起始的时间        long start = System.currentTimeMillis();        String srcPath = "C:\\Users\\WQW\\Desktop\\bj.jpg";        String destPath ="C:\\Users\\WQW\\Desktop\\bj3.jpg";        //调用方法        MainTest m = new MainTest();        m.copyFileWriterBuffered(srcPath,destPath);        //结束的时间        long end = System.currentTimeMillis();        System.out.println("复制操作花费的时间为:"+(end-start));}}

6.进行图片的加密

package 课堂练习;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;/** * 进行图片的加密 * */public class PicTest {    public static void main(String[] args) {        // TODO Auto-generated method stub        //FileInputStream fileInputStream = new FileInputStream(new File("C:\\Users\\WQW\\Desktop\\bj.jpg"));        //或者        try {            FileInputStream fileInputStream = new FileInputStream("C:\\Users\\WQW\\Desktop\\bj.jpg");            FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\WQW\\Desktop\\bj2.jpg");            byte[] buffer = new byte[20];            int len;            while ((len=fileInputStream.read(buffer))!=-1) {                //加密:对字节数组进行修改//              //错误的,buffer数据没有改变,只是b改变了//              for (byte b : buffer) {//                  b=(byte)(b^5);//              }                //正确的                for (int i = 0; i < len; i++) {                    buffer[i] = (byte) (buffer[i] ^ 5);                }                fileOutputStream.write(buffer, 0, len);            }            fileInputStream.close();            fileOutputStream.close();        } catch (FileNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }}}

7、进行图片 的解密

package 课堂练习;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;/** * 进行图片的解密 * 主要是^位运算符的使用 * */public class PicTest2 {    public static void main(String[] args) {        // TODO Auto-generated method stub        //FileInputStream fileInputStream = new FileInputStream(new File("C:\\Users\\WQW\\Desktop\\bj.jpg"));        //或者        try {            FileInputStream fileInputStream = new FileInputStream("C:\\Users\\WQW\\Desktop\\bj2.jpg");            FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\WQW\\Desktop\\bj3.jpg");            byte[] buffer = new byte[20];            int len;            while ((len=fileInputStream.read(buffer))!=-1) {                //解密:对字节数组进行修改//              //错误的,buffer数据没有改变,只是b改变了//              for (byte b : buffer) {//                  b=(byte)(b^5);//              }                //正确的                for (int i = 0; i < len; i++) {                    buffer[i] = (byte) (buffer[i] ^ 5);                }                fileOutputStream.write(buffer, 0, len);            }            //资源的关闭            fileInputStream.close();            fileOutputStream.close();        } catch (FileNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }}}

8、其它

  • 使用ByteArrayOutputStream来解决读取字节出现乱码问题

//如果文件内容太大,会出现乱码,可以用ByteArrayOutputStream来实现//          byte[] buffer = new byte[20];//          int len;//          while((len= inputStream.read(buffer))!=-1) {//              String str = new String(buffer, 0, len);//              System.out.println(str);//          }            //使用ByteArrayOutputStream,把文件内容写入到一个数组中去//          baos = new ByteArrayOutputStream();//          byte[] buffer = new byte[5];//          int len;//          while((len=inputStream.read(buffer))!=-1) {//              baos.write(buffer, 0, len);//          }//          //转换成字符串//          System.out.println(baos.toString());

十一、字符集

1、常用的字符集

  • ASCII:美国信息交换码,用一个字节的7位可以表示

  • ISO-8859-1:用一个字节的8位可以表示

  • GB2312:中国的中文编码表,最多两个字节编码中文

  • GBK:融合了更多 的中文字文字字符

  • Unicode:国际标准码,融合了目前人类使用的所有字符,所有的文字都要用两个字节来表示

  • UTF-8:变长的编码方式,可用1-4个字节来表示一个字符

2、解决字符乱码问题

package 课堂练习;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.util.Arrays;public class Test4 {    public static void main(String[] args) {        // TODO Auto-generated method stub        FileInputStream fileInputStream = null;        try {            //创建File类对象            File file = new File("C:\\Users\\WQW\\Desktop\\wqw\\hello.txt");            //创建流的对象            fileInputStream = new FileInputStream(file);            //3.进行流的读取            //新建一个字节数组、            byte[] buf = new byte[2];            int len;            while ((len=fileInputStream.read(buf))!=-1) {                int pos=0;                for(byte v:buf) {                    //记录负数的个数                    if(v<0) {                        pos++;                    }                }                if(pos%2==0) {                    //将字节数组转化成字符串                    String str= new String(buf,0,len);                    System.out.print(str);                }else {                    //再读取下一位                    int nextByteValue = fileInputStream.read();                    int nextLen = len+1;                    //将字节数组扩容一位                    buf = Arrays.copyOf(buf, nextLen);                    buf[len]=(byte)nextByteValue;                    //打印输出                    String str = new String(buf,0,nextLen);                    System.out.print(str);                }            }        } catch (Exception e) {            // TODO: handle exception               e.printStackTrace();        }finally {            //关闭资源        try {            if(fileInputStream!=null)            fileInputStream.close();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        }}}

十一、求一篇文档中的每个字符出现的次数

package 课堂练习;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.util.HashMap;import java.util.Map;import java.util.Set;/** * 获取文本上每个字符出现的字数 * 提示:遍历文本的所有一个字符,保存在Map中 * */public class Test5 {    public static void main(String[] args) {        // TODO Auto-generated method stub        FileReader fileReader = null;        BufferedWriter bufferedWriter = null;        try {            //1.创建Map集合            Map<Character,Integer> map = new HashMap<>();            //遍历每一个字符,每一个字符出现的次数放到map中            fileReader = new FileReader("C:\\Users\\WQW\\Desktop\\Test.txt");            int c = 0;            while ((c=fileReader.read())!=-1) {                //int 还原char                char ch =(char)c;                //判断char是否在map中第一次出现                if (map.get(ch)==null) {                    map.put(ch, 1);                }else {                    map.put(ch, map.get(ch)+1);                }            }            //3.把map中的数据存放在count.txt            //3.1创建writer            bufferedWriter = new BufferedWriter(new FileWriter("C:\\Users\\WQW\\Desktop\\Test2.txt"));            //3.2遍历map,在写入数据            Set<Map.Entry<Character,Integer>> entrySet = map.entrySet();            for (Map.Entry<Character, Integer> entry : entrySet) {                switch(entry.getKey()) {                case ' ':                    bufferedWriter.write("空格="+entry.getValue());                    break;                case '\t':                    bufferedWriter.write("tab键="+entry.getValue());                    break;                case '\r':                    bufferedWriter.write("回车="+entry.getValue());                    break;                  case '\n':                    bufferedWriter.write("换行="+entry.getValue());                    break;                  default:                    bufferedWriter.write(entry.getKey()+"="+entry.getValue());                    break;                }                bufferedWriter.newLine();            }        }catch (Exception e) {            e.printStackTrace();        }finally {            try {                if(bufferedWriter!=null)                bufferedWriter.close();            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }}}

十二、BufferedReader源码分析

1、分析构造器

public MyBufferedReader(Reader in, int sz) {        super(in);        if (sz <= 0)            throw new IllegalArgumentException("Buffer size <= 0");        this.in = in;        //自定义缓存大小        //分配8个字符的缓存大小        cb = new char[sz];        //nextChar:记录下一次读取字符的位置        //nChars:记录当前缓存区可读的字符个数        nextChar = nChars = 0;    }

2、分析read方法

public int read(char cbuf[], int off, int len) throws IOException {        //编写同步锁代码块        synchronized (lock) {            //确认输入流不为空            ensureOpen();            if ((off < 0) || (off > cbuf.length) || (len < 0) ||                ((off + len) > cbuf.length) || ((off + len) < 0)) {                throw new IndexOutOfBoundsException();            } else if (len == 0) {                return 0;            }            //从缓存区的数据复制到cbuf数组里面            int n = read1(cbuf, off, len);            if (n <= 0) return n;            //将之前处理不完的数据复制到cbuf数组,再次调用read1方法            while ((n < len) && in.ready()) {                int n1 = read1(cbuf, off + n, len - n);                if (n1 <= 0) break;                n += n1;            }            return n;        }    }

read1方法

private int read1(char[] cbuf, int off, int len) throws IOException {        //nextChar:记录下一次读取字符的位置        //nChars:记录缓存区可读的字符个数        //如果nextChar>nChars,则重新刷新缓存区        if (nextChar >= nChars) {            /* If the requested length is at least as large as the buffer, and               if there is no mark/reset activity, and if line feeds are not               being skipped, do not bother to copy the characters into the               local buffer.  In this way buffered streams will cascade               harmlessly. */            if (len >= cb.length && markedChar <= UNMARKED && !skipLF) {                return in.read(cbuf, off, len);            }            //针对缓存区的数据,重新刷新,将新的数据重新更新到缓存区            fill();        }        if (nextChar >= nChars) return -1;        if (skipLF) {            skipLF = false;            if (cb[nextChar] == '\n') {                nextChar++;                if (nextChar >= nChars)                    fill();                if (nextChar >= nChars)                    return -1;            }        }        int n = Math.min(len, nChars - nextChar);        //将缓冲区的数据复制到cbuf        System.arraycopy(cb, nextChar, cbuf, off, n);        //并且更新nextChar的位置值        nextChar += n;        return n;    }

fill方法(刷新)

private void fill() throws IOException {        int dst;        //是否有调有mark方法,如果没有设置mark值,则markedChar <= UNMARKED为true        if (markedChar <= UNMARKED) {            /* No mark */            dst = 0;        } else {            /* Marked */            int delta = nextChar - markedChar;            if (delta >= readAheadLimit) {                /* Gone past read-ahead limit: Invalidate mark */                markedChar = INVALIDATED;                readAheadLimit = 0;                dst = 0;            } else {                if (readAheadLimit <= cb.length) {                    /* Shuffle in the current buffer */                    System.arraycopy(cb, markedChar, cb, 0, delta);                    markedChar = 0;                    dst = delta;                } else {                    /* Reallocate buffer to accommodate read-ahead limit */                    char ncb[] = new char[readAheadLimit];                    System.arraycopy(cb, markedChar, ncb, 0, delta);                    cb = ncb;                    markedChar = 0;                    dst = delta;                }                nextChar = nChars = delta;            }        }        int n;        do {            //将输入流的数据读取到缓存区里面,n变量决定读取多个字符            n = in.read(cb, dst, cb.length - dst);        } while (n == 0);        //如果n>0,代表已经读到数据        if (n > 0) {            //nChars:缓存区可读的数据            nChars = dst + n;            //下一次可读数据的位置            nextChar = dst;        }    }

十三、打印流(PrintStream\PrintWriter)

1、重定向概念

  • 有两种重定向输出

    • 默认的标准输出设备:控制台(以红色字体输出)

    • 默认的标准输出设备:控制台

    • 标准输出

    • 标准错误输出

  • 标准输入

    • 默认的设备;键盘

  • 上述重定向输入、输出都可以使用System类来描述

    • 描述标准输出错误(默认控制台,红色字体输出)

    • 描述标准输出(默认控制台)

    • 描述标准输入(默认:键盘)

    • System.in

    • System.out

    • System.err

  • 举例

public class MainTest{    public static void main(String[] args){        //思路:使用System.in实现。System.in---->转换流----》BufferedReaderd的readline()方法                //将字节转换成字符        InputStreamReader isr = new InputStreamReader(System.in);        BufferedReader br = new BufferedReader(isr);        while(true){            System.out.println("请输入字符");            String data = br.readLine();            if("e".equalsIgnoreCase(data)){                System.ouot.priintln("程序结束");                break;            }            String upperCase = data.toUpperCase();            System.outprintln(upperCase);        }    }}

2、PrintStream类

  • 分类

    • 但同时它也支持字符串输出,如果调用printxxx(String str)方法,他底层就是调用BufferWriter实现输出

    • 也支持字节输出操作

    • writer(int b);

    • writer(byte[] buf);

    • 写数据

    • 输出流

    • 字节流

package PrintStream实例;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.PrintStream;public class MainTest {    public static void main(String[] args) throws IOException {/*      System.out.println("hello world");        System.err.println("java hello");*/        //调用PrintStream的打印流将helloworld输出到控制器        //重定向输出        /*         * 标准输出:System.out配置         * 标准错误输出:System.err配置         * */        /*         * 修改重定向设备:         * 标准输出到a.txt         *  标准错误输出:b.txt         *          */        PrintStream consolePs=System.out;        //创建一个PrintStream打印类,针对文件输出流进行打印写入操作        FileOutputStream aFileOutptStream=new FileOutputStream(new File("a.txt"));        PrintStream ps=new PrintStream(aFileOutptStream);/*      ps.println("helloworld 1");        ps.println("helloworld 2");        ps.println("helloworld 3");*/        ps.write(97);        //创建一个PrintStream打印类,针对标准错误输出信息打印到b.txt        /*FileOutputStream bFileOutptStream=new FileOutputStream(new File("b.txt"));        PrintStream errorPs=new PrintStream(bFileOutptStream);        //更改标准输出设备:从控制台---->a.txt文件        System.setOut(ps);        //更改标准错误输出设备:从控制台----->b.txt        System.setErr(errorPs);        System.out.println("helloworld");        System.out.println("helloworld2");        System.out.println("helloworld3");        //还原默认的标准输出        System.setOut(consolePs);        System.out.println("helloworld4");        System.out.println("helloworld5");        System.out.println("helloworld6");        //输出标准错误信息        System.err.println("error helloworld 1");        System.err.println("error helloworld 2");        System.err.println("error helloworld 3");        System.err.println("error helloworld 4");*/        /*        ps.println("helloworld");        ps.println("aaaaaa");        ps.println("bbbbb");        ps.flush();        ps.close();        aFileOutptStream.close();        */}}

3、PrintWriter类

  • 输出流

  • 输出数据、打印数据

  • 字符流

    • 不支持字节操作

    • 仅支持字符操作

package PrintWriter实例;import java.io.File;import java.io.FileWriter;import java.io.IOException;import java.io.PrintWriter;public class MainTest {    public static void main(String[] args) throws IOException {        FileWriter fileWriter=new FileWriter(new File("c.txt"));        PrintWriter pw=new PrintWriter(fileWriter);        pw.println("helloworld1");        pw.println("helloworld2");        pw.println("helloworld3");        pw.println("helloworld4");        //刷新一下        pw.flush();}}

十四、RandomAccessFile类作用

1、简介

  • 它并不是IO流体系中的一种

  • 但它能够读、写文件

  • 可以自由访问文件的任意位置

2、特点

  • 针对文件,支持字节、字符操作

  • 针对行数据操作

  • 自由访问文件的任意位置

    • seck方法

3、使用方式

  • 创建RandomAccessFile类实例需要指定一个mode参数,该参数指定RandomAccessFile的访问模式

    • r:以只读的方式打开

    • rw:打开以便读取和写入

    • rwd:打开以便读取和写入,同步文件内容的更新

    • rws:打开以便读取和写入,同步文件内容和元数据的更新

4、举例

package RandomAccessFile实例;import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;public class MainTest2 {    public static void main(String[] args) throws IOException {        File file=new File("g.txt");        RandomAccessFile randomAccessFile=new RandomAccessFile(file, "rw");        String content="helloworld";        randomAccessFile.writeUTF(content);        randomAccessFile.writeUTF(content);        randomAccessFile.writeUTF(content);        randomAccessFile.writeUTF(content);}}

十五、对象流(处理流)

1、概述:

  • 用于存储和读取基本数据类型数据或对象的处理流

  • 序列化

    • 用ObjectOutputStream类保存基本数据类型或对象的机制

  • 反序列化

    • 用ObjectInputStream类读取基本类型数据或对象的机制

  • ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量

2、ObjectOutputStream(序列化)

  • 将内存中java对象序列化成字节序列,保存到磁盘中或通过网络传输出去

  • 如何实现序列化

    • 创建一个类并实现Serializable接口

    • 创建上面类的对象

    • 创建一个输出流的文件

    • 新建一个ObjectOutputStream对象

    • 调用writerObject()方法

  • 举例

package objectOutputStream;import java.io.Serializable;//创建一个类并实现Serializable接口public class Person implements Serializable{    private String name;    private int 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;}    public Person(String name, int age) {        super();        this.name = name;        this.age = age;}    public Person() {        super();}    @Override    public String toString() {        return "Person [name=" + name + ", age=" + age + "]";}}
package objectOutputStream;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;public class MainTest {    //进行序列化处理    public static void main(String[] args) {        // TODO Auto-generated method stub        //创建Person对象        Person person = new Person();        person.setAge(25);        person.setName("张三");        FileOutputStream fileOutputStream;        ObjectOutputStream objectOutputStream=null;        try {            //创建一个输出流的文件            fileOutputStream = new FileOutputStream(new File("person.txt"));            //ObjectOutputStream针对次此fileOutputStream进行处理            objectOutputStream= new ObjectOutputStream(fileOutputStream);               //调用writerObject方法            objectOutputStream.writeObject(person);        } catch (FileNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally {            //资源关闭           try {               //进行判断ObjectOutputStream对象是否创建成功               if(objectOutputStream!=null)               objectOutputStream.close();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        }}}

3、ObjectInputStream(反序列化)

  • 从磁盘针对序列化文件,还原成一个对象

  • 步骤

    • Person p=(Person) os.readObject();
    • 创建读取文件的输入流对象

    • 创建一个读取对象的输入流对象,读取某个文件

    • 反序列化成一个对象

    • 打印输出

  • 举例

package objectInputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.ObjectInputStream;import objectOutputStream.Person;public class MainTest {    //进行反序列化处理    public static void main(String[] args) {        // TODO Auto-generated method stub        try {            //创建一个输入流的文件            FileInputStream fileInputStream = new FileInputStream(new File("person.txt"));            //ObjectInputStream针对次此fileInputStream进行处理            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);            //反序列化成一个对象            Person person = (Person) objectInputStream.readObject();            //打印输出            System.out.println("年龄:"+person.getAge());            System.out.println("用户名:"+person.getName());            //资源关闭            objectInputStream.close();        } catch (FileNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (ClassNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }}}

4、关键字

  • transient

    • 使用该关键字修饰成员变量,则此变量忽略序列化处理

5、自定义序列化处理

  • 简介

    • 可以自定义实现序列化逻辑处理

  • 具体实现

    • 在序列化对象类重写:readObject和writeObject方法

  • 举例

package 自定义序列化;import java.io.IOException;import java.io.Serializable;public class Person2 implements Serializable{    private String name;    private int 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;}    public Person2(String name, int age) {        super();        this.name = name;        this.age = age;}    public Person2() {        super();}    @Override    public String toString() {        return "Person [name=" + name + ", age=" + age + "]";}    /**     * 通过重写此方法,还原成文件     * 要用private方法     * */    private void readObject(java.io.ObjectInputStream in) {        try {            setName(in.readUTF().toUpperCase());            setAge(in.readInt());        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }}    /**通过重写此方法,自定义序列化逻辑(序列化,将对象序列化成字节,存储到磁盘)     *      * */    private void writeObject(java.io.ObjectOutputStream out) {        //将用户名序列化        try {            out.writeUTF(getName());            //将年龄序列化            out.writeInt(getAge());        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }}}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值