zoukankan      html  css  js  c++  java
  • Java进阶

    1.FileOutputStream文件字节输出流

      作用:把内存中的数据写入到硬盘当中

    构造方法

    public FileOutputStream(File file) :创建文件输出流以写入由指定的 File对象表示的文件。

    public FileOutputStream(String name) : 创建文件输出流以指定的名称写入文件。

    当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件。如果有这个文件,会清空这个文件的数据。

    写入数据的原理:(内存 - - > 硬盘)

      Java程序 - - > JVM(java虚拟机)- - > OS(操作系统)- - > OS调用写数据的方法 - - > 把数据写入文件当中

    public class OUTPutStream {
        public static void main(String[] args) throws IOException {
            FileOutputStream fos = new FileOutputStream("D:\JA\Part1-basic\src\basicpart\day01\StreamM\a.txt");
            fos.write(95);
            fos.close();
        }
    }

    一次写多个字节:

      如果写的第一个字节是正数(0-127),那么显示的时候会查ASCII码表

      如果写的第一个字节是负数,那第一个字节会和第二个字节,两个字节组成一个中文显示,查询系统默认码表(GBK)

    写出指定长度字节数组: write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节

    写入字符串的方法:可以使用String类中的方法把字符串,转换为字节数组

      byte【】 getBytes() 将字符串转换为字节数组

    public class OUTPutStream {
        public static void main(String[] args) throws IOException {
            FileOutputStream fos = new FileOutputStream("D:\JA\Part1-basic\src\basicpart\day01\StreamM\a.txt");
            byte[] bytes = "chris".getBytes();
            System.out.println(Arrays.toString(bytes));
            fos.write(bytes);
            fos.close();
        }
    }

    续写和换行,在构造方法中将append参数设置为true

      Windows换行符号:

      Linux:/n

      mac:/r

    public class OUTPutStream {
        public static void main(String[] args) throws IOException {
            FileOutputStream fos = new FileOutputStream("D:\JA\Part1-basic\src\basicpart\day01\StreamM\a.txt",true);
            fos.write("你好
    ".getBytes());
            fos.write("咋啦
    ".getBytes());
            fos.close();
        }
    }

    2.FileInputStream 文件字节输入流

    public class FileINputStream {
        public static void main(String[] args) throws IOException {
            FileInputStream fis = new FileInputStream("Part1-basic\src\basicpart\day01\StreamM\a.txt"); //相对路径
            int len = 0; //记录读取到的字节
            //循环遍历文件
            while ((len = fis.read()) != -1) {
                System.out.print(len);
            }
            fis.close();
        }
    }

    一次读取多个字节的方法:

    public class FileINputStream {
        public static void main(String[] args) throws IOException {
            FileInputStream fis = new FileInputStream("Part1-basic\src\basicpart\day01\StreamM\a.txt"); //相对路径
            byte[] bytes = new byte[4];//建立一个能装四个字节的数组
            int len = fis.read(bytes); //此时bytes里面会从文件中抓取前四个字节放入到数组中
            System.out.println(len);//len表示的是读取的有效字节个数
            System.out.println(Arrays.toString(bytes));
            System.out.println(new String(bytes));
        }
    }

    改进方法:

    public class FileINputStream {
        public static void main(String[] args) throws IOException {
            FileInputStream fis = new FileInputStream("Part1-basic\src\basicpart\day01\StreamM\a.txt"); //相对路径
            byte[] bytes = new byte[1024];//建立一个能装1024个字节的数组
            int len = 0;
            while ((len = fis.read(bytes)) != -1) {
                System.out.println(new String(bytes, 0, len)); //len为有效字节个数
            }
        }
    }

    文件复制:

    public class FileCopy {
        public static void main(String[] args) throws IOException {
            long startTime = System.currentTimeMillis();
            FileInputStream fis = new FileInputStream("D:\Baseball\cai.jpg");//创建文件字节输入流 读取数据
            FileOutputStream fos = new FileOutputStream("D:\AAD\cai.jpg");//创建文件字节输出流 写入数据
            int len = 0;//记录读取的有效字节
            byte[] bytes = new byte[1024];//一次多读一些
            while ((len = fis.read(bytes)) != -1){
                fos.write(bytes,0,len);//用字节输出流把读取到的字节写入到文件中
            }
            //释放资源,先关写的
            fos.close();
            fis.close();
            long endTime = System.currentTimeMillis();
            System.out.println("复制文件的时间"+(endTime - startTime)+ "毫秒");
        }
    }

    3.文件字符输入流 FileReader

    读取文件:

    public class FR {
        public static void main(String[] args) throws IOException {
            FileReader fr = new FileReader("Part1-basic\src\basicpart\day01\StreamM\a.txt");
            char[] cs = new char[1024];//用来存储读取到的多个字符
            int len = 0;//记录的是每次读取的有效字符个数
            while ((len = fr.read(cs)) != -1) {
                System.out.print(new String(cs, 0, len));
            }
        }
    }

    4.文件字符输出流 FileWriter 写入时先写入内存缓冲区中 因为要把字符转换为字节 flush一下就行了

    public class FR {
        public static void main(String[] args) throws IOException {
            FileWriter fw = new FileWriter("Part1-basic\src\basicpart\day01\StreamM\b.txt",true);
            fw.write(98);
            char[] cs = {'a','c','e'};
            fw.write(cs);
            fw.write("帅哥");
            fw.flush();
            fw.close();
        }
    }

     5.处理流中异常相关问题

      变量在定义的时候可以没有值,但在使用的时候必须有值

    public class FR {
        public static void main(String[] args) {
            FileWriter fw = null;//提高变量的作用域,变量的值必须先定义,不然局部无法使用
            try {
                fw = new FileWriter("r:Part1-basic\src\basicpart\day01\StreamM\b.txt", true);
                fw.write("船只");
                fw.flush();
            } catch (IOException e) {
                System.out.println(e);
            } finally {
                //如果创建对象失败了,那么fw的默认值为空,就会抛出空指针异常,需要进行判断
                if (fw != null) {
                    try {
                        fw.close();//本身存在异常,需要try catch
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    JDK7的新特性 try()括号里放对象,作用域只在try里有效,而且自动释放

    public class FR {
        public static void main(String[] args) {
            try (FileWriter fw = new FileWriter("r:Part1-basic\src\basicpart\day01\StreamM\b.txt", true)) {
                fw.write("船只");
                fw.flush();
            } catch(IOException e) {
                System.out.println(e);
            }
        }
    }

    6.Properties属性集 双列集合(key和value默认都是字符串) 唯一一个和IO流相结合的集合

    public Object setProperty(String key, String value) : 保存一对属性。

    public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。

    public Set<String> stringPropertyNames() :所有键的名称的集合。

    public class FR {
        public static void main(String[] args) {
            Properties prop = new Properties();
            //存储属性值
            prop.setProperty("chris","21");
            prop.setProperty("joe","20");
            prop.setProperty("Lin","23");
            //获取此集合中的健集
            Set<String> set = prop.stringPropertyNames();
    
            //遍历set集合,取出每一个键
            for (String key : set) {
                //使用方法得到值
                String value = prop.getProperty(key);
                System.out.println(key + value);
            }
        }
    }

    (1)public void load(InputStream inStream) : 从字节输入流中读取键值对。

      参数中使用了字节输入流,通过流对象,可以关联到某文件上,这样就能够加载文本中的数据了。

    (2)public void store(OutputStream out,String comment) 

      不能写入中文!!字节输出流

    (3)public void store(Writer writer,String comment)

      字符输出流,可以写入中文

      注释不能使用中文,一般使用空字符串

    public class FR {
        public static void main(String[] args) throws IOException {
            Properties prop = new Properties();
            //存储属性值
            prop.setProperty("chris","21");
            prop.setProperty("joe","20");
            prop.setProperty("Lin","23");
    
            FileWriter fw = new FileWriter("D:\Baseball\cai.txt");
            prop.store(fw,"sava data");
            fw.close();
        }
    }

    7.缓冲流

    缓冲流,也叫高效流,是对4个基本的 FileXxx 流的增强,所以也是4个流,按照数据类型分类:

      字节缓冲流: BufferedInputStream , BufferedOutputStream

      字符缓冲流: BufferedReader(特有方法readline,无数据时返回null,末尾不含任何终止符,需自己换行) , BufferedWriter(提供了个newline方法来换行)

    缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

    public class Buffered {
        public static void main(String[] args) throws IOException {
            FileOutputStream fos = new FileOutputStream("D:\JA\Part1-basic\src\basicpart\day01\StreamM\f.txt",true);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            bos.write("我是帅哥".getBytes());
            bos.flush();
            bos.close();
        }
    }

    复制文件的效率大大提升:

    public class Buffered {
        public static void main(String[] args) throws IOException {
            long s = System.currentTimeMillis();
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\JA\Part1-basic\src\basicpart\day01\StreamM\f.txt"));
            FileOutputStream fos = new FileOutputStream("D:\JA\Part1-basic\src\basicpart\day01\StreamM\g.txt",true);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = bis.read(bytes))!= -1){
                bos.write(bytes,0,len);
            }
            bis.close();
            bos.close();
            long e = System.currentTimeMillis();
            System.out.println("共耗时" + (e-s) + "毫秒");
        }
    }

    文本排序练习!!!重点

    public class TextSort {
        public static void main(String[] args) throws IOException {
            //1.先创建hashmap集合对读取的数据进行存储
            HashMap<String, String> map = new HashMap<>();
    
            //2.创建两个流对象
            BufferedReader reader = new BufferedReader(new FileReader("Part1-basic\src\basicpart\day01\StreamM\f.txt"));
            BufferedWriter writer = new BufferedWriter(new FileWriter("Part1-basic\src\basicpart\day01\StreamM\new.txt"));
    
            //3.使用readline方法来逐行读取文本
            String line; //用来记录文本
            while ((line = reader.readLine()) != null) {
                //4.对读取的文本进行切割
                String[] arr = line.split("\."); //序号和文本以.来分割
    
                //5.把切割好的键和值写入到hashmap中
                map.put(arr[0], arr[1]); //每次读取时arr【0】为序号 arr【1】为文本
            }
    
            //6.遍历hashmap集合
            for (String key : map.keySet()){
                String value = map.get(key); // 通过key获取value
                line = key + "." + value; //这就是完整的一条内容
                //7.将数据写回去
                writer.write(line);
                writer.newLine();//换行
            }
            reader.close();
            writer.close();
        }
    }

    8.转换流

    转换流 java.io.InputStreamReader ,是Reader的子类,是从字节流到字符流的桥梁。它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。

    构造方法

      InputStreamReader(InputStream in) : 创建一个使用默认字符集的字符流。

      InputStreamReader(InputStream in, String charsetName) : 创建一个指定字符集的字符流。

    转换流 java.io.OutputStreamWriter ,是Writer的子类,是从字符流到字节流的桥梁。使用指定的字符集将字符编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集。

    构造方法

      OutputStreamWriter(OutputStream in) : 创建一个使用默认字符集的字符流。

      OutputStreamWriter(OutputStream in, String charsetName) : 创建一个指定字符集的字符流。

    public class FileINputStream {
        public static void main(String[] args) throws IOException {
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("Part1-basic\src\basicpart\day01\StreamM\f.txt"),"gbk");
            osw.write("你好");
            osw.flush();
            osw.close();
        }
    }

    9.序列化和反序列化流

    序列化操作

    1. 一个对象要想序列化,必须满足两个条件:

      该类必须实现 java.io.Serializable 接口, Serializable 是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出 NotSerializableException 。

      该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用transient 关键字修饰。

      Static关键字修饰的变量是不能被序列化的,序列化的都是对象,因为static优先于对象进入到内存中

       

    public class FileINputStream {
        public static void main(String[] args) throws IOException {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Part1-basic\src\basicpart\day01\StreamM\f.txt"));
            oos.writeObject(new Person("chris",20)); //该类必须是标记接口的可序列化对象
            oos.close();
        }
    }

    另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败,抛出一个 InvalidClassException 异常。发生这个异常的原因如下:

      该类的序列版本号与从流中读取的类描述符的版本号不匹配

      该类包含未知数据类型

      该类没有可访问的无参数构造方法

    Serializable 接口给需要序列化的类,提供了一个序列版本号。 serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

     解决方法:在类中加入

      private static final long serialVersionUID = 1L;

     

    10.打印流 PrintStream

    可以改变打印流向

  • 相关阅读:
    .net core 3.1 使用Redis缓存
    JavaSE 高级 第11节 缓冲输入输出字节流
    JavaSE 高级 第10节 字节数组输出流ByteArrayOutputStream
    JavaSE 高级 第09节 字节数组输入流ByteArrayInputStream
    JavaSE 高级 第08节 文件输出流FileOutputStream
    JavaSE 高级 第07节 文件输入流FileInputStream
    JavaSE 高级 第06节 初识I、O流
    JavaSE 高级 第05节 日期类与格式化
    JavaSE 高级 第04节 StringBuffer类
    JavaSE 高级 第03节 Math类与猜数字游戏
  • 原文地址:https://www.cnblogs.com/caixiaowu/p/12864601.html
Copyright © 2011-2022 走看看