转换流(可以根据需求修改编码表)
乱码的原因
因为文本在存储时使用的映射码表和在读取时使用的码表不一致造成的。
编码表(了解)
在计算机中无论任何数据的传输、存储、持久化,都是以二进制的形式体现的。 那么当我存一个字符的时候,计算机需要持久化到硬盘,或者保存在内存中。 这个时候保存在内存、硬盘的数据显然也是二进制的。 那么当我需要从硬盘、内存中取出这些字符,再显示的时候,为什么二进制会变成了字符呢? 这就是码表存在的意义。 码表其实就是一个字符和其对应的二进制相互映射的一张表。 这张表中规定了字符和二进制的映射关系。 计算机存储字符时将字符查询码表,然后存储对应的二进制。 计算机取出字符时将二进制查询码表,然后转换成对应的字符显示。 不同的码表所容纳的字符映射也是不同的。 可以这样理解。 在有些码表中一个字符占用1个字节,1个字节能表示的范围是-128到127,总共为256。所以能容纳256个字符映射。 而有些码表中一个字符占用2个字节,甚至3个字节,因此能容纳的字符映射也更多。 下面按照自己的理解详细讲述一下不同的码表。 常见的码表: ASCII: * 美国码表,码表中只有英文大小写字母、数字、美式标点符号等。每个字符占用1个字节,所有字符映射的二进制都为正数,因此有128个字符映射关系。 GB2312: * 兼容ASCII码表,并加入了中文字符,码表中英文大小写字母、数字、美式标点符号占一个字节,中文占两个字节,中文映射的二进制都是负数,因此有128× 128 = 16384个字符映射关系。 GBK/GB18030: * 兼容GB2312码表,英文大小写字母、数字、美式标点符号,占一个字节。中文占两个字节,第一个字节为负数,第二个字节为正数和负数,因为有128× 256 = 32768个字符映射关系。 Unicode码表: * 国际码表,包含各国大多数常用字符,每个字符都占2个字节,因此有65536个字符映射关系。Java语言使用的就是Unicode码表。 * Java中的char类型用的就是这个码表。char c = 'a';占两个字节。 UTF-8码表: * 是基于Unicode码表的,但更智能,会根据字符的内容选择使用多个字节存储。英文占一个字节,中文占3个字节。 乱码的原因 * 因为文本在存储时使用的映射码表和在读取时使用的码表不一致造成的。 |
public class InputStreamReaderDemo { public static void main(String[] args) throws Exception{ // readGBK(); readUTF8(); } // 使用utf8读取数据 public static void readUTF8() throws IOException { // 创建字符输入转换流对象:默认使用GBK InputStreamReader isr = new InputStreamReader(new FileInputStream("c.txt"),"UTF-8"); // 创建字符数组存储读取到内容 char[] cbuf = new char[1024]; // 读取数据 int len = isr.read(cbuf); System.out.println(new String(cbuf,0,len)); // 关闭流 isr.close(); } // 使用GBK读取数据 public static void readGBK() throws IOException { // 创建字符输入转换流对象:默认使用GBK InputStreamReader isr = new InputStreamReader(new FileInputStream("c.txt")); // 创建字符数组存储读取到内容 char[] cbuf = new char[1024]; // 读取数据 int len = isr.read(cbuf); System.out.println(new String(cbuf,0,len)); // 关闭流 isr.close(); } } |
代码演示
public class ObjectOutputStreamDemo { public static void main(String[] args) throws Exception{ // 创建学生对象 Student stu = new Student("9527","jack","男",23); // 创建对象输出流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("stu.txt")); // 调用方法将对象输出到文件中 oos.writeObject(stu); // 关闭流 oos.close(); } } |
public class ObjectInputStreamDemo { public static void main(String[] args) throws Exception{ // 创建对象输入流 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("stu.txt")); // 读取对象 Student stu = (Student)ois.readObject(); System.out.println(stu); // 关闭流 ois.close(); } } |
public class PrintStreamDemo { public static void main(String[] args) throws Exception{ // 创建字节打印输出流 // PrintStream ps = new PrintStream("ps.txt"); PrintWriter ps = new PrintWriter("ps.txt"); ps.println(97); ps.println(1.8); ps.println(false); ps.println('a'); ps.println("你好"); ps.println(100L); // 关闭流 ps.close(); } } |
public class Demo01 { public static void main(String[] args) throws IOException { // FileUtils工具类的常用方法 // 使用指定的编码从指定的文件中读取内容 // System.out.println(FileUtils.readFileToString(new File("a.txt"),"utf8")); // 将指定字符串输出到指定的文件中 // FileUtils.write(new File("d.txt"), "hello world 世界"); // 将srcFile文件的内容复制到destFile文件中。 // FileUtils.copyFile(new File("a.txt"), new File("e.txt")); // 文件夹复制 FileUtils.copyDirectory(new File("/Users/pkxing/Documents/77期就业班/day12/resource/commons-io-2.4"), new File("/Users/pkxing/Documents/commons-io-2.4")); // FilenameUtils工具类常用方法 /*System.out.println(FilenameUtils.getName("/users/pkxing/documents/aaa.txt")); System.out.println(FilenameUtils.getExtension("/users/pkxing/documents/aaa.txt")); System.out.println(FilenameUtils.isExtension("/users/pkxing/documents/aaa.txt","png"));*/ } } |