当前位置: 移动技术网 > IT编程>开发语言>Java > 6.4(java学习笔记)转换流

6.4(java学习笔记)转换流

2018年11月01日  | 移动技术网IT编程  | 我要评论

一、乱码问题

 

我们来看下列例子:  

public class constream {
    //当前平台默认采用gbk
    public static void main(string[] args){
        string str = "依风";
        byte[] by = new byte[48];
        byte[] bz = new byte[48];
        try {
            by = str.getbytes("utf-8");//设置编码方式为utf-8,即将依风以utf-8的个数转换为byte
            bz = str.getbytes("gbk");
        } catch (unsupportedencodingexception e) {
            // todo auto-generated catch block
            e.printstacktrace();
        }
        system.out.println(new string(by));//解码,默认采用平台默认格式,此处为gbk,与编码格式不同会产生乱码
        system.out.println(new string(bz,0,3));//编码与解码采用格式相同,但解码的字节缺少,会出现乱码
        system.out.println(new string(bz));//编码解码格式相同,且字符为缺少,解码正常不会出现乱码
        
    }
}
运行结果:
渚濋 依? 依风

 

eclipse采用的编码格式,在菜单栏点击windows-->preferences-->general-->workspace 查看默认编码方式

 

可以看到上面出现乱码的主要原因有两个:

1.编码和解码格式不统一。

2.字节丢失。

 

而转换流主要就是解决第一个问题的,它可以在读取和写入时指定编码格式,这样统一后就可以避免乱码问题。

 

二、 inputstreamreader & outputstreamwtriter

    inputstreamreader是从字节流到字符流的桥梁:它读取字节并使用指定的字符集(utf-8、gbk等)将它们解码成字符。

    outputstreamwriter是从字符流到字节流的桥梁:写入其中的字符使用指定的字符集(utf-8、gbk等)编码为字节。

 

三、构造方法

  outputstreamwriter(outputstream out, string charsetname)

  inputstreamreader(inputstream in, string charsetname)

  初始化传递进去的是输入输出流对象,charsename是指定的编码格式。

  剩下的操作方法与输入输出流类似。

 

四、例子

  

import java.io.bufferedreader;
import java.io.bufferedwriter;
import java.io.file;
import java.io.fileinputstream;
import java.io.filenotfoundexception;
import java.io.fileoutputstream;
import java.io.ioexception;
import java.io.inputstream;
import java.io.inputstreamreader;
import java.io.outputstream;
import java.io.outputstreamwriter;

public class constream {
    public static void main(string[] args){
    //    file f = new file("f:\\依风\\desktop\\utf-8.txt");
        file f = new file("f:\\依风\\desktop\\test.txt");
        string write = "依风\n依风\n依风";
        string read;
        try {
            char []c = new char[1024];
            //字节输入输出流-->转换流-->字符缓冲流
            //以一种编码格式写入
            outputstream w = new fileoutputstream(f);
            outputstreamwriter ow = new outputstreamwriter(w,"gbk");//将字符转换为gbk格式的字节码并写入
            bufferedwriter buffw = new bufferedwriter(ow);
            buffw.write(write);
            buffw.flush();
            buffw.close();
            w.close();
            //将写入的数据
            inputstream r = new fileinputstream(f);//字节流
            inputstreamreader ir = new inputstreamreader(r,"utf-8");//将读入gbk格式的字节码,并用utf-8格式转换为字符
            bufferedreader buffr = new bufferedreader(ir);//字符缓冲流
            while(null != (read = buffr.readline())){
                system.out.println(read);
            }
            buffr.close();
            r.close();
        } catch (filenotfoundexception e) {
            // todo auto-generated catch block
            e.printstacktrace();
        } catch (ioexception e) {
            // todo auto-generated catch block
            e.printstacktrace();
        }
    }
}
运行结果:
????
????
????

先将字符串以gbk方式编码成字节,然后将gbk格式的字节写入文件。

然后将gbk格式的字节以utf-8格式解码成字符。

上列代码运行后显示的是乱码,因为写入和读取采用的编码方式不一样。

看个图更好理解:

 

 可见转换流主要就两个功能:

1、字节流与字符流字节转换的桥梁

2、指定字节转换为字符的编码方式

 

如果把上述代码中的读、写编码格式一致,则不会出现乱码。反之则会出现乱码。

 

还要一点需要注意:

文件打开时采取的解码方式与程序写入时的编码方式无关。

举个例子,假如我是将字符串转换为gbk格式的字节,然后将gbk格式的字节写入记事本(*.txt)。

我们打开记事本时记事本首先要解码(将二进制的字节转换为字符),但此时采用的解码规则不一定是gbk。

可能是gbk,也可能是utf-8。记事本采取的解码规则是记事本本身绝对的,记事本会根据本身存储的字节信息进行判断,

然后选取对应的编码,这个判断大多数情况下时准确的但也有例外。

 

例如在记事本中写入“连通”,然后另存为指定下编码规则为ansi,即在windows平台是采用下gbk编码规则。

然后再次打开记事本会发现显示的是乱码。因为“连通”的gbk格式编码和utf-8格式的编码“类型”,所以记事本会用utf-8的方式进行解码。

采用gbk编码方式的字节码用utf-8编码方式解码就会出现乱码问题。

 

输入连通

另存为,修改编码规则为ansi(gbk)

 

保存退出,然后再次打开该文本。

我们再次点击另存为:

编码中显示的utf-8就代表记事本当前的编码规则。

也就是说我们输入“连通”然后用gbk格式保存,记事本自己判断这个编码是utf-8,然后采用utf-8方式解码,然后我们看到的就是乱码。

当然这只是个例,换一些别的字符采用上述操作不会出现乱码。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网