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();
    	}
    }
    

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

  • 相关阅读:
    MSDN Magazine搞错了
    Visual Studio 2005中设置调试符号(Debug Symbols)
    BCB 6的问题
    吴裕雄天生自然Spring Boot使用Spring Data JPA实现人与身份证的一对一关系映射
    吴裕雄天生自然Spring BootSpring Data JPA
    吴裕雄天生自然Spring BootSpring Boot对JSP的支持
    吴裕雄天生自然Spring BootSpring Boot的异常统一处理
    吴裕雄天生自然Spring Boot使用Spring Data JPA实现Author与Article的一对多关系映射
    吴裕雄天生自然Spring Boot解决 Error creating bean with name 'entityManagerFactory' defined in class path resource
    吴裕雄天生自然Spring Boot@ExceptionHandler注解和@ControllerAdvice注解
  • 原文地址:https://www.cnblogs.com/tigerlion/p/11179229.html
Copyright © 2011-2022 走看看