学习日记44--java学习--I/O流1

  1. 概述:
    IO流用来处理设备之间的数据传输
    • Java对数据的操作是通过流的方式
    • Java用于操作流的类都在IO包中
    • 流按流向分为两种:输入流,输出流。
    • 流按操作类型分为两种:
      • 字节流 : 操作字节的。字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
      • 字符流 : 操作字符的。字符流只能操作纯字符数据,比较方便。
  2. IO流常用父类
    • 字节流的抽象父类:
      • InputStream
      • OutputStream
    • 字符流的抽象父类:
      • Reader
      • Writer
  3. 基本框架:

    public static void main(String[] args) {                        //需要异常处理
            FileInputStream fis = new FileInputStream("xxx.txt");       //异常:读的文件可能不存在
            FileOutputStream fos = new FileOutputStream("yyy.txt");     //异常:写的路径可能不存在
    
            int b;
            while((b = fis.read()) != -1) {                             //异常:可能文件不可读
                fos.write(b);                                           //异常:可能文件不可写
            }
            fis.close();                                                //异常:可能无法关闭输入流
            fos.close();                                                //异常:可能无法关闭输出流
        }

    流的标准处理异常代码(jdk1.6版本)

        public static void demo1() throws FileNotFoundException, IOException {
            FileInputStream fis = null;
            FileOutputStream fos = null;
            try {
                fis = new FileInputStream("xxx.txt");
                fos = new FileOutputStream("yyy.txt");
    
                int b;
                while((b = fis.read()) != -1) {
                    fos.write(b);
                }
            }finally {
                try{
                    if(fis != null)
                        fis.close();
                }finally {                          //try fianlly的嵌套目的是能关一个尽量关一个
                    if(fos != null)
                        fos.close();
                }
            }
        }
    
    }

    流的标准处理异常(jdk1.7版本)

        public static void main(String[] args) throws IOException {
                try(
                FileInputStream fis = new FileInputStream("xxx.txt");     //已具备自动关闭(流)功能
                FileOutputStream fos = new FileOutputStream("yyy.txt");{
                int b;
                while((b = fis.read()) != -1) {
                    fos.write(b);
                }
            }
        }
  4. 缓冲区拷贝:BufferInputStream,BufferOutputStream,开发时推荐使用
    提高开发效率:活用匿名对象

        //FileInputStream fis = new FileInputStream("xxx.mp3");
        //BufferedInputStream bis = new BufferedInputStream(fis);   
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("xxx.mp3"));       //使用了匿名对象
    
  5. close方法

    • 具备刷新的功能,在关闭流之前,就会先刷新一次缓冲区(也就是将缓冲区的内容同步到文件中去),将缓冲区的字节全都刷新到文件上,再关闭,close方法刷完之后就能写了

    flush方法

    • 具备刷新的功能,刷完之后还可以继续写,可以实现查看实时进度
  6. IO流实现图片传输加密

    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Test1 {
    
        /**
         * @param args
         * @throws IOException 
         * 将写出的字节异或上一个数,这个数就是密钥,解密的时候再次异或就可以了
         */
        public static void main(String[] args) throws IOException {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("xxx.jpg"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.jpg"));   //复制后得到的图片无法打开,完成加密。把该图片同理再加密一次(双异或),即可解密。
    
            int b;
            while((b = bis.read()) != -1) {
                bos.write(b ^ 123);
            }
    
            bis.close();
            bos.close();
        }
    
    }
    
  7. 拷贝指定路径文件实例

    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.Scanner;
    
    public class Test2 {
    
        /**
         * 在控制台录入文件的路径,将文件拷贝到当前项目下
         * 
         * 分析:
         * 
         * 1,定义方法对键盘录入的路径进行判断,如果是文件就返回
         * 2,在主方法中接收该文件
         * 3,读和写该文件
         * @throws IOException 
         */
        public static void main(String[] args) throws IOException {
            File file = getFile();                  //获取文件
            BufferedInputStream  bis = new BufferedInputStream(new FileInputStream(file));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file.getName()));
    
            int b;
            while((b = bis.read()) != -1) {
                bos.write(b);
            }
    
            bis.close();
            bos.close();
        }
    
        /*
         * 定义一个方法获取键盘录入的文件路径,并封装成File对象返回
         * 1,返回值类型File
         * 2,参数列表无
         */
        public static File getFile() {
            Scanner sc = new Scanner(System.in);                //创建键盘录入对象
            System.out.println("请输入一个文件的路径:");
            while(true) {
                String line = sc.nextLine();                    //接收键盘录入的路径
                File file = new File(line);                     //封装成File对象,并对其进行判断
                if(!file.exists()) {
                    System.out.println("您录入的文件路径不存在,请重新录入:");
                }else if(file.isDirectory()) {
                    System.out.println("您录入的是文件夹路径,请重新录入:");
                }else {
                    return file;
                }
            }
        }
    }
  8. 录入数据拷贝到文件

    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.Scanner;
    
    public class Test3 {
    
        /**
         * 将键盘录入的数据拷贝到当前项目下的text.txt文件中,键盘录入数据当遇到quit时就退出
         * 
         * 分析:
         * 1,创建键盘录入对象
         * 2,创建输出流对象,关联text.txt文件
         * 3,定义无限循环
         * 4,遇到quit退出循环
         * 5,如果不quit,就将内容写出
         * 6,关闭流
         * @throws IOException 
         */
        public static void main(String[] args) throws IOException {
            //1,创建键盘录入对象
            Scanner sc = new Scanner(System.in);
            //2,创建输出流对象,关联text.txt文件
            FileOutputStream fos = new FileOutputStream("text.txt");
            System.out.println("请输入数据:");
            //3,定义无限循环
            while(true) {
                String line = sc.nextLine();                    //将键盘录入的数据存储在line中
                //4,遇到quit退出循环
                if("quit".equals(line)) {
                    break;
                }
                //5,如果不quit,就将内容写出
                fos.write(line.getBytes());                     //字符串写出必须转换成字节数组
                fos.write("\r\n".getBytes());
            }
            //6,关闭流
            fos.close();
        }
    
    }
  9. 字符流(FileReader类,FileWriter类)是什么

    • 字符流是可以直接读写字符的IO流
    • 字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要写出字符, 需要把字符转为字节再写出.
  10. IO流(什么情况下使用字符流)

    • 字符流也可以拷贝文本文件, 但不推荐使用. 因为读取时会把字节转为字符, 写出时还要把字符转回字节.
    • 程序需要读取一段文本, 或者需要写出一段文本的时候可以使用字符流
    • 读取的时候是按照字符的大小读取的,不会出现半个中文
    • 写出的时候可以直接将字符串写出,不用转换为字节数组
  11. (字符流是否可以拷贝非纯文本的文件)
    • 不可以拷贝非纯文本的文件
    • 因为在读的时候会将字节转换为字符,在转换过程中,可能找不到对应的字符,就会用?代替,写出的时候会将字符转换成字节写出去
    • 如果是?,直接写出,这样写出之后的文件就乱了,无法重现
  12. 带缓冲的字符流)

    • BufferedReader的read()方法读取字符时会一次读取若干字符到缓冲区, 然后逐个返回给程序, 降低读取文件的次数, 提高效率
    • BufferedWriter的write()方法写出字符时会先写到缓冲区, 缓冲区写满时才会写到文件, 降低写文件的次数, 提高效率
    BufferedReader br = new BufferedReader(new FileReader("aaa.txt"));  //创建字符输入流对象,关联aaa.txt
            BufferedWriter bw = new BufferedWriter(new FileWriter("bbb.txt"));  //创建字符输出流对象,关联bbb.txt
    
            int ch;             
            while((ch = br.read()) != -1) {     //read一次,会先将缓冲区读满,从缓冲去中一个一个的返给临时变量ch
                bw.write(ch);                   //write一次,是将数据装到字符数组,装满后再一起写出去
            }
    
            br.close();                         //关流
            bw.close();
  13. readLine()和newLine()方法,整行读写

    • BufferedReader的readLine()方法可以读取一行字符(不包含换行符号)
    • BufferedWriter的newLine()可以输出一个跨平台的换行符号”\r\n”
              BufferedReader br = new BufferedReader(new FileReader("aaa.txt"));
              BufferedWriter bw = new BufferedWriter(new FileWriter("bbb.txt"));
              String line;   //等同于 String line = null;
              while((line = br.readLine()) != null) {
                  bw.write(line);
                  //bw.write("\r\n");                 //只支持windows系统
                  bw.newLine();                       //跨平台的
              }
      
              br.close();
              bw.close(); 
  14. ReadLine() 方法只存在于 BufferedReader() ;NewLine() 方法只存在于 BufferedWriter()。在FileReader和FileWriter中是没有这两种方法的。

  15. 装饰设计模式:
    方法:
    1. 获取到被包装的类的引用
    2. 通过构造函数创建对象的时候,传入被包装的对象
    3. //对其原有功能进行升级
    优势:

    1. 耦合性不强,被装饰的类的变化与装饰类的变化无关
  16. 编码表–CharSet

  17. 流程:(使用指定码表的转换流)
    (utf-8).txt–>FileInputStream–>InputStreamReader(字节流,编码表),字节转行为字符–>BufferedReader–>Java程序–>BufferedWriter–>OutPutStreamWriter(字节流,编码表),字符转化为字节–>FileOutputStream–>(gbk).txt

  18. 实例:获取给定文本的每种字符出现的个数

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.TreeMap;
    
    public class Test3 {
    
        /**
         * 获取一个文本上每个字符出现的次数,将结果写在times.txt上
         * 
         * 分析:
         * 1,创建带缓冲的输入流对象
         * 2,创建双列集合对象TreeMap
         * 3,将读到的字符存储在双列集合中,存储的时候要做判断,如果不包含这个键,就将键和1存储,如果包含这个键,就将该键和值加1存储
         * 4,关闭输入流
         * 5,创建输出流对象
         * 6,遍历集合将集合中的内容写到times.txt中
         * 7,关闭输出流
         * @throws IOException 
         */
        public static void main(String[] args) throws IOException {
            //1,创建带缓冲的输入流对象
            BufferedReader br = new BufferedReader(new FileReader("zzz.txt"));
            //2,创建双列集合对象TreeMap
            TreeMap<Character, Integer> tm = new TreeMap<>();
            //3,将读到的字符存储在双列集合中,存储的时候要做判断,如果不包含这个键,就将键和1存储,如果包含这个键,就将该键和值加1存储
            int ch;
            while((ch = br.read()) != -1) {
                char c = (char)ch;                  //强制类型转换
                /*if(!tm.containsKey(c)) {
                    tm.put(c, 1);
                }else {
                    tm.put(c, tm.get(c) + 1);
                }*/
                tm.put(c, !tm.containsKey(c) ? 1 : tm.get(c) + 1);
            }
            //4,关闭输入流
            br.close();
            //5,创建输出流对象
            BufferedWriter bw = new BufferedWriter(new FileWriter("times.txt"));
            //6,遍历集合将集合中的内容写到times.txt中
            for(Character key : tm.keySet()) {
                switch (key) {
                case '\t':
                    bw.write("\\t" + "=" + tm.get(key));    
                    break;
                case '\n':
                    bw.write("\\n" + "=" + tm.get(key)); 
                    break;
                case '\r':
                    bw.write("\\r" + "=" + tm.get(key)); 
                    break;
                case ' ':
                    bw.write("space" + "=" + tm.get(key));
                    break;
                default:
                    bw.write(key + "=" + tm.get(key));          //写出键和值
                    break;
                }
                bw.newLine();
            }
            //7,关闭输出流
            bw.close();
        }
    
    }

猜你喜欢

转载自blog.csdn.net/dershine/article/details/82226810