zoukankan      html  css  js  c++  java
  • java I/O流

    java.io.File类用于表示文件(目录)
    File类只用于表示文件(目录)的信息(名称、大小等),不能用于文件内容的访问

    RandomAccessFile java提供的对文件内容的访问,既可以读文件,也可以写文件。
    RandomAccessFile支持随机访问文件,可以访问文件的任意位置

    (1)java文件模型
    在硬盘上的文件是byte byte byte存储的,是数据的集合
    (2)打开文件
    有两种模式"rw"(读写) "r"(只读)
    RandomAccessFile raf = new RandomeAccessFile(file,"rw")
    文件指针,打开文件时指针在开头 pointer = 0;
    (3) 写方法
    raf.write(int)--->只写一个字节(后8位),同时指针指向下一个位置,准备再次写入
    (4)读方法
    int b = raf.read()--->读一个字节
    (5)文件读写完成以后一定要关闭(Oracle官方说明)


    序列化与基本类型序列化
    1)将类型int 转换成4byte或将其他数据类型转换成byte的过程叫序列化
    数据---->n byte
    2)反序列化
    将n个byte 转换成一个数据的过程
    nbyte ---> 数据
    3)RandomAccessFile提供基本类型的读写方法,可以将基本类型数据
    序列化到文件或者将文件内容反序列化为数据
    IO流(输入流、输出流)
    字节流、字符流
    1.字节流
    1)InputStream、OutputStream
    InputStream抽象了应用程序读取数据的方式
    OutputStream抽象了应用程序写出数据的方式
    2)EOF = End 读到-1就读到结尾
    3)输入流基本方法
    int b = in.read();读取一个字节无符号填充到int低八位.-1是 EOF
    in.read(byte[] buf)
    in.read(byte[] buf,int start,int size)
    4)输出流基本方法
    out.write(int b) 写出一个byte到流,b的低8位
    out.write(byte[] buf)将buf字节数组都写入到流
    out.write(byte[] buf,int start,int size)

    5)FileInputStream--->具体实现了在文件上读取数据
    6)FileOutputStream 实现了向文件中写出byte数据的方法
    7)DataOutputStream/DataInputStream
    对"流"功能的扩展,可以更加方面的读取int,long,字符等类型数据
    DataOutputStream
    writeInt()/writeDouble()/writeUTF()

    8)BufferedInputStream&BufferedOutputStream
    这两个流类位IO提供了带缓冲区的操作,一般打开文件进行写入
    或读取操作时,都会加上缓冲,这种流模式提高了IO的性能
    从应用程序中把输入放入文件,相当于将一缸水倒入到另一个缸中:
    FileOutputStream--->write()方法相当于一滴一滴地把水“转移”过去
    DataOutputStream-->writeXxx()方法会方便一些,相当于一瓢一瓢把水“转移”过去
    BufferedOutputStream--->write方法更方便,相当于一飘一瓢先放入桶中,再从桶中倒入到另一个缸中,性能提高了

    package com.imooc.io;
    
    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 IOUtil {
        /**
         * 读取指定文件内容,按照16进制输出到控制台
         * 并且每输出10个byte换行
         * @param fileName
         * 单字节读取不适合大文件,大文件效率很低
         */
        public static void printHex(String fileName)throws IOException{
            //把文件作为字节流进行读操作
            FileInputStream in = new FileInputStream(fileName);
            int b ;
            int i = 1;
            while((b = in.read())!=-1){
                if(b <= 0xf){
                    //单位数前面补0
                    System.out.print("0");
                }
                System.out.print(Integer.toHexString(b)+"  ");
                if(i++%10==0){
                    System.out.println();
                }
            }
            in.close();
        }
        /**
         * 批量读取,对大文件而言效率高,也是我们最常用的读文件的方式
         * @param fileName
         * @throws IOException
         */
        public static void printHexByByteArray(String fileName)throws IOException{
            FileInputStream in = new FileInputStream(fileName);
            byte[] buf = new byte[8 * 1024];
            /*从in中批量读取字节,放入到buf这个字节数组中,
             * 从第0个位置开始放,最多放buf.length个 
             * 返回的是读到的字节的个数
            */
            /*int bytes = in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大
            int j = 1; 
            for(int i = 0; i < bytes;i++){
                System.out.print(Integer.toHexString(buf[i] & 0xff)+"  ");
                if(j++%10==0){
                    System.out.println();
                }
            }*/
          int bytes = 0;
          int j = 1;
          while((bytes = in.read(buf,0,buf.length))!=-1){
              for(int i = 0 ; i < bytes;i++){
                  System.out.print(Integer.toHexString(buf[i] & 0xff)+"  ");
                  if(j++%10==0){
                      System.out.println();
                  }
              }
          }
          in.close();
        }
        /**
         * 文件拷贝,字节批量读取
         * @param srcFile
         * @param destFile
         * @throws IOException
         */
        public static void copyFile(File srcFile,File destFile)throws IOException{
            if(!srcFile.exists()){
                throw new IllegalArgumentException("文件:"+srcFile+"不存在");
            }
            if(!srcFile.isFile()){
                throw new IllegalArgumentException(srcFile+"不是文件");
            }
            FileInputStream in = new FileInputStream(srcFile);
            FileOutputStream out = new FileOutputStream(destFile);
            byte[] buf = new byte[8*1024];
            int b ;
            while((b = in.read(buf,0,buf.length))!=-1){
                out.write(buf,0,b);
                out.flush();//最好加上
            }
            in.close();
            out.close();
            
        }
        /**
         * 进行文件的拷贝,利用带缓冲的字节流
         * @param srcFile
         * @param destFile
         * @throws IOException
         */
        public static void copyFileByBuffer(File srcFile,File destFile)throws IOException{
            if(!srcFile.exists()){
                throw new IllegalArgumentException("文件:"+srcFile+"不存在");
            }
            if(!srcFile.isFile()){
                throw new IllegalArgumentException(srcFile+"不是文件");
            }
            BufferedInputStream bis = new BufferedInputStream(
                    new FileInputStream(srcFile));
            BufferedOutputStream bos = new BufferedOutputStream(
                    new FileOutputStream(destFile));
            int c ;
            while((c = bis.read())!=-1){
                bos.write(c);
                bos.flush();//刷新缓冲区
            }
            bis.close();
            bos.close();
        }
        /**
         * 单字节,不带缓冲进行文件拷贝
         * @param srcFile
         * @param destFile
         * @throws IOException
         */
        public static void copyFileByByte(File srcFile,File destFile)throws IOException{
            if(!srcFile.exists()){
                throw new IllegalArgumentException("文件:"+srcFile+"不存在");
            }
            if(!srcFile.isFile()){
                throw new IllegalArgumentException(srcFile+"不是文件");
            }
            FileInputStream in = new FileInputStream(srcFile);
            FileOutputStream out = new FileOutputStream(destFile);
            int c ;
            while((c = in.read())!=-1){
                out.write(c);
                out.flush();
            }
            in.close();
            out.close();
        }
        
    }


    2.字符流
    1) 编码问题
    2)认识文本和文本文件
    java的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码)
    文件是byte byte byte ...的数据序列
    文本文件是文本(char)序列按照某种编码方案(utf-8,utf-16be,gbk)序列化为byte的存储结果
    3)字符流(Reader Writer)---->操作的是文本文本文件
    字符的处理,一次处理一个字符
    字符的底层任然是基本的字节序列
    字符流的基本实现
    InputStreamReader 完成byte流解析为char流,按照编码解析
    OutputStreamWriter 提供char流到byte流,按照编码处理

    FileReader/FileWriter
    字符流的过滤器
    BufferedReader ---->readLine 一次读一行
    BufferedWriter/PrintWriter ---->写一行


    3.对象的序列化,反序列化
    1)对象序列化,就是将Object转换成byte序列,反之叫对象的反序列化
    2)序列化流(ObjectOutputStream),是过滤流----writeObject
    反序列化流(ObjectInputStream)---readObject

    3)序列化接口(Serializable)
    对象必须实现序列化接口 ,才能进行序列化,否则将出现异常
    这个接口,没有任何方法,只是一个标准

    4) transient关键字
    private void writeObject(java.io.ObjectOutputStream s)
    throws java.io.IOException
    private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException

    package com.imooc.io;
    
    import java.io.Serializable;
    
    public class Student implements Serializable{
        private String stuno;
        private String stuname;
        //该元素不会进行jvm默认的序列化,也可以自己完成这个元素的序列化
        private transient int stuage;  
        
        public Student(String stuno, String stuname, int stuage) {
            super();
            this.stuno = stuno;
            this.stuname = stuname;
            this.stuage = stuage;
        }
    
        public String getStuno() {
            return stuno;
        }
        public void setStuno(String stuno) {
            this.stuno = stuno;
        }
        public String getStuname() {
            return stuname;
        }
        public void setStuname(String stuname) {
            this.stuname = stuname;
        }
        public int getStuage() {
            return stuage;
        }
        public void setStuage(int stuage) {
            this.stuage = stuage;
        }
        @Override
        public String toString() {
            return "Student [stuno=" + stuno + ", stuname=" + stuname + ", stuage="
                    + stuage + "]";
        }
         private void writeObject(java.io.ObjectOutputStream s)
                    throws java.io.IOException{
             s.defaultWriteObject();//把jvm能默认序列化的元素进行序列化操作
             s.writeInt(stuage);//自己完成stuage的序列化
         }
         private void readObject(java.io.ObjectInputStream s)
                    throws java.io.IOException, ClassNotFoundException{
              s.defaultReadObject();//把jvm能默认反序列化的元素进行反序列化操作
              this.stuage = s.readInt();//自己完成stuage的反序列化操作
        }
    }


    分析ArrayList源码中序列化和反序列化的问题

    5)序列化中 子类和父类构造函数的调用问题






  • 相关阅读:
    System.Text.Json 自定义Converter实现时间转换
    WeihanLi.Npoi 根据模板导出Excel
    用 F# 手写 TypeScript 转 C# 类型绑定生成器
    【C#】写文件时如何去掉编码前缀
    一个支持 CodeFirst/DbFirst/ModelFirst 的数据库小工具
    C#设计模式学习笔记:(15)迭代器模式
    【WPF学习】第四十六章 效果
    C# 如何实现完整的INI文件读写类
    Blend 修改TreeViewItem样式
    C#设计模式学习笔记:(16)观察者模式
  • 原文地址:https://www.cnblogs.com/shininguang/p/4774605.html
Copyright © 2011-2022 走看看