zoukankan      html  css  js  c++  java
  • java io 详细代码实现 纪录

    什么是IO流?

     byte序列的读写,Java中的IO流是实现输入/输出的基础.
    1)
    InputStream : 抽象类读取数据的过程  包含读取方法read();
      in 模仿了读取小说的过程

     简单说  :  in是读取文件的

    OutputStream:抽象了写出数据的过程  包含写出方法write();
     out模仿了写笔记记录的过程

     简单说  : out是写入文件的

    基本的byte流
    InputStream(抽象方法read())
     |--- FileInputStream(read()在文件上读取)   节点流
     |
     |--- FilterInputStream 过滤器流,输入流功能的扩展
     |   |--- DataInputStream(readInt())  基本类型数据的读取
     |   |--- BufferedInputStream 提供读取缓冲区管理
     | --- ObjectInputStream   过滤器流,依赖基本byte流,扩展对象的反序列化

    OutputStream(抽象方法write()) 
     |--- FileOutputStream(write()在文件上写实现写入)   节点流
     |
     |--- FilterOutputStream 过滤器流,输出流功能的扩
     |    |--- DataOutputStream(writerInt())  基本类型数据的写出
     |    |--- BufferedOutputStream 提供了输出缓冲区管理
     | --- ObjectOutputStream 过滤器流,依赖基本byte流,扩展对象的序列化

    注意:除节点流外都是过滤器流

    字符流,可以处理字符编码,底层依赖于byte流
    Reader 读取文本
         | --- InputStreamReader  过滤去,依赖基本byte输入流
         |      实现文本编码的解析
         |
         | --- BufferedReader 过滤器, 需要依赖Reader 实例
         |    提供了readLine()方法, 可以在文本文件中读取一行
         |    是常用的文本读取方法   
    Writer
         | --- OutputStreamWriter  过滤器,,依赖基本byte输出流
         |        实现文本编码
         | --- PrintWriter  过滤器,依赖于Writer 流
         |                       提供了输出文本常有方法println()

    2)  EOF =  End of File = -1 (文件读到末尾会返回-1)

    3)  输入流的基本方法  
     InputStream in = new InputStream(file) / /file是文件名
     int b  = in.read();      读取一个byte无符号填充到int底八位,-1是EOF
     int.read(byte[] buf)    读取数据填充到buf中
     int.read(byte[] buf,int start,int size)  读取数据填充到buf中
     in.close      关闭输入流

    4)输出流的基本方法:
     OutputStream out = new OutputStream(file) / /file是文件名
     out.write(int b)     写出一个byte 到流 b 的底八位写出
     out.write(byte[] buf)    将buf的一部分写入流中
     out.write(byte[] buf, int start, int size)  将buf的一部分写入流中
     out.flush()      清理缓存
     out.close

    1.FileInputStream (read()在文件上读取)   节点流
    方法:  read()         从输入流中读取数据的下一个字节
         read(byte[] buf)  从输入流中读取一定数量的字节,并将其存储在缓冲区数组 buf中 
         read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。

    import java.io.FileInputStream; 
    import java.io.IOException; 
    import java.io.InputStream; 
    public class InputStreamDemo { 
     public static void main(String[] args)  
      throws IOException { 
      String file = "out.txt"; 
      InputStream in = new FileInputStream(file); 
      int b; 
      while((b=in.read())!=-1){//read()方法 
       System.out.print(Integer.toHexString(b) + " "); 
      } 
      in.close(); 
       
      in = new FileInputStream(file); 
      //in.available() 可以读取的数据个数,小文件一般是文件长度 
      byte[] buf = new byte[in.available()]; 
      in.read(buf);//read(byte[] buf)方法重载 
      in.close(); 
      for (byte c : buf) { 
       System.out.print(Integer.toHexString(c & 0xff) + " "); 
       // c & 0xff --->将16进制写成0xff的格式 
       //ffffffd6---> d6 
       //11111111 11111111 11111111 11010110  &对应相乘 
       //00000000 00000000 00000000 11111111  0xff 
       //00000000 00000000 00000000 11010110 
      } 
     } 
    }


    2  FileOutputStream(write()在文件上写实现写入)   节点流
    方法 :write(int b)  将指定的字节写入此输出流。s
     write(byte[] buf)   将 b.length 个字节从指定的 byte 数组写入此输出流。
     write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
    例子

    import java.io.*; 
    
    
    public class OutputStreamDemo { 
     public static void main(String[] args)  
     throws IOException{ 
      String file = "out.txt"; 
      OutputStream out = new FileOutputStream(file); 
      out.write(65);//在文件中是以16进制存储的,对应0x41 
      out.write(66);//0x42 
      byte[] buf = {(byte)0xd6,(byte)0xd0}; 
      out.write(buf); 
      out.flush();//刷出缓存,清理缓冲区,保证可靠写  
      out.close(); 
     } 
    }
     

    3.BufferedInputStream和BufferedOutputStream 的 用法

    BufferedInputStream(FileInputStream in)
    BufferedOutputStream(FileOutputStream out)
    可以提高性能
    例子


    import java.io.BufferedInputStream; 
    import java.io.BufferedOutputStream; 
    import java.io.FileInputStream; 
    import java.io.FileOutputStream; 
    import java.io.IOException; 
    import java.io.InputStream; 
    
    
    public class BufferedStreamDemo { 
     public static void main(String[] args) throws IOException { 
      //BufferedInputStream普通写法 
      String file = "out.txt"; 
      InputStream ins = new FileInputStream(file); 
      BufferedInputStream bufin= new BufferedInputStream(ins); 
      int b; 
      while((b=bufin.read())!=-1){ 
       System.out.println(Integer.toHexString(b)); 
      } 
      //常用写法,只要用到FileInputStream的地方都可以套一个BufferedInputStream用来提升性能 
      BufferedInputStream in = new BufferedInputStream( 
        new FileInputStream("out.txt")); 
       
      //BufferedOutputStream 
      BufferedOutputStream out = new BufferedOutputStream( 
        new FileOutputStream("out.txt")); 
      out.write(65); 
     } 
    }
     

    4.基本类型数据的写出和读入
    DataOutputStream  方法:readInt()  readLong()  readBoolean()等
    写出(写)

    例子
    import java.io.*; 
    public class DataOutDemo { 
     public static void main(String[] args) 
      throws IOException{  
      String file = "data.dat";//项目文件夹 
      OutputStream out = new FileOutputStream(file); 
      //DataOutputStream 实现基本类型数据的序列化 
      //将基本类型数据拆开为byte序列,写入到out流中 
      DataOutputStream dos = new DataOutputStream(out); 
      dos.write(-2); 
      dos.writeInt(-2); 
      dos.writeLong(-2); 
      dos.writeByte(-2); 
      dos.writeDouble(-2); 
      dos.writeShort(-2); 
      dos.writeFloat(-2); 
      dos.writeBoolean(true); 
      dos.writeChar('中'); 
      dos.close(); 
    
    
     } 
    }

    DataInputStream   方法:  writeInt()  writeChar() 等8种
    读入(读)

    import java.io.DataInputStream; 
    import java.io.FileInputStream; 
    import java.io.IOException; 
    import java.io.InputStream; 
    
    
    public class DataInDemo { 
     public static void main(String[] args)  
      throws IOException{ 
       
      String file = "data.dat"; 
    
    
      InputStream in = new FileInputStream(file); 
      //DataInputStream 从基本流中读取基本类型数据,实现基本 
      //类型数据的反序列化 
      DataInputStream dis = new DataInputStream(in); 
      int b = dis.read(); 
      int i = dis.readInt(); 
      long l= dis.readLong(); 
      byte bx = dis.readByte(); 
      double d = dis.readDouble(); 
      short s = dis.readShort(); 
      float f = dis.readFloat(); 
      boolean bol = dis.readBoolean(); 
      char c = dis.readChar(); 
      dis.close(); 
      System.out.print( b +" ");//254  fe 
      System.out.print(i+" "); 
      System.out.print(l+" "); 
      System.out.print(bx+" "); 
      System.out.print(d+" "); 
      System.out.print(s+" "); 
      System.out.print(f+" "); 
      System.out.print(bol+" "); 
      System.out.print(c+" "); 
       
     } 
    }

    5 字符串的序列化(文字的编码方案)
     从char序列到byte序列 的转换,叫"编码"
     1) String 字符串本质上是Char
     
     2)utf-16be 编码-----将16位char从中间切开为2个byte
         utf -16be是将 unicode char[] 序列化为byte[]的编码方案
         能够支持65535个字符编码,英文浪费空间

     如:
     char[] = ['A',    'B',    '中']
      对应     0041,0042,4e2d

     utf-8:国际标准,是将unicode编码为byte序列的方案,采用变长编码 1-N方案,其中英文1个byte,中文3个byte
       unicoded的" 中": 4e 2d = 01001110 00101101
        utf-8的"中":e4 b8 ad =11100100 10111000 10101101
            1110xxxx 10xxxxxx 10xxxxxx

     以0开头的是英文(0-127)
     110表示连续2字节表示一个字符
     1110表示连续3字节表示一个字符
     每个数据字节以10开头

    GBK: 中国标准,支持20000+中日韩文,英文编码1byte,中文2byte
     与unicode不兼容,中文windows默认gbk

    ISO8859-1:只支持255个英文字符,不支持中文(Sun服务器默认编码,如tomcat等)

    例子

    import java.io.FileOutputStream; 
    import java.io.IOException; 
    import java.io.OutputStream; 
    
    
    public class CharIODemo { 
     public static void main(String[] args)  
      throws IOException{ 
      String str = "ABCD中国"; 
      System.out.println(str); 
      //Java 的字符是16位 Unicode值,而文件是8位Byte序列 
       
      //GBK 
      System.out.println("GBK编码方案,对字符编码"); 
      String file = "gbk.txt"; 
      OutputStream out = new FileOutputStream(file);//默认GBK编码方案 
      byte[] gbk = str.getBytes("GBK"); 
      out.write(gbk); 
      out.close(); 
      IOUtils.print(file); 
      //UTF-16BE,每个编码是2个字节 
      System.out.println("UTF-16BE编码方案,对字符编码"); 
      file = "utf-16be.txt"; 
      out = new FileOutputStream(file); 
      byte[] utf16be = str.getBytes("UTF-16BE"); 
      out.write(utf16be); 
      out.close(); 
      IOUtils.print(file); 
       
      //UTF-8,英文是1个字节,中文是3个字节 
      System.out.println("UTF-8编码方案,对字符编码"); 
      file = "utf-8.txt"; 
      out = new FileOutputStream(file); 
      byte[] utf8 = str.getBytes("UTF-8");//编码string -> byte[] 
      out.write(utf8); 
      out.close(); 
      IOUtils.print(file); 
       
      byte[] buf = IOUtils.read("utf-8.txt"); 
      //new String(buf,"UTF-8"),构造器可以将 byte编码序列 
      //解码为 char序列(字符串) 
      String s = new String(buf,"UTF-8");//解码byte-> String 
      System.out.println(s); 
     } 
    }

    6 字符流IO(Reader Writer)
    1) 字符的处理,一次处理一个字符(unicode编码)
    2) 字符的底层仍然是基本的字节流
    3) 字符流的基本实现
     InputStreamReader 完成byte流解析为char流,按照编码解析
     OutputStreamWriter 提供char流到byte流,按照编码处理
    4) 字符流的过滤器
        是字符读写的功能扩展,极大的方便了文本的读写操作
        BufferedReader : readLine()   一次读取一行
        PrintWriter : println()  一次打印一行
    5)读取一个文本文件
     InputStream is = new FileInputStream("test.txt");
     Reader in = new InputStreamReader(is);
     BufferedReader reader = new BufferedReader(in);
     或者
     BufferedReader in = new BufferedReader(new FileReader(filename));

    import java.io.BufferedInputStream; 
    import java.io.BufferedReader; 
    import java.io.FileInputStream; 
    import java.io.IOException; 
    import java.io.InputStreamReader; public class TestReaderDemo { 
     public static void main(String[] args)  
      throws IOException{ 
      //Scanner BufferedReader都是流的功能扩展,是过滤器 
      // 不能单独使用,最终需要依赖于基本byte流(in) 
      //Scanner 提供了nextLine()方法//Java5以后 
      //BufferedReader 提供了 readLine()方法,读取一行 
      //readLine()读取到文件末尾返回null 
       
      //逐行读取文本文件,显示到系统控制台 
      //工作中常用 
      String file = "in.txt"; //为当前工作区workspace/项目名/in.txt 
      BufferedReader in = new BufferedReader( 
        new InputStreamReader( 
          new BufferedInputStream( 
            new FileInputStream(file)),"gbk")); 
      String str; 
      while((str = in.readLine()) != null){ 
       System.out.println(str); 
      } 
      in.close(); 
     }

    6)写出一个文本文件
     PrintWriter out = new PrintWriter(new FileWriter(new FileOutputStream(filename)));
     或者
     PrintWriter out = new PrintWriter(
         new OutputStreamWriter(
          new FileOutputStream(filename)))
    例子

    import java.io.IOException; 
    import java.io.PrintWriter; 
    import java.util.Scanner; 
    
    
    public class SyncWriteDemo { 
     public static void main(String[] args)  
      throws IOException{ 
      Scanner in = new Scanner(System.in); 
      String file = "sync.txt"; 
      PrintWriter out = new PrintWriter(file,"UTF-8"); 
      while(true){ 
       String str = in.nextLine(); 
       out.println(str); 
       if("q".equalsIgnoreCase(str)){ 
        break; 
       } 
      } 
      out.close(); 
     } 
    }

    7)系统的默认编码,中文一般是GBK
    如何查看默认编码?

    String encoding = System.getProperty("file.encoding");


    7 对象的IO序列化和深层复制

    什么是对象序列化:
     将对象Object转换为byte序列,反之叫做对象的反序列华
    1)序列化流,是过滤流
     ObjectOutputStream   方法 writeObject()  对象的序列化
     ObjectInputStream     方法readObject()  对象的反序列化
    2)序列化接口(Serializable)


       对象必须实现"序列化接口Serializable"才能进行序列化,否则将出现不能序列化的异常
     Serializable是一个空的接口,没有任何方法 ,仅作为序列化的一个标识


    3)JavaBean 规范规定,Java类必须实现Serializable接口


       Java API中的类大多是符合Java Bean规范的,基本都实现了Serializable


    4) 对象的序列化可以变相实现对象的深层复制
    例子

    import java.io.BufferedInputStream; 
    import java.io.BufferedOutputStream; 
    import java.io.FileInputStream; 
    import java.io.FileOutputStream; 
    import java.io.ObjectInputStream; 
    import java.io.ObjectOutputStream; 
    import java.io.Serializable; 
    
    
    public class ObjectIODemo { 
     public static void main(String[] args)  
      throws Exception{ 
      String file = "obj.dat"; 
      ObjectOutputStream out = new ObjectOutputStream( 
        new BufferedOutputStream( 
          new FileOutputStream(file))); 
      Foo foo =new Foo(); 
      out.writeObject(foo);//将foo引用的对象,序列化到文件中 
      out.close(); 
       
      //读出 
      ObjectInputStream in = new ObjectInputStream( 
        new BufferedInputStream( 
          new FileInputStream(file))); 
      Foo foo1 = (Foo)in.readObject();//对象反序列化 
      in.close(); 
      System.out.println(foo1.name); 
    
    
      System.out.println("深层复制:对象被复制,对象属性也被复制"); 
      System.out.println(foo==foo1);//false 对象复制了(一层) 
      System.out.println(foo.name == foo1.name);//false ,属性被复制了(二层) 
      //利用序列化 和 反序列化  可以简洁的实现 对象的深层复制 
     } 
    
    
    } 
    class Foo implements Serializable{//Serializable没有声明方法 
     String name = "Tom"; 
    }

    浅层复制与深层复制
    1)java的默认规则是浅层复制,性能好,但隔离性差,如(clone(),Arrays.copyOf)
     浅层复制 : 对象的引用不同,但对象中属性的引用相同
    2)利用序列化可以实现深层复制
     深层复制: 对象的引用不同,但对象中的属性的引用也不相同

    import java.io.ByteArrayInputStream; 
    import java.io.ByteArrayOutputStream; 
    import java.io.ObjectInputStream; 
    import java.io.ObjectOutputStream; 
    
    
    public class DeepcopyDemo { 
     public static Object deepCope(Object obj){ 
      try{ 
       //1. 对象序列化 
       // 缓冲流: 字节数组输出流 
       ByteArrayOutputStream buf = 
        new ByteArrayOutputStream(); 
       //对象输出流 
       ObjectOutputStream out =  
        new ObjectOutputStream( 
          new ByteArrayOutputStream()); 
        
       out.writeObject(obj);//序列化对象到buf中 
       out.close(); 
        
       //2 .对象的反序列化 
       byte[] ary = buf.toByteArray(); 
       ByteArrayInputStream bais =  
        new ByteArrayInputStream(ary); 
       ObjectInputStream in =  
        new ObjectInputStream(bais); 
       Object o = in.readObject();//从ary反序列化 
       in.close(); 
       return o; 
        
      }catch(Exception e){ 
       e.printStackTrace(); 
       throw new RuntimeException(e); 
      } 
     } 
    }

    以上用到的ByteArrayInputStreamByteArrayOutputStream

    下面有一个ByteArrayInputStream和ByteArrayOutputStream的例子

    例子

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.util.Arrays;
    import com.tarena.day18.IOUtils;
    public class ByteArrayIODemo {
     public static void main(String[] args)
      throws IOException{
      byte[] ary = {1,-1,127,-128};
      //   {00000001, 11111111, 01111111, 10000000}
      ByteArrayInputStream in = new ByteArrayInputStream(ary);
      int b = in.read();//1 00000000 00000000 00000000 00000001
      System.out.println(b);
      b = in.read();
      System.out.println(b);//255   00000000 00000000 00000000 11111111
      b = in.read();  
      System.out.println(b);//127   00000000 00000000 00000000  01111111
      b = in.read();
      System.out.println(b);//128   00000000 00000000 00000000  10000000
      b = in.read();
      System.out.println(b);//-1    11111111  11111111  11111111  11111111
      in.close();
     
      ByteArrayOutputStream out = new ByteArrayOutputStream();//默认开辟32byte的数组作为输出目标 
      //如果满了就自动扩容
      //out:[0,0,0,0,0,0,0,.....]
      //
      out.write(1);//[1,0,0,0,0,0,....]
      out.write(-2);//[1,fe,0,0,0,0,0,....]
      out.write(-1);//[1,fe,ff,0,0,0,0,....]
      out.close();
      byte[] buf = out.toByteArray();//复制有效部分
      IOUtils.print(buf);//[01, fe, ff ]
     }
    }

  • 相关阅读:
    深度学习 框架比较
    深度学习 Fine-tune 技巧总结
    基于Spark环境对比Python和Scala语言利弊
    【Python系列】HDF5文件介绍
    【Git】CentOS7 通过源码安装Git
    【Git】Git工具常用命令
    登录自动跳转
    offset,scroll,client系列
    谷歌浏览器input中的text 和 button 水平对齐的问题
    git 的基本使用
  • 原文地址:https://www.cnblogs.com/signheart/p/14442592.html
Copyright © 2011-2022 走看看