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

参考链接: 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 中的中文编码问题》。 

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/540241.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[转载] Java9发布回顾Java 8的十大新特性

参考链接&#xff1a; Java中的DoubleStream mapToObj() java9已经在北京时间9月22日正式发布&#xff0c;开发者可以在oracle jdk官网上下载到最新的jdk9。 今天&#xff0c;我们先来一起复习一下2014年发布的Java 8的十大新特性。先来喝杯java~~~ 按照java升级的传统&…

窗体间传递数据

前言 做项目的时候&#xff0c;winfrom因为没有B/S的缓存机制&#xff0c;窗体间传递数据没有B/S页面传递数据那么方便&#xff0c;今天我们就说下winfrom中窗体传值的几种方式。 共有字段传递 共有字段传递实现起来很方便&#xff0c;就是在窗体类中加个共有字段属性&#xff…

[转载] c语言中检查命令行参数_C中的命令行参数

参考链接&#xff1a; Java中的命令行参数 c语言中检查命令行参数 Command line argument is a parameter supplied to the program when it is invoked. Command line argument is an important concept in C programming. It is mostly used when you need to control your …

MySQL关闭Enterprise Server源码

今天从MySQL官方网站上获知&#xff0c;MySQL宣布关闭Enterprise Server的源码&#xff0c;对于广大开源爱好者来说&#xff0c;这是一个沉重的打击。虽然免费的用户群体一般仅仅使用MySQL Community Server&#xff08;开源免费社区版&#xff09;&#xff0c;但关闭MySQL Ent…

[转载] Java中Scanner用法总结

参考链接&#xff1a; Java之Scanner类 最近在做OJ类问题的时候&#xff0c;经常由于Scanner的使用造成一些细节问题导致程序不通过&#xff08;最惨的就是网易笔试&#xff0c;由于sc死循环了也没发现&#xff0c;导致AC代码也不能通过。。。&#xff09;&#xff0c;因此对S…

os和shutil模块

import os //os模块基本实现了linux系统中所有的命令 os.system(终端命令)&#xff1a;在终端执行命令 os.getcwd():获取当前的工作路径 os.chdir():修改工作路径 os.chmod():修改权限 os.chown():修改属主属组 os.mkdir():创建单个目录&#xff0c;当目录存在时报异常&…

[转载] JAVA语言程序设计(基础篇)第十版课后题答案(第一章)

参考链接&#xff1a; Java中的Scanner和nextChar() JAVA语言程序设计&#xff08;基础篇&#xff09;第十版课后题答案 第一章 第二题 /** Created by ysy on 2018/7/6. */ public class text2 { public static void main(String[] args){ for(int i 0; i < 5; i) Syste…

java.util.Date和java.sql.Date 一点区别

最近无意中发现&#xff0c;在oracle中同一样的一个Date类型字段&#xff0c;存储的日期格式有两种不同的情况&#xff0c;第一种是2011-1-1 12:00:00&#xff0c;第二种是2011-1-1&#xff0c;仔细查找发现在向数据库中写数据的时候定义的变量的问题。 第一种是&#xff1a;ja…

[转载] java中关于用\t格式输出

参考链接&#xff1a; 用Java格式化输出 看了好多人关于\t的用法&#xff0c;感觉找不到自己想要的答案&#xff0c;所以索性就自己输出来看看&#xff0c;如图&#xff1a;这样可以一目了然的看出来&#xff0c;\t&#xff08;制表符&#xff09;的作用就是看前面输出满不满8…

微信抢房软件开发

2019独角兽企业重金招聘Python工程师标准>>> 这两年楼市真可谓是一个"火“字难以形容 经历了长沙两次开盘&#xff0c;都没有抢到&#xff0c;目前还没有买到房子&#xff0c;说说我的悲剧吧&#xff0c;让大伙都开心开心 第一次抢房是今年4月份长沙万科金域国…

[转载] Java——数组习题

参考链接&#xff1a; Java从控制台读取输入的方法 package chap02; import java.util.Scanner; /** * * author admin * date 2020-4-8 * description: * 题目内容&#xff1a; 编写程序&#xff0c; 从控制台读取下面的信息&#xff0c; 每月按22天工作日计算&#xff0c;…

超全Linux备份工具集合,满足你的所有需要!

经常备份计算机上的数据是个好的做法&#xff0c;它可以手动完成&#xff0c;也可以设置成自动执行。许多备份工具拥有不同的功能特性&#xff0c;让用户可以配置备份类型、备份时间、备份对象、将备份活动记入日志及执行更多操作。 1.Rsync这是一款在Linux用户当中颇受欢迎的命…

[转载] Java内存管理-你真的理解Java中的数据类型吗(十)

参考链接&#xff1a; Java中的字符串类String 1 做一个积极的人 编码、改bug、提升自己 我有一个乐园&#xff0c;面向编程&#xff0c;春暖花开&#xff01; 推荐阅读 第一季 0、Java的线程安全、单例模式、JVM内存结构等知识梳理 1、Java内存管理-程序运行过程&#x…

Linux系统安全加固脚本

闲来无事&#xff0c;整理一个系统安全加固脚本&#xff0c;每个公司的要求不一样&#xff0c;所以仅供参考&#xff1a; #!/bin/sh echo "00 */1 * * * /usr/sbin/ntpdate 192.168.1.1 >>/var/log/ntpdate.log" > mycrontab crontab mycrontab rm -rf my…

[转载] 整理下java中stringBuilder和stringBuffer两个类的区别

参考链接&#xff1a; Java中的StringBuffer类 StringBuilder和StringBuffer这两个类在动态拼接字符串时常用&#xff0c;肯定比String的效率和开销小&#xff0c;这是因为String的对象不会回收哦。 其实我一直用StringBuilder这个类&#xff0c;因为可以简写为sb的变量在程序…

11.13 模10计数器设计

.新建一个工程 Family&#xff1a;FLEX10K Available device&#xff1a;EPF10K20TC144-3 2.设置lpm_counter宏单元参数并连接引脚 连接引脚的时候要注意的是&#xff0c;向量线的连接。 3.时序仿真 检查无误后进行下一步 4.载入7448并进行引脚连接 5.分配管脚 再次编译&#x…

[转载] java对象在内存中的结构

参考链接&#xff1a; 了解Java中的类和对象 今天看到一个不错的PPT&#xff1a;Build Memory-efficient Java Applications&#xff0c;开篇便提出了一个问题&#xff0c;在Hotspot JVM中&#xff0c;32位机器下&#xff0c;Integer对象的大小是int的几倍&#xff1f; 我们…

使用valueOf前必须进行校验

每个枚举都是java.lang.Enum的子类,都可以访问Enum类提供的方法,比如hashCode(),name(),valueOf()等..... 其中valueOf()方法会把一个String类型的名称转变为枚举项,也就是枚举项中查找出字面值与该参数相等的枚举项,虽然这个方法很简单,但是JDK却做了一个对于开发人员来说并不…

[转载] 【Java】Java基础知识及其扩展笔记(8千字)

参考链接&#xff1a; Java中的StringBuilder类及其示例 Java基础知识及其扩展笔记 零 l 写在前面一 l JVM1、【1.1.2.1】java程序运行的一般流程2、【1.1.2.1】JVM一般运行流程3、【1.1.2.1】JIT&#xff08;just in time 即时编译编译器&#xff09;4、堆与栈 二 l Java …

多IDC GSLB的部署

之前已经介绍过GSLB的实现原理&#xff0c;这里再向大家讲述一下GSLB经常遇到的部署方式&#xff0c;多IDC的部署。很多大型的企业或业务容灾要求非常高的客户都会部署有多个异地的数据中心&#xff0c;以保证其业务的“全天候”不间断的正常运行&#xff0c;而要整合多个IDC的…