转换流和打印流

136 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第29天,点击查看活动详情

转换流InputStreamReader和OutputStreamWriter

介绍

(1)InputStreamReader:Reader的子类,可以将InputStream(字节流)包装(转换)成Reader(字符流)。

(2)OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装(转换)成Writer(字符流)。

(3)当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流。

(4)可以在使用时指定编码格式(比如utf-8、gbk)等。

InputStreamReader

InputStreamReader (Java Platform SE 6)

InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。

为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:

 BufferedReader in
   = new BufferedReader(new InputStreamReader(System.in));

OutputStreamWriter

OutputStreamWriter (Java Platform SE 6)

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。可以指定此缓冲区的大小,不过,默认的缓冲区对多数用途来说已足够大。注意,传递给 write() 方法的字符没有缓冲。

为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。例如:

 Writer out
   = new BufferedWriter(new OutputStreamWriter(System.out));

应用案例

(1)编程将字节流FileInputStream包装成(转换成)字符流InputStreamReader,对文件进行读取(按照utf-8/gbk格式),进而在包装成BufferedReader。

import java.io.*;
public class InputStreamReader_ {
    public static void main(String[] args) throws IOException {
        String filePath = "e:\\a.txt";

        //1. 把 FileInputStream 转成 InputStreamReader
        
        //2. 指定编码 gbk
        //InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");
        
        //3. 把 InputStreamReader 传入 BufferedReader
        //BufferedReader br = new BufferedReader(isr);
        //将 2 和 3 合在一起
        BufferedReader br = new BufferedReader(new InputStreamReader(
        new FileInputStream(filePath), "gbk"));
        
        //4. 读取
        String s = br.readLine();
        System.out.println("读取内容=" + s);
        
        //5. 关闭外层流
        br.close();
    }
}

(2)编程将字节流FileOutputStream包装成(转换成)字符流OutputStreamWriter,对文件进行写入(按照gbk格式,也可以使用其他格式,比如utf-8)

// 1.创建流对象
OutputStreamWriter osw =
new OutputStreamWriter(new FileOutputStream("d:\\a.txt"), "gbk");

// 2.写入
osw.write("hello,周小末~");

// 3.关闭
osw.close();
System.out.println("保存成功~");

打印流PrintStream和PrintWriter

PrintStream

PrintStream (Java Platform SE 6)

PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。它还提供其他两项功能。与其他输出流不同,PrintStream 永远不会抛出 IOException;而是,异常情况仅设置可通过 checkError 方法测试的内部标志。另外,为了自动刷新,可以创建一个 PrintStream;这意味着可在写入 byte 数组之后自动调用 flush 方法,可调用其中一个 println 方法,或写入一个换行符或字节 ('\n')。

PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。

PrintWriter

PrintWriter (Java Platform SE 6)

向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream"java.io 中的类") 中的所有 print 方法。它不包含用于写入原始字节的方法,对于这些字节,程序应该使用未编码的字节流进行写入。

PrintStream 类不同,如果启用了自动刷新,则只有在调用 printlnprintfformat 的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。这些方法使用平台自有的行分隔符概念,而不是换行符。

此类中的方法不会抛出 I/O 异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用 checkError() 是否出现错误。

应用案例

//演示PrintWriter
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class PrintWriter_ {
    public static void main(String[] args) throws IOException {
        //PrintWriter printWriter = new PrintWriter(System.out);
        PrintWriter printWriter = new PrintWriter(new FileWriter("e:\\f2.txt"));
        package com.hspedu.printstream;
        
        
        
//演示PrintStream
import java.io.IOException;
import java.io.PrintStream;

public class PrintStream_ {
    public static void main(String[] args) throws IOException {
        PrintStream out = System.out;
        //在默认情况下,PrintStream 输出数据的位置是 标准输出,即显示器
        /*
            public void print(String s) {
                if (s == null) {
                    s = "null";
                }
                write(s);
            }
        */
        
        out.print("john, hello");
        //因为 print 底层使用的是 write , 所以我们可以直接调用 write 进行打印/输出
        out.write("周小末".getBytes());
        out.close();
        
        //我们可以去修改打印流输出的位置/设备
        //1. 输出修改成到 "e:\\f1.txt"
        //2. "hello, 周小末" 就会输出到 e:\f1.txt
        //3. public static void setOut(PrintStream out) {
                // checkIO();
                // setOut0(out); // native 方法,修改了 out
            // }
            
        System.setOut(new PrintStream("e:\\f1.txt"));
        System.out.println("hello, 周小末");
    }
}

        printWriter.print("hi, 北京你好~~~~");
        printWriter.close();//flush + 关闭流, 才会将数据写入到文件..
    }
}