1、字符流原理 字符流是以字符为单位读写数据的流。Reader是字符输入流的父类,Writer是字符输出流的父类。 字符流是一种高级流,其构造方法需要传入一种低级流作为参数。 字符流底层封装的仍是字节流。
2、InputStreamReader的构造方法InputStreamReader有如下几个构造方法,但是最常用的是InputStreamReader(InputStream in, String charsetName),改构造方法第一个参数是字节流,第二个参数是字符集字符串代码片段如下:/* * InputStreamReader构造方法 * InputStreamReader(InputStream in) * * InputStreamReader(InputStream in, String charsetName) * * InputStreamReader(InputStream in, Charset cs) * * InputStreamReader(InputStream in, CharsetDecoder dec) */ @Test public void testISRContructor() throws Exception{ FileInputStream fis = new FileInputStream("rw.txt"); //构造方法InputStreamReader(InputStream in)参数传入一个字节流 InputStreamReader isr = new InputStreamReader(fis); //构造方法InputStreamReader(InputStream in, String charsetName) //第一个参数是字节流,第二个参数是字符集字符串 InputStreamReader isr2 = new InputStreamReader(fis,"UTF-8"); //构造方法InputStreamReader(InputStream in, Charset cs) //第一个参数是字节流,第二个参数是字符集类 Charset cs = Charset.forName("UTF-8"); InputStreamReader isr3 = new InputStreamReader(fis,cs); //构造方法InputStreamReader(InputStream in, CharsetDecoder dec) //第一个参数是字节流,第二个参数是编码器 CharsetDecoder dc = cs.newDecoder(); InputStreamReader isr4 = new InputStreamReader(fis,dc); }
3、InputStreamReader的原理 该流能够通过给定的字符集将读取的字节数组转换成字符串,当然该流将底层封装其底层仍是基于字节流的,我们能够根据给定的字符集读取到相应的字符串。示例代码如下: /* * InputStreamReader字符输入流常用方法 * int read() * 读取一个字符,返回的int值"低16位"有效,不是int值"低8位"有效了 * * int read(chra[] chrs) * 读取一组字符数组,返回值是实际读取的字符量 */ @Test public void testISR() throws Exception{ FileInputStream fis = new FileInputStream("test_inputstreamreader.txt"); //构造方法InputStreamReader(InputStream in,String charsetName) InputStreamReader isr = new InputStreamReader(fis,"UTF-8"); int d = -1; while((d = isr.read())!=-1){ System.out.print((char)d); } isr.close(); }字符输入流的read()让人似曾相识,只是返回值是“低16位”(一个字符占位)有效,而read(char[] chrs)是读取字符数组,而不是字节数组了。分析:关闭高级流,会自动关闭低级流。所以不必再写fis.close()。
4、OutputStreamWrite的构造方法OutputStreamWriter的构造方法和InputStreamReader的构造方法是一一对应的,这里就不多赘言。代码片段如下:/* * OutputStreamWriter的几个构造方法: * OutputStreamWriter(OutputStream out) * * OutputStreamWriter(OutputStream out, String charsetName) * * OutputStreamWriter(OutputStream out, Charset cs) * * OutputStreamWriter(OutputStream out, CharsetEncoder enc) */ @Test public void testOSWContructor() throws Exception{ FileOutputStream fos = new FileOutputStream("rw.txt"); //构造方法OutputStreamWriter(OutputStream out) OutputStreamWriter osw = new OutputStreamWriter(fos); //构造方法OutputStreamWriter(OutputStream out, String charsetName) OutputStreamWriter osw2 = new OutputStreamWriter(fos,"UTF-8"); //构造方法OutputStreamWriter(OutputStream out, Charset cs) Charset cs = Charset.forName("UTF-8"); OutputStreamWriter osw3 = new OutputStreamWriter(fos,cs); //构造方法OutputStreamWriter(OutputStream out, CharsetEncoder enc) CharsetEncoder enc = cs.newEncoder(); OutputStreamWriter osw4 = new OutputStreamWriter(fos,enc); }
5、OutputStreamWriter的原理 该流可以将字符串按照给定的字符集转换为字节后写出。示例代码片段如下: /* * void write(int c) * 写出int值的"低16位"有效,即一个字符 * * void write(String str) * 将给定的字符串写出 * * void write(char[] chs) * 将给定的字符数组写出 * * void write(char[] chs,int off,int len) * 将给定的字符数组以off为起始连续len个写出 */ @Test public void testOSW() throws Exception{ FileOutputStream fos = new FileOutputStream("test_outputsteamwriter.txt"); //构造方法OutputStreamWriter(OutputStream out,String charsetName) OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8"); osw.write("Hello!OutputStreamWriter!"); System.out.println("写出完毕"); osw.close(); }字符流的write方法与之前讲到的IO操作流相似,只是之前讲到的都是以字节为单位读写数据,现在是以字符为单位读取数据了。注意:字符流只能用于文本文档文件,不能用于音频和视频等非文本文档文件。
6、使用字符流读取复制文件源代码分享1)、main方法进行测试,示例代码如下: /* * 这次引入异常处理的概念,下节会继续讲到 * */ public static void main(String[] args){ //可以把抽象路径作为参数 copy("speech.txt","speech_copy.txt"); System.out.println("复制完毕"); }
7、2)、将复制文件的功能封装在一个copy方法中对调用者开放必要参数,复制文件copy方法如下 //复制文件 public static void copy(String docName,String copyName){ FileInputStream fis = null; InputStreamReader isr = null; FileOutputStream fos = null; OutputStreamWriter osw = null; try { //读取文件 fis = new FileInputStream(docName); isr = new InputStreamReader(fis,"UTF-8"); //复制文件 fos = new FileOutputStream(copyName); osw = new OutputStreamWriter(fos,"UTF-8"); int d = -1; while((d=isr.read())!=-1){ osw.write(d); } } catch (FileNotFoundException fnfE) { System.out.println(docName+"文件不存在,请检查输入的文件名称或路径"); fnfE.printStackTrace(); } catch (UnsupportedEncodingException unEncodingE){ System.out.println("编码集无法编译"); unEncodingE.printStackTrace(); } catch (IOException ioE){ System.out.println("读写文件出错"); ioE.printStackTrace(); } finally { if(isr!=null){ try { isr.close(); } catch (IOException e) { System.out.println("字符输入流关闭异常"); e.printStackTrace(); } } if(osw!=null){ try { osw.close(); } catch (IOException e) { System.out.println("字符输出流关闭异常"); e.printStackTrace(); } } } }查看运行结果,见图:分析:项目研发过程中首先要确立需求,将代码模块化,便于单元测试和最终的集成测试,适当的注释能够帮助阅读代码。