Java中的IO流

    xiaoxiao2021-03-25  149

    流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备之间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

    从不同的角度对流可以分为以下几类:

    1、输入流和输出流

       输入流:只能从文件中读取数据,而不能向其中写入数据。    输出流:只能向文件中写入数据,而不能读取。    如从服务器通过网络传送数据到客户端,Server端的内存负责将数据输出到网络上,因此Server端的程序使用的是输出流。Client端的内存负责从网络上读取数据,因此Client端的程序使用的是输入流。 2、字节流和字符流    引用(http://www.2cto.com/kf/201312/262036.html)     字符流的由来:因为数据编码的不同,而有了对字符进行高效操作的流对象。本质就是基于字节流读取时,去查了指定的码表。     字符流和字节流的而不同点:     1、读取单位不同:字节流以字节byte(8bit)为单位,字符流以十六位的字符操作单位。     2、处理对象不同:字节流能处理所有类型的数据(如图片、视频等),而字符流只能处理字符类型的数据。     3、字节流在操作的时候本身是不会用到缓冲区的,是对文件本身进行直接操作;而字符流在操作的时候会用到缓冲区,是通过缓冲区来操作文件。     结论:优先选用字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容,但是字符只是在内存中才会形成的,所以在开发中,字节流使用广泛。     规律:后缀是Stream的都是字节流,后缀是Reader、Writer的是字符流。 3、节点流和处理流     按照角色进行分类。     可以直接的向一个IO设备(磁盘/网络)读/写数据的流就是节点流,也被称之为低级流。     处理流用于对已存在的流记性连接和封装,通过封装后的流实现数据的读/写功能,也被称作高级流。 java中的流是通过四个基类派生而来: InputStream(字节输入流)  Reader(字符输入流) :所有输入流的基类。 OutputStream(字节输出流)  Writer(字符输出流) :所有输出流的基类。 具体分析各种流: 1、输入字节流 InputStream InputStream是所有的输入字节流的父类,它是一个抽象类。 ByteArrayInputStream、StringBufferInputStream、FileInputStream是三种基本的介质流,他们分别从Byte数组、StringBuffer和本地文件中读取数据。 实例代码:读取文件中的内容:

    FileInputStream:

    [java] view plain copy print ? package com.basic.file;    import java.io.File;  import java.io.FileInputStream;  import java.io.FileNotFoundException;  import java.io.IOException;    public class FileInputStreamDemo {      public static void main(String[] args) {          File file=new File("c:\\a.txt");          FileInputStream fis=null         try             //创建文件输入字节流              fis=new FileInputStream(file);              //创建一个用于缓存字节数组              byte[] by=new byte[1024];              //定义一个int型变量,用于记录读入的字节数              int len=0             //循环获取数据              while((len=fis.read(by))!=-1){                  //把字节数组转换成字符串输出                  System.out.println(new String(by,0,len));              }          } catch (FileNotFoundException e) {              e.printStackTrace();          } catch (IOException e) {              e.printStackTrace();          }finally             if(fis!=null){                  try                     fis.close();                  } catch (IOException e) {                      e.printStackTrace();                  }              }          }      } 

    代码中by的字节长度为1024,如果文件较小的话,则会造成浪费空间,我们需要文件的准确大小,这是我们可以把 byte[] by=new byte[1024];===>byte[] by=new byte[(int) file.length()]; 按字节读取文件中的内容:

    代码示例:

    [java] view plain copy print ? package com.basic.file;  import java.io.File;  import java.io.FileInputStream;  import java.io.IOException;  public class FileInputStreamDemo {      public static void main(String[] args) throws IOException {          File file=new File("c:\\a.txt");          FileInputStream fis=null         fis=new FileInputStream(file);          byte[] by=new byte[(int) file.length()];          int len=0         int count=0         while((len=fis.read(by))!=-1){              by[count++]=(byte) fis.read();              System.out.println(new String(by));              if(fis!=null){                  fis.close();              }          }      }  2、输出字节流 OutputStream OutputStream是所有输出字节流的父类,它也是一个抽象类。ByteArrayOutputStream、FileOutputStream是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。

    向文件中写入字符串的代码示例: 代码示例:

    [java] view plain copy print ? package com.basic.file;  import java.io.File;  import java.io.FileNotFoundException;  import java.io.FileOutputStream;  import java.io.IOException;  public class FileOutputStreamDemo {      public static void main(String[] args) {          File file=new File("c:\\b.txt");          FileOutputStream fos=null         try             fos=new FileOutputStream(file);              fos.write("哈哈哈哈哈哈哈哈".getBytes());              fos.flush();          } catch (FileNotFoundException e) {              e.printStackTrace();          } catch (IOException e) {              e.printStackTrace();          }finally             if(fos!=null){                  try                     fos.close();                  } catch (IOException e) {                      e.printStackTrace();                  }              }          }      }  输入字节流读取文件的步骤: 1、创建一个输入文件字节流的对象。 2、创建一个字节数组用于缓存数据。 3、创建一个用于保存读取字节数的变量。 4、循环读取数据。 5、把字节数组转换成字符串等格式。 6、关闭流。 输出字节流写入文件的步骤: 1、创建一个输出文件字节流对象。 2、准备数据源,把数据源转换成字节数组。 调用write方法,把数据源内容写入到输出流当中。 4、刷新流。 5、关闭流。 利用字节输入流和字节输出流进行文件的复制: 代码示例:

    [java] view plain copy print ? package com.basic.file;    import java.io.File;  import java.io.FileInputStream;  import java.io.FileNotFoundException;  import java.io.FileOutputStream;  import java.io.IOException;    public class CopyDemo1 {      public static void main(String[] args) {          copy(new File("c:\\a.txt"),new File("c:\\b.txt"));      }      public static void copy(File srcFile,File destFile){          FileInputStream fis=null         FileOutputStream fos=null         try             fis=new FileInputStream(srcFile);              fos=new FileOutputStream(destFile);              byte[] by=new byte[1024];              int len=0             while((len=fis.read(by))!=-1){                  fos.write(by, 0, len);                  fos.flush();              }          } catch (FileNotFoundException e) {              e.printStackTrace();          } catch (IOException e) {              e.printStackTrace();          }finally             try                 fos.close();                  fis.close();              } catch (IOException e) {                  e.printStackTrace();              }          }      } 

    3、字符输入流 Reader Reader是所有的输入字符流的父类,它是一个抽象类。 CharReader、StringReader是两种介质流,它们分别将Char数组和String中读取数据。 BufferedReader为Reader提供缓冲功能。 4、字符输出流 Writer Writer 是所有的输出字符流的父类,它是一个抽象类。BufferedWriter 是一个装饰器为Writer 提供缓冲功能。

    节点流处于io操作第一线,所有的操作必须通过它来进行,处理流对于其他流进行操作(提高效率和操作灵活性)。 处理流不断地增大了处理的范围,对于其他流的处理提高了性能、效率和操作的灵活性。 处理流中的分类: 一:缓冲流 1、字节缓冲流    BufferedInputStream    BufferedOutputStream 2、字符缓冲流    BufferedReader    BufferedWriter

       BufferedInputStream实现的原理:    其中有一个缓存区间,默认大小为8kb,每次调用read方法时,会先尝试从缓存区当中获取内容,如果读取失败就说明缓存区没有数据,然后把这些字节放入放入缓存区当中,最后再将缓存区的内容或者全部缓存给用户,直接从缓存区读取数据会比直接从数据源读取数据的速度快,所以效率更高,性能更好。    如果没有缓冲区,read()没执行一次,就会发送一次I/O操作。 二:转换流 作用:将字节流转换成字符流,乱码、编码和解码的问题。 1、编码和解码的概念: 解码就是二进制的内容通过解码字符集转换成字符的过程。 编码就是字符通过编码字符集转换成二进制内容的过程。 乱码出现的原因: 1、编码和解码的字符集不统一。 2、字节的缺少,长度的丢失。 三:内存流或者字节数组流     ByteArrayInputStream    字节数组输入流     ByteArrayOutputStream   字节数组输出流 四:数据处理流     DataInputStream     DataOutputStream     既能保存数据,又能保存数据类型。     只能保留基本类型+String 五:序列化流     ObjectInputStream     ObjectOutputStream 保留引用数据(对象)  数据+类型 序列化和反序列化 序列化:将对象保存在文件里或者保存在字节数组当中。       把对象转换为字节序列的过程称为对象的序列化。 反序列化:将文件或者字节数组转换成对象。        将字节序列恢复成对象的过程称为对象的反序列化。 注意: 1、先序列化再反序列化,反序列化的顺序必须和序列化的顺序相同。 2、不是所有的对象都可以被序列化,只有实现了Serializable这个接口的类才可以被序列化。 3、不是所有的属性都需要被序列化,用transient修饰。 对象序列化的功能: 1、把对象的字节序列永远的保存在硬盘上,通常会存放在一个文件中。 2、在网络上传送对象的自己序列。 反序列化:  输入流 objectInputStream 序列化:    输出流 objectOutputStream

    对于I/O流这块,刚学的时候脑子里感觉都乱成一锅粥了,总结以下,感觉清晰了好多。

    转载请注明原文地址: https://ju.6miu.com/read-10721.html

    最新回复(0)