IO流【转换流、字符输出流、数据流、对象流】(三)-全面详解(学习总结---从入门到深化)

简介: IO流【转换流、字符输出流、数据流、对象流】(三)-全面详解(学习总结---从入门到深化)

转换流


InputStreamReader/OutputStreamWriter用来实现将字节流转化
成字符流。


通过转换流解决乱码


ANSI(American National Standards Institute)美国国家标准协会

public class TestInputStreamReader {
    public static void main(String[] args) {
        //创建文件字节输入流对象
        try(FileInputStream fis = new FileInputStream("d:/sxt.txt");
            //创建转换流(字节到字符的转换)流对象,并在该对象中指定编码。
            InputStreamReader isr = new InputStreamReader(fis,"gbk")){
            StringBuilder sb = new StringBuilder();
            //操作流对象
            int temp = 0;
            while((temp = isr.read()) != -1)
           {
                sb.append((char) temp);
           }
            System.out.println(sb);
       }catch(IOException e){
            e.printStackTrace();
       }
   }
}


通过转换流实现键盘输入屏幕输出

import java.io.*;
public class TestConvertStream {
    public static void main(String[] args) {
    // 创建字符输入和输出流:使用转换流将字节流转换成字符流
    BufferedReader br = null;
    BufferedWriter bw = null;
 try {
      br = new BufferedReader(new InputStreamReader(System.in));
      bw = new BufferedWriter(new OutputStreamWriter(System.out));
      // 使用字符输入和输出流
     String str = br.readLine();
     // 一直读取,直到用户输入了exit为止
     while (!"exit".equals(str)) {
     // 写到控制台
    bw.write(str);
    bw.newLine();// 写一行后换行
    bw.flush();// 手动刷新
    // 再读一行
    str = br.readLine();
   }
 } catch (IOException e) {
     e.printStackTrace();
 } finally {
 // 关闭字符输入和输出流
 if (br != null) {
    try {
         br.close();
       } catch (IOException e) {
      e.printStackTrace();
     }
 }
 if (bw != null) {
 try {
      bw.close();
     } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }
 }
}


通过字节流读取文本文件并添加行号

public class TestLineNumber2 {
    public static void main(String[] args) {
   //创建字符输入缓冲流、输入字节到字符转换流、文件字节输入流对象
        try(BufferedReader br = new BufferedReader(new InputStreamReader(new
FileInputStream("d:/sxt.txt")));
            //创建字符输出缓冲流、输出字符到字节转换流、文件字节输出流对象
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new
FileOutputStream("d:/sxt4.txt")))){
            //操作流
            String temp = "";
            //序号变量
            int i = 1;
            //按照行读取
            while((temp = br.readLine()) != null){
                bw.write(i+","+temp);
                //换行
                bw.newLine();
                //序号累加
                i++;
           }
            //刷新
            bw.flush();
       }catch(IOException e){
            e.printStackTrace();
       }
   }
}


通过转换流实现键盘输入屏幕输出


System.in是字节流对象,代表键盘的输入。

System.out是字节流对象,代表输出到屏幕。

public class TestKeyboardInput {
    public static void main(String[] args) {
           //创建键盘输入相关流对象
        try(BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
           //创建向屏幕输出相关流对象
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))){
            while(true){
                bw.write("请输入:");
                bw.flush();
                //获取键盘输入的字符串
                String input = br.readLine();
                //判断输入的内容是否含有退出关键字。
                if("exit".equals(input) || "quit".equals(input)){
                    bw.write("Bye Bye !");
                    bw.flush();
                    break;
               }
            //将读取到键盘输入的字符串,输出到屏幕。
                bw.write("您输入的是:"+input);
                bw.newLine();
                bw.flush();
           }
       }catch(IOException e){
            e.printStackTrace();
       }
   }
}


字符输出流


在Java的IO流中专门提供了用于字符输出的流对象PrintWriter。该 对象具有自动行刷新缓冲字符输出流,特点是可以按行写出字符 串,并且可通过println();方法实现自动换行。

public class TestPrintWriter {
   public static void main(String[] args) {
         //创建字符输出流对象
        try(PrintWriter pw = new PrintWriter("d:/sxt5.txt")){
            //调用不带换行方法完成内容的输出
            pw.print("abc");
            pw.print("def");
            //调用带有自动换行方法完成内容的输出
            pw.println("Oldlu");
            pw.println("sxt");
            pw.flush();
       }catch(IOException e){
            e.printStackTrace();
       }
   }
}


通过字符输出流添加行号

public class TestLineNumber3 {
    public static void main(String[] args) {
        //创建字符输入缓冲流对象与文件字符输入流对象
        try(BufferedReader br = new BufferedReader(new FileReader("d:/sxt.txt"));
            //创建字符输出流对象
            PrintWriter pw = new PrintWriter("d:/sxt6.txt")){
            //操作流
            String temp = "";
            //定义序号变量
            int i = 1;
            while((temp = br.readLine()) != null){
                pw.println(i+","+temp);
                //序号累加
                i++;
           }
            //刷新
            pw.flush();
       }catch(IOException e){
            e.printStackTrace();
       }
   }
}


数据流


数据流将“基本数据类型与字符串类型”作为数据源,从而允许程序 以与机器无关的方式从底层输入输出流中操作Java基本数据类型与 字符串类型。 DataInputStream和DataOutputStream提供了可以存取与机器无 关的所有Java基础类型数据(如:int、double、String等)的方 法。

public class TestDataStream {
    public static void main(String[] args) {
        //创建数据输出流对象与文件字节输出流对象
        try(DataOutputStream dos = new DataOutputStream(new FileOutputStream("d:/data"));
           //创建数据输入流对象与文件字节输入流对象
           DataInputStream dis = new DataInputStream(new FileInputStream("d:/data"))){
            //将如下数据写入到文件中
            dos.writeChar('a');
            dos.writeInt(10);
            dos.writeDouble(Math.random());
            dos.writeBoolean(true);
            dos.writeUTF("山东聊城");
            //手动刷新缓冲区:将流中数据写入到文件中
            dos.flush();
            //直接读取数据:读取的顺序要与写入的顺序一致,否则不能正确读取数据。
            System.out.println("char: " + dis.readChar());
            System.out.println("int: " + dis.readInt());
            System.out.println("double: " + dis.readDouble());
            System.out.println("boolean: " + dis.readBoolean());
            System.out.println("String: " + dis.readUTF());
       }catch(IOException e){
            e.printStackTrace();
       }
   }
}


Oldlu提示: 使用数据流时,读取的顺序一定要与写入的顺序一致,否则不 能正确读取数据。


对象流


我们前边学到的数据流只能实现对基本数据类型和字符串类型的读 写,并不能读取对象(字符串除外),如果要对某个对象进行读写 操作,我们需要学习一对新的处理流:

ObjectInputStream/ObjectOutputStream。


处理基本数据类型数据


ObjectInputStream/ObjectOutputStream处理基本数据类型。

public class TestObjectStreamBasicType {
    public static void main(String[] args) {
            //创建对象输出流对象与文件字节输出流对象
        try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:/data2"));
           //创建对象输入流对象与文件字节输入流对象
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/data2"))){
            //将如下数据写入到文件中
            oos.writeInt(10);
            oos.writeDouble(Math.random());
            oos.writeChar('a');
            oos.writeBoolean(true);
            oos.writeUTF("你好,山东聊城");
            oos.flush();
            //必须要按照写入的顺序读取数据
            System.out.println("int: "+ois.readInt());
            System.out.println("double: "+ois.readDouble());
            System.out.println("char: "+ois.readChar());
            System.out.println("boolean: "+ois.readBoolean());
            System.out.println("String: "+ois.readUTF());
       }catch(IOException e){
            e.printStackTrace();
       }
   }
}


注意


1、对象流不仅可以读写对象,还可以读写基本数据类型。

2、读写基本数据类型时,读取的顺序一定要与写入的顺序一致,否则不能正确读取数据。


复习:


IO流技术介绍


什么是IO


输入(Input)指的是:可以让程序从外部系统获得数据(核心含义是 “读”,读取外部数据)。 输出(Output)指的是:程序输出数据给外部系统从而可以操作外部 系统(核心含义是“写”,将数据写出到外部系统)。 java.io包为我们提供了相关的API,实现了对所有外部系统的输入输 出操作,这就是我们这章所要学习的技术。


什么是数据源


数据源data source,提供数据的原始媒介。常见的数据源有:数据 库、文件、其他程序、内存、网络连接、IO设备。如图所示。


数据源分为:源设备、目标设备。


1 源设备:为程序提供数据,一般对应输入流。

2 目标设备:程序数据的目的地,一般对应输出流。


流的概念


流是一个抽象、动态的概念,是一连串连续动态的数据集合。 对于输入流而言,数据源就像水箱,流(stream)就像水管中流动着 的水流,程序就是我们最终的用户。我们通过流(A Stream)将数 据源(Source)中的数据(information)输送到程序 (Program)中。 对于输出流而言,目标数据源就是目的地(dest),我们通过流(A Stream)将程序(Program)中的数据(information)输送到目 的数据源(dest)中。


流与源数据源和目标数据源之间的关系:


Oldlu提示

输入/输出流的划分是相对程序而言的,并不是相对数据源。


第一个简单的IO流程序


当程序需要读取数据源的数据时,就会通过IO流对象开启一个通向 数据源的流,通过这个IO流对象的相关方法可以顺序读取数据源中 的数据。

使用流读取文件内容(不规范的写法,仅用于测试)

import java.io.*;
public class TestI01 {
 public static void main(String[] args) {
 try {
 //创建输入流
 FileInputStream fis = new FileInputStream("d:/a.txt"); // 文件内容是:abc
 //一个字节一个字节的读取数据
 int s1 = fis.read(); // 打印输入字符a对应的ascii码值97
 int s2 = fis.read(); // 打印输入字符b对应的ascii码值98
 int s3 = fis.read(); // 打印输入字符c 对应的ascii码值99
 int s4 = fis.read(); // 由于文件内容已经读取完毕,返回-1
 System.out.println(s1);
 System.out.println(s2);
 System.out.println(s3);
 System.out.println(s4);
 // 流对象使用完,必须关闭!不然,总占用系统资源,最终会造成系统崩溃!
   fis.close();
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}


以上案例我们要注意以下几点:


1、我们读取的文件内容是已知的,因此可以使用固定次数的“int s= fis.read();”语句读取内容,但是在 实际开发中通常我们根本不知道文件的内容,因此我们在读取的时候需要配合while循环使用。

2、 为了保证出现异常后流的正常关闭,通常要将流的关闭语句要放到finally语句块中,并且要判断流 是不是null。


IO流的经典写法


使用流读取文件内容(经典代码,一定要掌握)

import java.io.*;
public class Test2 {
 public static void main(String[] args) {
 FileInputStream fis = null;
 try {
       fis = new FileInputStream("d:/a.txt"); // 内容是:abc
       StringBuilder sb = new StringBuilder();
       int temp = 0;
      //当temp等于-1时,表示已经到了文件结尾,停止读取
      while ((temp = fis.read()) !=-1) {
         sb.append((char) temp);
     }
         System.out.println(sb);
 } catch (Exception e) {
         e.printStackTrace();
 } finally {
 try {
 //这种写法,保证了即使遇到异常情况,也会关闭流对象。
 if (fis != null) {
      fis.close();
     }
  } catch (IOException e) {
      e.printStackTrace();
    }
   }
 }
}


IO流新语法经典写法


在JDK7以及以后的版本中可以使用try-with-resource语法更优雅的 关闭资源。

java.lang.AutoCloseable接口: 在java.lang.AutoCloseable接口中包含了一个close方法,该方法用 于关闭资源。 只要是实现了java.lang.AutoCloseable接口的对象,都可以使用 try-with-resource关闭资源。 使用最新的try-with-resource简化(经典代码,一定要掌握)

public class Test3 {
    public static void main(String[] args) {
        //使用try-with-resource方式关闭资源。
        //在try中打开资源,不需要在代码中添加finally块关闭资源。
        try(FileInputStream fis = new FileInputStream("d:/a.txt");){
            StringBuilder sb = new StringBuilder();
            int temp=0;
            while((temp = fis.read()) != -1)
           {
                sb.append((char) temp);
           }
            System.out.println(sb);
       }catch(Exception e){
            e.printStackTrace();
       }
   }


Oldlu建议 如上代码是一段非常典型的IO流代码,其他流对象的使用也 基本是同样的模式!

目录
相关文章
|
3月前
|
存储 Java 数据安全/隐私保护
从零开始学习 Java:简单易懂的入门指南之IO字符流(三十一)
从零开始学习 Java:简单易懂的入门指南之IO字符流(三十一)
|
3月前
|
存储 移动开发 Java
从零开始学习 Java:简单易懂的入门指南之IO字节流(三十)
从零开始学习 Java:简单易懂的入门指南之IO字节流(三十)
|
3月前
|
存储 网络协议 Java
Java学习—IO流
Java学习—IO流
|
3月前
|
存储 算法 Java
从零开始学习 Java:简单易懂的入门指南之IO序列化、打印流、压缩流(三十三)
从零开始学习 Java:简单易懂的入门指南之IO序列化、打印流、压缩流(三十三)
|
3月前
|
分布式计算 Java 大数据
IO流【Java对象的序列化和反序列化、File类在IO中的作用、装饰器模式构建IO流体系、Apache commons-io工具包的使用】(四)-全面详解(学习总结---从入门到深化)
IO流【Java对象的序列化和反序列化、File类在IO中的作用、装饰器模式构建IO流体系、Apache commons-io工具包的使用】(四)-全面详解(学习总结---从入门到深化)
51 0
|
3月前
|
存储 自然语言处理 Java
从零开始学习 Java:简单易懂的入门指南之IO缓冲流、转换流(三十二)
从零开始学习 Java:简单易懂的入门指南之IO缓冲流、转换流(三十二)
|
3月前
|
缓存 Java
IO流【Java中IO的四大抽象类、常用流详解 、 缓冲字节流、 文件字符流、缓冲字符流】(二)-全面详解(学习总结---从入门到深化)
IO流【Java中IO的四大抽象类、常用流详解 、 缓冲字节流、 文件字符流、缓冲字符流】(二)-全面详解(学习总结---从入门到深化)
36 0
IO流【Java中IO的四大抽象类、常用流详解 、 缓冲字节流、 文件字符流、缓冲字符流】(二)-全面详解(学习总结---从入门到深化)
|
30天前
|
存储 Java 数据处理
|
1月前
|
Java API
java中IO与NIO有什么不同
java中IO与NIO有什么不同
|
3月前
|
存储 Java Android开发
IO流:java中解码和编码出现乱码说明及代码实现
IO流:java中解码和编码出现乱码说明及代码实现