Java API —— 编码 & IO流( InputStreamReader & OutputStreamWriter & FileReader & FileWriter & BufferedReader & BufferedWriter )
1、编码
1)编码表概述
由字符及其对应的数值组成的一张表
2)常见编码表
· ASCII/Unicode 字符集:ASCII是美国标准信息交换码,用一个字节的7位可以表示。Unicode是国际标准码,融合了多种文字,所有文字都用两个字节来表示,Java语言使用的就是unicode。
· ISO-8859-1:拉丁码表。欧洲码表,用一个字节的8位表示。
· GB2312/GBK/GB18030:GB2312是中国的中文编码表。GBK是中国的中文编码表升级,融合了更多的中文文字符号。GB18030是GBK的取代版本。
· BIG5:通行于台湾、香港地区的一个繁体字编码方案,俗称“大五码”。
· UTF-8:最多用三个字节来表示一个字符。
3)字符串中的编码问题
· 编码 把看得懂的变成看不懂的
· 解码 把看不懂的变成看得懂的
import java.io.UnsupportedEncodingException; import java.util.Arrays; /** * Created by gao on 15-12-28. */ /** * String(byte[] bytes, String charsetName):通过指定的字符集解码字节数组 * byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码为字节数组 */ public class StringDemo { public static void main(String[] args) throws UnsupportedEncodingException { String s = "你好"; // String -- byte[] byte[] bys1 = s.getBytes(); byte[] bys2 = s.getBytes("GBK"); byte[] bys3 = s.getBytes("UTF-8"); System.out.println(Arrays.toString(bys1)); // [-60, -29, -70, -61] System.out.println(Arrays.toString(bys2)); // [-60, -29, -70, -61] System.out.println(Arrays.toString(bys3)); // [-28, -67, -96, -27, -91, -67] // byte[] -- String String ss1 = new String(bys1); // 你好 String ss2 = new String(bys2, "GBK"); // 你好 String ss3 = new String(bys3, "UTF-8"); // 你好 System.out.println(ss1); System.out.println(ss2); System.out.println(ss3); } }
2、转换流
1)OutputStreamWriter 字符输出流
· public OutputStreamWriter(OutputStream out):根据默认编码把字节流的数据转换为字符流
· public OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流
2)InputStreamReader 字符输入流
· public InputStreamReader(InputStream in):用默认的编码读取数据
· public InputStreamReader(InputStream in,String charsetName):根据指定编码把字节流数据转换为字符流
· public InputStreamReader(InputStream in):用默认的编码读取数据
· public InputStreamReader(InputStream in,String charsetName):根据指定编码把字节流数据转换为字符流
例子1:
package itcast02; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; /** * Created by gao on 15-12-28. */ public class OutputStreamWriterDemo { public static void main(String[] args) throws IOException { // 创建对象 // OutputStreamWriter(OutputStream out):根据默认编码把字节流的数据转换为字符流 //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt")); //public OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流 //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "GBK"); OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "UTF-8"); // 写数据 osw.write("中国"); // 释放资源 osw.close(); } }
例子2:
package itcast02; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; /** * Created by gao on 15-12-28. */ public class InputStreamReaderDemo { public static void main(String[] args) throws IOException { // 创建对象 //InputStreamReader(InputStream is):用默认的编码读取数据 //InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt")); //InputStreamReader(InputStream is,String charsetName):用指定的编码读取数据 InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "UTF-8"); // 读取数据 // 一次读取一个字符 int by = 0; while ((by = isr.read()) != -1) { System.out.println((char) by); } // 释放资源 isr.close(); } }
3)OutputStreamWriter写数据
· OutputStreamWriter写数据方法
· public void write(int c):写一个字符
· public void write(char[] cbuf):写一个字符数组
· public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
· public void write(String str):写一个字符串
· public void write(String str,int off,int len):写一个字符串的一部分
· 字符流操作要注意的问题
· flush()的作用
· flush()和close()的区别
A:close()关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了。
B:flush()仅仅刷新缓冲区,刷新之后,流对象还可以继续使用。
例子1:
package itcast02; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; /** * Created by gao on 15-12-28. */ public class OutputStreamWriterDemo02 { public static void main(String[] args) throws IOException { // 创建对象 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw2.txt")); // 写数据 // public void write(int c):写一个字符 osw.write('a'); osw.write(97); // 为什么数据没有进去呢? // 原因是:字符 = 2字节 // 文件中数据存储的基本单位是字节。 // void flush() // public void write(char[] cbuf):写一个字符数组 char[] chs = {'a', 'b', 'c', 'd'}; osw.write(chs); // public void write(char[] cbuf,int off,int len):写一个字符数组的一部分 osw.write(chs, 1, 3); // public void write(String str):写一个字符串 osw.write("我爱中国"); // public void write(String str,int off,int len):写一个字符串的一部分 osw.write("我爱中国", 2, 2); // 刷新缓冲区 osw.flush(); // osw.write("我爱林青霞", 2, 3); // 释放资源 osw.close(); // java.io.IOException: Stream closed // osw.write("我爱林青霞", 2, 3); } }
4)InputStreamReader读数据
· public int read()
· public int read(char[] cbuf)
例子1:
package itcast02; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; /** * Created by gao on 15-12-28. */ public class InputStreamReaderDemo02 { public static void main(String[] args) throws IOException { // 创建对象 InputStreamReader isr = new InputStreamReader(new FileInputStream("StringDemo.java")); //int read(): 一次读取一个字符 // int ch = 0; // while ((ch = isr.read()) != -1) { // System.out.print((char) ch); // } //int read(char[] chs):一次读取一个字符数组 char[] chs = new char[1024]; int len = 0; while ((len = isr.read(chs)) != -1) { System.out.println(new String(chs, 0, len)); } // 释放资源 isr.close(); } }
例子2:复制文件
package exercise; import java.io.*; /** * Created by gao on 15-12-28. */ /* * 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中 * * 数据源: * a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader * 目的地: * b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter */ public class CopyFileDemo01 { public static void main(String[] args) throws IOException { // 封装数据源 InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt")); // 封装目的地 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt")); // 读写数据 // 方式1 // int ch = 0; // while((ch = isr.read())!=-1){ // osw.write(ch); // } // 方式2 char[] chs = new char[1024]; int len = 0; while ((len = isr.read(chs)) != -1) { osw.write(chs, 0, len); } // 释放资源 osw.close(); isr.close(); } }
3、转换流的简化写法
转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流提供了对应的子类。
· FileWriter
· FileReader
例子1:复制文件
package exercise; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; /** * Created by gao on 15-12-28. */ /* * 由于我们常见的操作都是使用本地默认编码,所以,不用指定编码。 * 而转换流的名称有点长,所以,Java就提供了其子类供我们使用。 * OutputStreamWriter = FileOutputStream + 编码表(GBK) * FileWriter = FileOutputStream + 编码表(GBK) * * InputStreamReader = FileInputStream + 编码表(GBK) * FileReader = FileInputStream + 编码表(GBK) * /* * 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中 * * 数据源: * a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader * 目的地: * b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter -- FileWriter */ public class CopyFileDemo02 { public static void main(String[] args) throws IOException { // 封装数据源 FileReader fr = new FileReader("a.txt"); // 封装目的地 FileWriter fw = new FileWriter("b.txt"); // 一次一个字符 // int ch = 0; // while ((ch = fr.read()) != -1) { // fw.write(ch); // } // 一次一个字符数组 char[] chs = new char[1024]; int len = 0; while ((len = fr.read(chs)) != -1) { fw.write(chs, 0, len); fw.flush(); } // 释放资源 fw.close(); fr.close(); } }
例子2:复制文件
package cn.itcast_04; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; /* * 需求:把c:\\a.txt内容复制到d:\\b.txt中 * * 数据源: * c:\\a.txt -- FileReader * 目的地: * d:\\b.txt -- FileWriter */ public class CopyFileDemo3 { public static void main(String[] args) throws IOException { // 封装数据源 FileReader fr = new FileReader("c:\\a.txt"); // 封装目的地 FileWriter fw = new FileWriter("d:\\b.txt"); // 读写数据 // int ch = 0; int ch; while ((ch = fr.read()) != -1) { fw.write(ch); } //释放资源 fw.close(); fr.close(); } }
4、字符缓冲流
1)BufferedWriter:字符缓冲输出流
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
2)BufferedReader:字符缓冲输入流
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
3)特殊功能
BufferedWriter
void newLine():写入一个行分隔符,根据系统来决定换行符。
BufferedReader
String readLine():读取一个文本行,一次读取一行数据,包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null。
例子1:
package buffereddemos; import java.io.*; /** * Created by gao on 15-12-28. */ public class BufferedWriterDemo01 { public static void main(String[] args) throws IOException{ // BufferedWriter(Writer out) //BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("bw.txt"))); //简洁版 BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt")); bw.write("hello"); bw.write("world"); bw.write("java"); bw.flush(); bw.close(); } }
例子2:
package buffereddemos; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; /** * Created by gao on 15-12-28. */ public class BufferedReaderDemo01 { public static void main(String[] args) throws IOException { // 创建字符缓冲输入流对象 BufferedReader br = new BufferedReader(new FileReader("bw.txt")); // 方式1 // int ch = 0; // while ((ch = br.read()) != -1) { // System.out.print((char) ch); // } // 方式2 char[] chs = new char[1024]; int len = 0; while ((len = br.read(chs)) != -1) { System.out.println(new String(chs, 0, len)); } br.close(); } }
例子3:
package buffereddemos; import java.io.*; /** * Created by gao on 15-12-28. */ /* * 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中 * * 数据源: * a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader -- BufferedReader * 目的地: * b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter -- FileWriter -- BufferedWriter */ public class CopyFileDemo { public static void main(String[] args) throws IOException { // 封装数据源 BufferedReader br = new BufferedReader(new FileReader("a.txt")); // 封装目的地 BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt")); // 两种方式其中的一种一次读写一个字符数组 char[] chs = new char[1024]; int len = 0; while ((len = br.read(chs)) != -1) { bw.write(chs, 0, len); bw.flush(); } // 释放资源 br.close(); bw.close(); } }
例子4:
package buffereddemos; import java.io.*; /** * Created by gao on 15-12-28. */ public class BufferedStringDemo { public static void main(String[] args) throws IOException { //write(); read(); } public static void read() throws IOException { // 创建字符缓冲输入流对象 BufferedReader br = new BufferedReader(new FileReader("bw2.txt")); // public String readLine():一次读取一行数据 // String line = br.readLine(); // System.out.println(line); // 最终版代码 String line = null; while ((line = br.readLine()) != null) { System.out.println(line); //注意自己加换行 } } public static void write() throws IOException { // 创建字符缓冲输出流对象 BufferedWriter bw = new BufferedWriter(new FileWriter("bw2.txt")); for (int x = 0; x < 10; x++) { bw.write("hello" + x); // bw.write("\r\n"); bw.newLine(); bw.flush(); } bw.close(); } }
例子5:
package buffereddemos; import java.io.*; /** * Created by gao on 15-12-28. */ /* * 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中 * * 数据源: * a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader -- BufferedReader * 目的地: * b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter -- FileWriter -- BufferedWriter */ public class CopyFileDemo02 { public static void main(String[] args) throws IOException { // 封装数据源 BufferedReader br = new BufferedReader(new FileReader("a.txt")); // 封装目的地 BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt")); // 读写数据 String line = null; while ((line = br.readLine()) != null) { bw.write(line); //遇到换行符截止 bw.newLine(); //复制不加换行符,所以需要自己加上换行符 bw.flush(); } // 释放资源 br.close(); bw.close(); } }