zoukankan      html  css  js  c++  java
  • 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();
    	}
    }
    

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

  • 相关阅读:
    JavaScript 深度克隆 JSON 对象
    NetBeans IDE 6.7.1 with JavaFX Now Available for Download!
    NetBeans 时事通讯(刊号 # 65 Jul 21, 2009)
    来自雨林木风的Linux发行版: Ylmf Linux
    JavaScript 深度克隆 JSON 对象
    STL vector vs list function comparison:
    手把手教你把Vim改装成一个IDE编程环境(图文)
    Using Visual Leak Detector
    疯狂的编程世界_IT新闻_博客园
    分享好段子:
  • 原文地址:https://www.cnblogs.com/tigerlion/p/11179229.html
Copyright © 2011-2022 走看看