Java基础教程——转换流

转换流

通常,Window默认的编码方式是GBK,Java项目一般建议设为UTF-8编码。这时候读取文件可能出现乱码。事实上实际应用中编码格式不匹配的场景非常多。

转换流可以指定编码方式,用于解决乱码问题。

OutputStreamWriter
InputStreamReader

字符编码:Character Encoding:自然语言的字符,与二进制数之间的对应规则。
文件流读取时使用的编码方式和文件本身编码方式不同时,会造成读取出来时出现乱码。

字符集 :Charset:系统支持的所有字符的集合,包括数字、文字、标点符号、图形符号等。一套字符集至少有一套字符编码。常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。

ASCII字符集
|--ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)。
|--|--基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符。
|--|--ASCII的扩展字符集使用8位(bits)表示一个字符,共256字符,方便支持欧洲常用字符。

ISO-8859-1字符集
|--拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等。
|--ISO-8859-1使用单字节编码,兼容ASCII编码。

GBxxx字符集:GB乃“国标”之意,是为了显示中文而设计的一套字符集。
|--GB2312:简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时,就表示一个汉字,大约包含7000多个简体汉字,还有数学符号、希腊字母、日文假名,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这便是所谓的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。
|--GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩文字等。Windows操作系统默认使用GBK编码。
|--GB18030:最新的中文码表。收录汉字7万多个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。

Unicode字符集
Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国
码。
有三种编码方案,UTF-8、UTF-16和UTF-32。最为常用的UTF-8编码。
|--UTF-8,可以用来表示Unicode标准中任何字符,它是电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。
UTF-8使用1至4个字节为进行编码(最大可占用6字节),编码规则:

  1. 128个ASCII字符,一个字节编码。
  2. 拉丁文等字符,两个字节编码。
  3. 大部分常用字(含中文),使用三个字节编码,基本等同于GBK。
  4. 还有一些字符使用四字节编码。

参考【utf-8中的汉字占用多少字节】:https://www.cnblogs.com/zxz1987/articles/6544593.html

看看UTF-8编码占了几个字节:

public class TestCharEncoding {
    public static void main(String[] args) throws Exception {
        String[] strArr = { "A", "Ω", "壹" };
        for (String s : strArr) {
            System.out.println("s:" + s.getBytes("utf-8").length);
        }
    }
}

运行结果

s:1
s:2
s:3


示例代码:转换流可以读写各种编码的文件,而纯字符流则可能读出乱码。

  • 使用FileInputStream类读取文件流,
  • 利用InputStreamReader将字节流转化为字符流,同时指定文件流的编码方式,
  • 再将字符流放入 BufferedReader中进行操作。

File → FileOutputStream → OutputStreamWriter(指定编码) → BufferedWriter

File → FileInputStream → InputStreamReader(指定编码) → BufferedReader

package ahjava.io;
import java.io.*;
public class 转换流 {
    public static final String FILE_NAME = "testMessyCode.txt";
    public static final String CHARSET_NAME = "gbk";
    // File->FileOutputStream->OutputStreamWriter(指定编码)->BufferedWriter
    static void write(String msg) throws Exception {
        File f = new File(FILE_NAME);
        FileOutputStream fos = new FileOutputStream(f);
        OutputStreamWriter osw = new OutputStreamWriter(fos, CHARSET_NAME);
        BufferedWriter bw = new BufferedWriter(osw);
        bw.write(msg);
        // 关闭流(写文件的关闭顺序如果不对,会抛异常,读文件没有影响)
        bw.close();
        osw.close();
        fos.close();
    }
    // File->FileInputStream->InputStreamReader(指定编码)->BufferedReader
    static void read() throws Exception {
        File f = new File(FILE_NAME);
        FileInputStream fis = new FileInputStream(f);
        InputStreamReader isr = new InputStreamReader(fis, CHARSET_NAME);
        BufferedReader br = new BufferedReader(isr);
        String str;
        while ((str = br.readLine()) != null) // 逐行读取数据
        {
            System.out.println(CHARSET_NAME + "读取:" + str);
        }
        // 关闭流
        br.close();
        isr.close();
        fis.close();
    }
    static void 纯字符流R_就怕货比货() {
        File file = new File(FILE_NAME);
        FileReader fr;
        try {
            fr = new FileReader(file);
            BufferedReader br = new BufferedReader(fr);
            String str;
            while ((str = br.readLine()) != null) {
                System.out.println("纯字符流读取:" + str);
            }
            br.close();
            fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws Exception {
        write("乱码?");
        纯字符流R_就怕货比货();
        read();
    }
}

*控制台输入

场景:控制台输入文字,写入文件。
通常建议把Java工程设为UTF-8编码。这时候如果写文件,文件是UTF-8编码。
然而,Windows平台默认的编码方式是GBK,可以通过转换流以GBK的编码方式写文件。
以下代码就是以GBK的编码格式把用户在控制台的输入写入文件。

import java.io.*;
public class 控制台输入 {
    public static void main(String[] args) throws IOException {
        控制台写入文件();
    }
    static void 控制台写入文件() throws IOException {
        /* 本例从控制台接受输入,然后写入到文件中,直到用户输入"!!!"为止 */
        // 输出:FileOutputStream->OutputStreamWriter(指定编码)->BufferedWriter
        FileOutputStream fos = new FileOutputStream("控制台写入文件.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
        BufferedWriter bw = new BufferedWriter(osw);
        // 输入:System.in(字节流)->InputStreamReader->BufferedReader
        // 将控制台输入对象转化成字符流,并建立缓冲流
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);
        String str = br.readLine(); // 接受从控制台输入的一行字符串
        while (!(str.equals("!!!"))) // 如果输入"!!!"则代表输入结束
        {
            bw.write(str); // 将从控制台输入的字符串写入到文件中
            bw.newLine(); // 换新行
            str = br.readLine(); // 再从控制台接受输入
        }
        // 关闭输入相关的流
        br.close();
        isr.close();
        // 关闭输出相关的流
        bw.close();
        osw.close();
        fos.close();
    }
}

*想想,“控制台写入文件()”方法,能不能连续调用两次?

原文地址:https://www.cnblogs.com/tigerlion/p/11179229.html

时间: 2024-08-28 21:34:38

Java基础教程——转换流的相关文章

java基础 关于转换流

转换流有两种:InputStreamReader:将字节流转换为字符流 OutputStreamWriter:将字符流转换为字节流 什么时候使用转换流?由以下分析: 流对象很多,首先要明确那个流对象. 通过三点来完成: 1.明确源和目的 源:输入流.InputStream Reader 目的:输出流. OutputStream Writer 2.操作的数据是否是纯文本. 是:字符流 否:字节流 3.当体系明确后,再明确要使用哪个具体的对象. 通过设备来进行区分: 源设备:内存,硬盘,键盘 目的设

Java基础教程——字符流

字符流 字节流服务文本文件时,可能出现中文乱码.因为一个中文字符可能占用多个字节. 针对于非英语系的国家和地区,提供了一套方便读写方式--字符流. java.io.Reader java.io.Writer 文件字符流 |-读文件:FileReader java.io.FileReader fr = new FileReader("待读取的文件");// 构造时使用默认的字符编码 int 读取单个字符 = fr.read(); char[] cbuf = new char[1024];

Java基础教程——缓冲流

缓冲流 "缓冲流"也叫"包装流",是对基本输入输出流的增强: 字节缓冲流: BufferedInputStream , BufferedOutputStream 字符缓冲流: BufferedReader , BufferedWriter 缓冲流的基本原理: 创建流对象时,会创建一个缓冲区数组,通过缓冲区读写,减少系统IO次数,以提高读写效率. 就像送快递,快递小哥一次带一件当然慢,所以用车来运输,跑一趟可以带很多件. 以字符流为例: |-读文件:FileReade

Java基础教程——打印流

打印流 打印流可以把原本输出到控制台的信息输出到文件中.PrintStream是字节打印流(还有个对应的字符打印流是PrintWriter,这里不涉及) System类中有个变量: public final static PrintStream out = null; 赋值处: static { registerNatives(); } 打印流: public class PrintStream extends FilterOutputStream{...} public class Filte

Java基础教程(25)--I/O流

??I/O流表示输入源或输出目标.流可以表示许多不同类型的源和目标,例如磁盘文件.设备.其他程序等. ??流支持许多不同类型的数据,包括字节.原始数据类型.字符和对象等.有些流只传递数据; 有些流则可以操纵和转换数据. ??无论各种流的内部是如何工作的,所有流都提供相同的简单模型:流是一系列数据.程序使用输入流从源头获取数据,一次一项: ??程序使用输出流将数据写入目的地,一次一项: ??在本文中,我们会看到流可以处理各种各样的数据,无论是基本数据还是复杂对象.先来几张IO流的全家福: ??In

Java基础教程:JDBC编程

Java基础教程:JDBC编程 快速开始 什么是JDBC JDBC 指 Java 数据库连接,是一种标准Java应用编程接口( JAVA API),用来连接 Java 编程语言和广泛的数据库. JDBC API 库包含下面提到的每个任务,都是与数据库相关的常用用法. 制作到数据库的连接. 创建 SQL 或 MySQL 语句. 执行 SQL 或 MySQL 查询数据库. 查看和修改所产生的记录. 从根本上来说,JDBC 是一种规范,它提供了一套完整的接口,允许便携式访问到底层数据库,因此可以用 J

java基础篇IO流的规律

前两篇降了IO流中的字节流和字符流复制的例子,今天来总结一下IO流的规律 掌握好IO流的规律,再开发中会很好用 下面来总结一下: 1,明确源和目的 源:输入流 InputStream 和Reader 目的:输出流 OutputStream 和Writer 2,操作的数据是否是纯文本. 是:使用字符流 不是:使用字节流 3,当体系明确后,在明确要使用哪个具体的对象,通过设备来进行区分 源设备: 内存,硬盘,键盘 目的设备: 内存,硬盘,控制台 这里的源就是你想进行的操作,比如说你想从c盘复制一个文

java基础学习总结——流

永不放弃,一切皆有可能!!! 只为成功找方法,不为失败找借口! java基础学习总结——流 一.JAVA流式输入/输出原理 流是用来读写数据的,java有一个类叫File,它封装的是文件的文件名,只是内存里面的一个对象,真正的文件是在硬盘上的一块空间,在这个文件里面存放着各种各样的数据,我们想读文件里面的数据怎么办呢?是通过一个流的方式来读,咱们要想从程序读数据,对于计算机来说,无论读什么类型的数据都是以010101101010这样的形式读取的.怎么把文件里面的数据读出来呢?你可以把文件想象成一

Java基础教程:枚举类型

Java基础教程:枚举类型 枚举类型 枚举是将一具有类似特性的值归纳在一起的方法.比如,我们可以将周一到周日设计为一个枚举类型.彩虹的七种颜色设计为一个枚举类型. 常量实现枚举 我们通过定义常量的方式来实现,如下: Public static class RainbowColor { // 红橙黄绿青蓝紫七种颜色的常量定义 public static final int RED = 0; public static final int ORANGE = 1; public static fina