ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[转载] 菜鸟举例理解字节流和字符流区别

2020-12-11 10:30:28  阅读:205  来源: 互联网

标签:编码 字节 字符 菜鸟 len 举例 new byte


参考链接: Java中的字符流与字节流 Character Stream对比Byte Stream

菜鸟举例理解字节流和字符流区别 

 按照uft8编码方式存储文档 

 文档存储路径在D盘下 

/**

* 按照utf8格式存储文档

*/

public static void storeDataByUTF8(){

    String path = "D:" + File.separator + "textutf8.txt";

    File file = new File(path);

    try {

        PrintWriter pw = new PrintWriter(file,"utf-8");

        for(int i=0;i<5;i++){

            pw.write(i+":"+"字节流与字符流!!!"+"\r\n");

        }

        pw.flush();

        pw.close();

    } catch (FileNotFoundException | UnsupportedEncodingException e) {

        e.printStackTrace();

    }

 对比使用BufferedReader和FileInputStream按照byte读取文档(按照字节流方式读取) 

 使用BufferedReader按照byte读取文档代码如下: 

public static void readDataWithArray(){

    String path = "D:" + File.separator + "textutf8.txt";

    File file = new File(path);

    try{

        FileInputStream fis = new FileInputStream(file);

          InputStreamReader isr = new InputStreamReader(fis,"utf-8");

        BufferedReader in = new BufferedReader(isr);

        byte[] b = new byte[2048];

        int temp = 0;

        int len = 0;

        

        while((temp=in.read())!=-1){  // -1是结束符

            b[len] = (byte)temp;

            if(len<2047)

                len++;

            else

                break;

        }

        in.close();

        System.out.println(new String(b,0,len,"utf-8"));

        

    }catch(Exception e){

        e.printStackTrace();

        System.out.println("While reading the data, the program threw out exceptions");

    }

 

 输出结果发生了乱码: 

0:W?AW&A

1:W?AW&A

2:W?AW&A

3:W?AW&A

4:W?AW&A 

 FileInputStream按照byte读取文档代码如下: 

public static void readDataWithArray(){

    String path = "D:" + File.separator + "textutf8.txt";

    File file = new File(path);

    try{

        FileInputStream in = new FileInputStream(file);

        //InputStreamReader isr = new InputStreamReader(fis,"utf-8");

        //BufferedReader in = new BufferedReader(isr);

        

        byte[] b = new byte[2048];

        int temp = 0;

        int len = 0;

        

        while((temp=in.read())!=-1){  // -1是结束符

            b[len] = (byte)temp;

            if(len<2047)

                len++;

            else

                break;

        }

        in.close();

        System.out.println(new String(b,0,len,"utf-8"));

        

    }catch(Exception e){

        e.printStackTrace();

        System.out.println("While reading the data, the program threw out exceptions");

    }

 

 输出结果正常: 

0:字节流与字符流!!!

1:字节流与字符流!!!

2:字节流与字符流!!!

3:字节流与字符流!!!

4:字节流与字符流!!! 

 以上两段代码不同之处只是读取文本的流不同,其他代码相同。要回答这个问题,首先来理解一下为什么要编码? 

 为什么要编码 

 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言。由于人类的语言有太多,因而表示这些语言的符号太多,无法用计算机中一个基本的存储单元—— byte 来表示,因而必须要经过拆分或一些翻译工作,才能让计算机能理解。我们可以把计算机能够理解的语言假定为英语,其它语言要能够在计算机中使用必须经过一次翻译,把它翻译成英语。这个翻译的过程就是编码。所以可以想象只要不是说英语的国家要能够使用计算机就必须要经过编码。 所以总的来说,编码的原因可以总结为: 

计算机中存储信息的最小单元是一个字节即 8 个 bit,所以能表示的字符范围是 0~255 个人类要表示的符号太多,无法用一个字节来完全表示要解决这个矛盾必须需要一个新的数据结构 char,从 char 到 byte 必须编码 

 为什么两者的结果那么不同呢? 

 在Java中byte是1个字节(8个bit),char是2个字节; 最基础的流InputStream和OutputStream是按照字节读取的(byte)。 

/**

 * Reads a byte of data from this input stream. This method blocks

 * if no input is yet available.

 *

 * @return     the next byte of data, or <code>-1</code> if the end of the

 *             file is reached.

 * @exception  IOException  if an I/O error occurs.

 */

public int read() throws IOException {

    return read0();

 但是BufferedReader类的read()方法返回的是char。所以没有处理好编码原因的第三个原因。 

public class BufferedReader extends Reader {

    private char cb[];  // char数组的缓存

    private int nChars, nextChar;

    ...

        /**

     * Reads a single character.

     *

     * @return The character read, as an integer in the range

     *         0 to 65535 (<tt>0x00-0xffff</tt>), or -1 if the

     *         end of the stream has been reached

     * @exception  IOException  If an I/O error occurs

     */

    public int read() throws IOException {

        synchronized (lock) {

            ensureOpen();

            for (;;) {

                if (nextChar >= nChars) {

                    fill();

                    if (nextChar >= nChars)

                        return -1;

                }

                if (skipLF) {

                    skipLF = false;

                    if (cb[nextChar] == '\n') {

                        nextChar++;

                        continue;

                    }

                }

                return cb[nextChar++];

            }

        }

    }

    

 举个详细的例子: 按照 ISO-8859-1 编码字符串“I am 君山”用 ISO-8859-1 编码,下面是编码结果:  

 从上图看出7个char 字符经过ISO-8859-1 编码转变成7个byte 数组,ISO-8859-1是单字节编码,中文“君山”被转化成值是3f的byte。3f也就是“?”字符,所以经常会出现中文变成“?”很可能就是错误的使用了 ISO-8859-1这个编码导致的。中文字符经过 ISO-8859-1编码会丢失信息,通常我们称之为“黑洞”,它会把不认识的字符吸收掉。由于现在大部分基础的 Java 框架或系统默认的字符集编码都是 ISO-8859-1,所以很容易出现乱码问题。 

 以上总结只是举例了一个简单的例子,希望能通过这个例子使得你对Java字节流和字符流的区别有个感性的认识。如果需要了解两者的区别,强烈建议大家看看另一篇博客《深入分析 Java 中的中文编码问题》。 

 如果博客写得有什么问题,请各请各位大神指出。

标签:编码,字节,字符,菜鸟,len,举例,new,byte
来源: https://blog.csdn.net/ld909/article/details/111030088

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有