欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java IO流详解

程序员文章站 2024-03-05 14:48:19
...
1.Java IO原理
     IO流简单来说就是Input和Output流,IO流主要是用来处理设备之间的数据传输,Java对于数据的操作都是通过流实现,而java用于操作流的对象都在IO包中。
    流(Stream)是指从源节点到目标节点的数据流动。
    源节点和目标节点可以是文件、网络、内存、键盘、显示器等等。
          ① 源节点的数据流称为输入流(用来读取数据)。
          ② 目标节点的数据流称为输出流(用来写入数据)。

2  IO流的分类
     按流向不同: 输入流、输出流(以程序为主体判断)
     按数据不同: 字符流、字节流(字符流用于操作文本文件  .java  .txt    字节流用于操作非文本文件  .avi  .mp3  .jpg   .doc)

3.IO流的结构体系     
Java IO流详解                                       
4.实例:
(1) 使用节点流完成文本文件的复制
@Test
public void test1() {
     // 1. 创建 FileReader 对象,同时打开指定文件
     FileReader fr = null;
     // 2. 创建 FileWriter 对象,同时打开指定文件
     FileWriter fw = null;
     try {
          fr = new FileReader("1.txt");

          fw = new FileWriter("2.txt");

          // 3. 读取指定文件的内容
          char[] cbuf = new char[100];
          int len = 0;
          while ((len = fr.read(cbuf)) != -1) {
               // 4. 将指定内容写到目标地点
               fw.write(cbuf, 0, len);
          }
     } catch (IOException e) {
          e.printStackTrace();
     } finally {
          // 5. 关闭流
          if (fw != null) {
               try {
                    fw.close();
               } catch (IOException e) {
                    e.printStackTrace();
               }
          }

          if (fr != null) {
               try {
                    fr.close();
               } catch (IOException e) {
                    e.printStackTrace();
               }
          }
     }
}
(2) 使用缓冲流完成非文本文件的复制
@Test
public void test2() {
     // 2. 创建 BufferedInputStream 对象,包装对应的节点流
     BufferedInputStream bis = null;
     // 4. 创建 BufferedOutputStream 对象,包装对应的节点流
     BufferedOutputStream bos = null;
     try {
          // 1. 创建 FileInputStream 对象,同时打开指定文件
          FileInputStream fis = new FileInputStream(
                    "C:\\Users\\LEE\\Desktop\\1.flv");

          bis = new BufferedInputStream(fis);

          // 3. 创建 FileOutputStream 对象,同时打开指定文件
          FileOutputStream fos = new FileOutputStream(
                    "C:\\Users\\LEE\\Desktop\\2.flv");

          bos = new BufferedOutputStream(fos);

          // 5. 使用缓冲流读取指定文件内容
          byte[] b = new byte[1024];
          int len = 0;
          while ((len = bis.read(b)) != -1) {
               // 6. 将指定内容写到目标地点
               bos.write(b, 0, len);
          }
     } catch (IOException e) {
          e.printStackTrace();
     } finally {
          // 7. 关闭流
          if (bis != null) {
               try {
                    bis.close();
               } catch (IOException e) {
                    e.printStackTrace();
               }
          }

          if (bos != null) {
               try {
                    bos.close();
               } catch (IOException e) {
                    e.printStackTrace();
               }
          }
     }

}

5.对象流:  ObjectInputStream  &   ObjectOutputStream
(1) 序列化:将内存中的对象永久的以二进制形式保存到磁盘中
    ① 创建节点流对象
    ②(可选)可以使用 缓冲流包装,用于提高传输效率。
    ③ 创建对象流,包装节点流
    ④ 完成对象的序列化
    ⑤ 关闭流
    ⑥ 需要序列化对象的类要实现 java.io.Serializable 接口
    ⑦ 提供一个***  private static final long serialVersionUID = 1234566L;
@Test
public void test1() {
     Person p1 = new Person("张三", 18);
     Person p2 = new Person("李四", 20);

     ObjectOutputStream oos = null;
     try {
          FileOutputStream fos = new FileOutputStream("person.dat");
          BufferedOutputStream bos = new BufferedOutputStream(fos);
          oos = new ObjectOutputStream(bos);

          oos.writeObject(p1);
          oos.writeObject(p2);
     } catch (IOException e) {
          e.printStackTrace();
     } finally {
          if (oos != null) {

               try {
                    oos.close();
               } catch (IOException e) {
                    e.printStackTrace();
               }
          }
     }}

//注意: transient 和 static 修饰的属性不能被序列化
(2) 反序列化:将磁盘中保存的对象读取
//对象的反序列化
@Test
public void test2(){
     ObjectInputStream ois = null;
     try {
          FileInputStream fis = new FileInputStream("person.dat");
          ois = new ObjectInputStream(fis);

          Person p1 = (Person) ois.readObject();
          Person p2 = (Person) ois.readObject();

          System.out.println(p1);
          System.out.println(p2);
     } catch (ClassNotFoundException e) {
          e.printStackTrace();
     } catch (IOException e) {
          e.printStackTrace();
     } finally {
          if(ois != null){
               try {
                    ois.close();
               } catch (IOException e) {
                    e.printStackTrace();
               }
          }
     }

}
说明:
    有的属性不需要序列化用transient修饰就可以了,但是并不表示该元素不会进行JVM默认的序列化,也可以自己完成元素的序列化。
    对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类构造器会被调用。
(3) transient的作用及使用方法
    我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。
    然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
    总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

6.转换流: InputStreamReader & OutputStreamWriter
     编码: 字符串  -> 字节数组
     解码: 字节数组  -> 字符串
@Test
public void test3() {
     BufferedReader br = null;
     try {
          InputStream in = System.in;
          InputStreamReader isr = new InputStreamReader(in);
          br = new BufferedReader(isr);

          String str = null;
          while ((str = br.readLine()) != null) {
               System.out.println("--" + str);
          }
     } catch (IOException e) {
          e.printStackTrace();
     } finally {
          if (br != null) {
               try {
                    br.close();
               } catch (IOException e) {
                    e.printStackTrace();
               }
          }
     }
}

7.java.io.File 类:
     用于描述文件或目录。 可以对文件或目录进行一些基本操作,如: 新建、删除、重命名等
     但是若需要操作文件的内容 File 类将无能为力,需要使用IO流,通常将File类对象与IO流配合使用。    
@Test
public void test4(){
     FileReader fis = null;
     try {
          fis = new FileReader(new File("1.txt"));

          char[] cs = new char[100];
          int len = 0;
          while((len = fis.read(cs)) != -1){
               System.out.print(new String(cs, 0, len));
          }
     } catch (IOException e) {
          e.printStackTrace();
     } finally {
          if(fis != null){
               try {
                    fis.close();
               } catch (IOException e) {
                    e.printStackTrace();
               }
          }
     }
}