• 传统IO总结



    上面是IO家族的全家福,这里先讲一下InputStreamOutputStream


    字节流InputStreamOutputStream
    一个我们日常开发常见的场景,复制文件,应该如何实现?一般的,我们会使用InputStream的read方法从源文件读取数据,然后用OutputStream的write方法向目标文件写数据。
    读写部分的代码是这样的:

     

     

    try{

          //构造一个输入流对象(读数据)source.txt文本的内容为: 呵呵呵呵呵

          InputStream is = new FileInputStream("F:\source.txt");

          //构造一个输出流对象(写数据)

          OutputStream os = new FileOutputStream("F:\target.txt");

          int len;//表示读入的数据(十进制的形式表示)              

          while((len = is.read())!=-1){

             System.out.println("len="+len);

             os.write(len);

          }

          os.close();

          is.close();

    }catch(Exception e){

          e.printStackTrace();

    }

     

    byte是基本类型的一种,八位,取值范围是'1000 0000'到'0111 1111'(这是补码),转换成十进制是'-128'到'127'。
    int也是基本类型的一种,三十二位,取值范围-2147483648到2147483647。代码里,读取一字节(byte)的数据,然后返回的是一个十进制的数字(int),因为int有32位,所以接收只有8位的byte简直绰绰有余,把这个十进制数字作为参数传给write,在write方法里自然会还原成对应的byte数据,写到目标文件里。这样,复制就完成了。其实,InputStream有三个重载的read方法。它们是:
    1.read():一次读取一个字节;返回一个int,读到文件末尾返回-1;   
    2.read(byte [] b):一次读取一个byte数组长度的数据;返回一个int,读到文件末尾返回-1,这个int代表的是实际读取的字节个数,如果数组长度是1024,在数据足够的情况下,返回值都是1024,代表read方法读取了1024个字节。读取到的数据都存放在数组b中,可以通过OutputStream的write(b)方法写到目标文件中。
    3.read(byte[] b,int off,int len):将输入流中最多 len 个数据字节读入字节数组。尝试读取多达 len 字节,但可能读取较少数量。以整数形式返回实际读取的字节数。将读取的第一个字节存储在元素 b[off] 中,下一个存储在 b[off+1] 中,依次类推。读取的字节数最多等于 len。

    这里说一下native关键字,native方法是指本地方法,当在方法中调用一些不是由java语言写的代码或者在方法中用java语言,直接操纵计算机硬件时要声明为native方法,java中,通过JNI(Java Native Interface,java本地接口)里实现。FileInputStream的read方法就是native的,据说是交给c库实现了。
    OutputStream有三个重载的write方法。参数形式和InputStream是一样的,不说了。

    FileInputStream和FileOutputStream   

    因为操作文件,所以要使用FileInputStream和FileOutputStream,它们重写了父类的方法。这里说一点,new FileOutputStream("文件路径/文件名"),如果文件路径存在,文件不存在,则会根据文件名创建文件。如果文件路径不存在,则会报错。(可以修改参数,决定FileOutputStream是否替换已存在文件)。
    最后说一句,如果你要复制文件,一个字节一个字节的copy是很慢的。

    BufferedInputStream和BufferedOutputStream

    这两货是缓冲流,存在就是为了提高读写速率的,各有一个8K(默认的)的缓冲区。可以这样使用它们:

    try{

            InputStream is = new FileInputStream("F:\source.txt");

            OutputStream os = new FileOutputStream("F:\target.txt");

            InputStream bis = new BufferedInputStream(is);

            OutputStream bos = new BufferedOutputStream(os);

            int len;//表示读入的数据(十进制的形式表示)

            while((len = bis.read())!=-1){

                  System.out.println ("len="+len);

                  bos.write(len);

            }

            bos.close();

            bis.close();

    }catch(Exception e){

            e.printStackTrace();

    }

    可以这样理解,BufferedInputStream一次读取8K的数据到内存中(如果有这么多数据),然后向BufferedOutputStream中写8K数据,当达到8K,BufferedOutputStream会一次将这8k数据从内存写到目标文件里。因为大大减少了将数据从硬盘copy到内存的次数(一个字节一个字节读写,文件里有多少个字节就要copy多少次,学过操作系统的同学知道,这是很浪费时间的),所以节省了大把的时间。需要注意的是,可以通过BufferedOutputStream的flush方法送出不足8k的数据。当然,关闭流也可以达到相同效果。另外,关闭上层的流,下层的流也会同时关闭,所以代码里不用再关闭FileInputStream和FileOutputStream了。 

    DataInputStream和DataOutputStream

    如果要求你向文件中写入boolean类型,你要怎么做?首先,你要知道true和false的二进制编码是什么,然后通过字节流可以将2进制编码写入文件。当读取的时候,你要判断不同的二进制编码是什么意思,才可以把文件中的二进制编码还原成true和false。很麻烦,用数据流可以解决这个问题。
    代码如下:

    try {

                   File file = new File("F:\source.txt");

                   DataOutputStream out = new DataOutputStream(new FileOutputStream(file));

                   out.writeBoolean(true);

                   out.writeByte((byte) 121);

                   out.writeChar((char) '爱');

                   out.writeShort((short) 100);

                   out.writeInt(300);

                   out.writeLong(100000000000000L);

                   out.writeUTF("你好");

                   out.close();

               } catch (FileNotFoundException e) {

                   e.printStackTrace();

               } catch (SecurityException e) {

                   e.printStackTrace();

               } catch (IOException e) {

                   e.printStackTrace();

               }

     

     

    使用代码读取文件中的内容:

             try {

                   File file = new File("F:\source.txt");

                   DataInputStream in = new DataInputStream(new FileInputStream(file));

                   System.out.println("readBoolean():"+ in.readBoolean());

                   System.out.println("readByte():"+in.readByte());

                   System.out.println("readChar():"+in.readChar());

                   System.out.println("readShort():"+in.readShort());

                   System.out.println("readInt():"+in.readInt());

                   System.out.println("readLong():"+in.readLong());

                   System.out.println("readUTF():"+ in.readUTF());

                   in.close();

               } catch (FileNotFoundException e) {

                   e.printStackTrace();

               } catch (SecurityException e) {

                   e.printStackTrace();

               } catch (IOException e) {

                   e.printStackTrace();

               }

     
     输出结果如下:

    据我观察,write和read是一一对应关系。你在文件里写入的是一长串二进制数据,其中有Int、byte、boolean,当你读取的时候,也要按照写入的顺序去读取,否则是读不出准确的数据的。 
    PS:请看source.txt文件里存储的内容 :
     


    ObjectInputStream和ObjectOutputStream

    要求你向文件中写入java中的对象,怎么办。用这两个家伙吧,它们存在的意义和DataInputStream与DataOutputStream是一样的。
    写数据:

           try {

                   ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("F:/source.txt"));

                   out.writeBoolean(true);

                   out.writeByte((byte)65);

                   out.writeChar('a');

                   out.writeInt(20131015);

                   out.writeFloat(3.14F);

                   out.writeDouble(1.414D);

                   // 写入HashMap对象

                   HashMap map = new HashMap();

                   map.put("one", "red");

                   map.put("two", "green");

                   map.put("three", "blue");

                   out.writeObject(map);

                   // 写入自定义的Box对象,Box实现了Serializable接口

                   Box box = new Box("desk", 80, 48);

                   out.writeObject(box);

                   out.close();

               } catch (Exception ex) {

                   ex.printStackTrace();

               }   

     读取代码:

               try {

                   ObjectInputStream in = new ObjectInputStream(new FileInputStream("F:/source.txt"));

                   System.out.printf("boolean:%b " , in.readBoolean());

                   System.out.printf("byte:%d " , (in.readByte()&0xff));

                   System.out.printf("char:%c " , in.readChar());

                   System.out.printf("int:%d " , in.readInt());

                   System.out.printf("float:%f " , in.readFloat());

                   System.out.printf("double:%f " , in.readDouble());

                   // 读取HashMap对象

                   HashMap map = (HashMap) in.readObject();

                   Iterator iter = map.entrySet().iterator();

                   while (iter.hasNext()) {

                       Map.Entry entry = (Map.Entry)iter.next();

                       System.out.printf("%-6s -- %s " , entry.getKey(), entry.getValue());

                   }

                   // 读取Box对象,Box实现了Serializable接口

                   Box box = (Box) in.readObject();

                   System.out.println("box: " + box);

                   in.close();

               } catch (Exception e) {

                   e.printStackTrace();

               }

    我只想说,完全可以用理解DataInputStream与DataOutputStream的方式去理解这两个流。


    System.out.println()

    先看看System的源码:
    public final class System {

           public final static PrintStream out = null;

    ...

    }

    我们知道了,syso实际上调用的是PrintStream的println方法。


    字符流Reader和Writer

    首先讲一下字节流和字符流的区别:

    读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

    处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

    结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。
    我们主要使用Writer的write方法和Reader的read方法。下面介绍它们的具体子类。

    InputStreamReader和OutputStreamWriter

    既然是处理字符的,首先一个问题就是如何编码。 

           private static void testWrite() {

                  try {

                      File file = new File("f:/source.txt");

                      OutputStreamWriter out = new OutputStreamWriter(

                              new FileOutputStream(file), "utf-8");

                      out.write("哈哈哈啊哈哈哈呀呀");

                      out.close();

                  } catch (IOException e) {

                      e.printStackTrace();

                  }

              }

              private static void testRead() {

                  try {

                      File file = new File("f:/source.txt");

                      InputStreamReader in = new InputStreamReader(new FileInputStream(file), "utf-8");

                      char c1 = (char) in.read();

                      System.out.println("c1=" + c1);

                      //跳过2个字符

                      in.skip(2);

                      char c2 = (char) in.read();

                      System.out.println("c2=" + c2);

                      // 测试read(char[] cbuf, int off, int len)

                      char[] buf = new char[2];

                      in.read(buf, 0, buf.length);

                      System.out.println("buf=" + (new String(buf)));

                      //循环方式读取

                      int b;

                      while((b=in.read())!=-1){

                          System.out.println("@"+(char)b);

                      }

                      in.close();

                  } catch (IOException e) {

                      e.printStackTrace();

                  }

              }

     输出:

    source.txt里的内容:


    因为我这个source.txt就是用的utf-8编码,所以文件里面的内容不是乱码~~~ 

    BufferedReader、BufferedWriter和PrintWriter

    这三个流是处理字符串的,有了它们终于可以成行的读写了,欢呼~ 

             private static void testWrite() {

                  try {

                      File file = new File("f:/source.txt");

                      OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file), "utf-8");

                      PrintWriter pw = new PrintWriter(out);

                      //BufferedWriter bw = new BufferedWriter(out);

                      pw.println("我说我写的手都麻了你信么?");

                      pw.append("啊!");

                      pw.write("反正我信了!");

                      //bw.newLine();

                      //bw.write("O(∩_∩)O哈哈~");

                      pw.close();

                      //bw.close();

                  } catch (IOException e) {

                      e.printStackTrace();

                  }

              }

              private static void testRead() {

                  try {

                      File file = new File("f:/source.txt");

                      InputStreamReader in = new InputStreamReader(new FileInputStream(file), "utf-8");

                      BufferedReader br = new BufferedReader(in);

                      String str = "";

                      while((str=br.readLine())!=null){

                          System.out.println(str);

                      }

                      br.close();

                  } catch (IOException e) {

                      e.printStackTrace();

                  }

              }

    输出:


    只能算是简单的总结吧,写累了,不写了。 

    @font-face { font-family: "宋体"; }@font-face { font-family: "宋体"; }@font-face { font-family: "@宋体"; }@font-face { font-family: "Cambria"; }@font-face { font-family: "Monaco"; }p.MsoNormal, li.MsoNormal, div.MsoNormal { margin: 0cm 0cm 0.0001pt; text-align: justify; font-size: 12pt; font-family: Cambria; }a:link, span.MsoHyperlink { color: blue; text-decoration: underline; }a:visited, span.MsoHyperlinkFollowed { color: purple; text-decoration: underline; }.MsoChpDefault { font-family: Cambria; }div.WordSection1 { }

  • 相关阅读:
    项目游戏开发日记 No.0x000002
    项目游戏开发日记 No.0x000001
    项目游戏开发日记 No.0x00000
    需求获取常见的方法是进行客户访谈,结合你的实践谈谈会遇到什么问题,你是怎么解决的?
    当下大部分互联网创业公司为什么都愿意采用增量模型来做开发?
    迷茫踌躇的2018,整装待发的2019
    阿里云轻量应用服务器 搭建配置详解
    JS常用数组方法及实例
    使用CSS隐藏HTML元素的四种常用方法
    标签种类及CSS引入方法
  • 原文地址:https://www.cnblogs.com/coolgame/p/9016142.html
Copyright © 2020-2023  润新知