IO流学习笔记(一)之FileWriter与FileReader
2017-06-03 16:56
633 查看
IO流
IO流用来处理设备之间的数据传输Java对数据的操作是通过流的方式
Java用于操作流的对象都在IO包中
流按照操作数据分为两种:字节流和字符流
流按流向分为:输入流和输出流
输入流和输出流是相对于内存设备而言
因为内存速度快,程序在内存中运行,数据从外设(硬盘)读取到内存中为输入,数据由内存到外设(硬盘)为输出
字符流的由来:
字节流可以处理所有数据,最早是没有字符流的,但是由于不同语言产生了多张码表(用于将其语言转为计算机语言即01码,如ascll,GBK等),由于多张码表的麻烦,国际组织便产生一张通用的码表Unicode码表,可以识别中英文等,Java中内置Unicode码表。其特点是无论什么字符都用两个字节表示,导致同一个中文在GBK和Unicode码表中对应的数字结果不同(因为对于编写程序选择不同编码方式会产生乱码),将(字节流+编码表)的组合方式封装为字符流。
简要来说:字节流读取文字字节数据后,不直接操作,而是先查指定的编码表,获取对应的文字,再对这个文字进行操作。简单来说,就是字节流+编码表。
分类:
字节流的抽象基类:InputStream,OutputStream
字符流的抽象基类:Reader,Writer
注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀,如InputStream的子类FileInputStream,Reader的子类FileReader
命名方式可以看作:该对象的功能+以父类名作为后缀
操作文字数据建议优先考虑字符流,而且要将数据从内存写到硬盘上,要使用字符流中的输出流Writer类,将数据从内存写到硬盘上,硬盘上的数据基本体现是文件,希望找到一个可以操作文件的Writer,即FileWriter
FileWriter
既然是往一个文件中写入文字数据,那么在创建对象时,必须明确该文件(用于存储数据的目的地),如果文件不存在,则会自动创建;如果文件存在,则会被覆盖,由于文件路径可能是非法路径,会导致IO异常,因此在方法处抛出,即throws IOException构造函数:
FileWriter(String fileName):根据给定的文件名构造一个FileWriter对象
FileWriter(String fileName,boolean append):根据给定的文件名以及指示是否附加(续写)写入数据的boolean值来构造FileWriter对象,构造函数中加入true,可以实现对文件进行续写,不然第二次运行程序会删除原有内容,续写,即可以再次运行写入时,是在原有的基础上基础写入,原内容是保存的
public class FileWriterDemo { /* 平台独立的换行符。 */ public static final String LS = System.getProperty("line.separator"); public static void main(String[] args) throws IOException { FileWriter fw = new FileWriter("demo.txt");//new对象时其实已经开始对硬盘进行操作 fw.write("abcde\r\nhahaha"); fw.write("abcde"+ LS+"nhahaha");//无论什么系统都可以实现换行 fw.close(); } }
flush()与close()区别:
flush()方法:刷新该流的缓冲,如果该流已保存缓冲区中各种write()方法的所有字符,则立即将它们写入预期目标。然后,
如果该目标是另一个字符或字节流,则将其刷新。因此,一次flush()调用将刷新Writer和OutputStream链中的所有缓冲区,因此上述写入也可以:
fw.write("abcde\r\nhahaha"); fw.write("abcde"+ LS+"nhahaha"); fw.flush();
close()关闭流,关闭资源。在关闭前会先调用flush刷新缓冲中的数据到目的地
与flush()的区别:flush可以使用多次,不断写入不断刷新即可,而close只可以使用一次,关闭之后,不可以进行流操作。 形象比喻:在一个文档中写数据,每保存一次就相当于进行一次flush(不保存并没有写入硬盘);如果一直写不保存,写完之后关闭,进行一次保存,写入硬盘,相当于close,再打开文件操作时,是另一个流。
换行问题:
fw.write("abcde\nhahaha")
并不能实现换行,windows中的换行是\r,unix中换行是\n,因此需要
fw.write("abcde\r\nhahaha");,还有一种与系统无关的换行方式:
public static final String LS = System.getProperty("line.separator");
IO异常的处理方式
public class IOExceptionDemo { public static final String LS = " " + System.getProperty("line.separator"); public static void main(String[] args) { /* 流对象异常的处理方式是在try块外创建引用变量,在try块里面进行对象的初始化 */ FileWriter fw = null; try { fw = new FileWriter("demo.txt"); fw.write("abcde"+ LS +"nhahaha"); } catch (IOException e) { e.printStackTrace(); }finally { //因为在之前创建fw对象时,如果是无效的路径,无法创建fw对象,此处可能空指针异常NullPointerException if (fw!=null){ try { fw.close();//关闭资源的异常是由底层造成的 } catch (IOException e) { throw new RuntimeException("关闭失败"); } } } } }
FileReader
进行读取有两种方式,一种是read()方法,一种是read(char[] cbuf)方法,如下将分别介绍两种方法:read()方法
public int read() throws IOException:读取单个字符,在字符可用,发生I/O错误或者已到达流的末尾前,此方法一直阻塞
返回:作为整数读取的字符,范围在0到65535之间,如果已到达流的末尾,则返回-1
public class FileReaderDemo { public static void main(String[] args) throws IOException { //1.创建读取字符数据的流对象 /* 构造函数其一: FileReader(String fileName):在给定从中读取数据的文件名的情况下创建一个新的FileReader 在创建读取流对象时,必须要明确读取的文件,一定要确定该文件是存在的 用一个读取流关联一个已经存在的文件 */ FileReader fr = new FileReader("demo.txt");//与文件关联 //用Reader中的read方法读取字符,此时文本中的数据是“ab”,硬盘中存储的是二进制,例如a对应的是97,b对应的是98 int ch = fr.read(); System.out.println(ch); System.out.println((char)ch); int ch1 = fr.read(); System.out.println(ch1); int ch2 = fr.read(); System.out.println(ch2);//到达结尾如扔继续读取,仍是-1 //图例假设结束标记是#,当读取到结束标记时,JVM为了表明读到了结尾,用-1表示 } }
运行结果:
原理:
基于如上原理可以如下进行连续读取,即连续读取数据的第一种方式,一次读一个
int ch = 0; while((ch=fr.read())!=-1){ System.out.println((char)ch);//转为字符进行输出 }
read(char[] cbuf)方法
public int read(char[] cbuf) throws IOException:将字符读入数组。在某个输入可用,发生I/O错误或者已到达流的末尾前,此方法一直阻塞
参数:
cbuf-目标缓冲区
返回:
读取的字符数(不同于read()方法,read()方法返回的是读到的字符),如果已到达流的末尾,则返回-1
不同于read(),read(char[] cbuf)是每读取一个便将其存与数组cbuf中
public class FileReaderDemo2 { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("demo.txt");//与文件关联 char[] buf = new char[3];//txt文本中是“abcde" int num = fr.read(buf);//将读到的字符存储到数组中,此时内容abc System.out.println(num+":"+new String(buf)); int num1 = fr.read(buf);//将读到的字符存储到数组中,此时内容dec System.out.println(num1+":"+new String(buf)); int num2 = fr.read(buf);//将读到的字符存储到数组中,此时内容dec,因为已经到达末尾,并没有读取到新字符 System.out.println(num2+":"+new String(buf)); fr.close(); } }
原理:
基于第二种读取方式的连续读取:
int len = 0; while((len=fr.read(buf))!=-1){ System.out.println(new String(buf,0,len)); }
两种读取方式哪种好?
第二种读取所需的循环次数少,效率高,第一种方式有多少个字符就需要循环多少次
复制文本文件
public class CopyText { private static final int BUFFER_SIZE = 1024; public static void main(String[] args){ FileReader fr = null; FileWriter fw = null; try { fr = new FileReader("demo.text"); fw = new FileWriter("test.text"); //创建一个容器,用于读取缓冲字符 char[] buf = new char[BUFFER_SIZE]; int len = 0; while ((len=fr.read(buf))!=-1){ fw.write(buf,0,len); } }catch (Exception e){ throw new RuntimeException("读写失败"); }finally { if (fr!=null) try { fr.close(); } catch (IOException e) { e.printStackTrace();//如果是图形化界面,这些语句实际就是弹出的对话框 } if (fw!=null) try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } } }
两个流(输入流fr与输出流fw)原本是没有关系的,想要使两者能够进行数据传输,需要通过一个“中转”即上述的数组容器
相关文章推荐
- 学习笔记之IO流(FileReader,FileWriter,文件拷贝)
- 字符流学习笔记及总结(FileWriter、FileReader、BufferedWriter、BufferedReader)
- Java SE学习笔记:File类、IO流以及他们的经典案例
- Java基础 - IO流之字符流,FileReader,FileWriter,BufferedReader,BufferedWriter,装饰设计模式,编码表
- 黑马程序员_java_IO流_FileWriter_FileReader_BufferedWriter_BufferedReader_IO异常
- IO流之创建文件并filereader、filewriter 读写操作
- java学习10--InputStreamReader,OutputStreamWriter,FileReader,FileWriter,BufferedReader,BufferedWriter
- 黑马程序员_IO流 FileReader和FileWriter
- java学习笔记之FileReader FileWriter
- 【学习笔记】Java IO流(1)--字符输出流FileWriter
- IO流中FileWriter和FileReader之一
- 黑马程序员---2015.6.24java基础笔记--FileWriter- FileReader-BufferedWriter-BufferedReader
- 常见io流-------文件字符流FileReader、FileWriter。可以直接操作char型字符
- Java基础知识强化之IO流笔记37:FileReader/FileWriter(转换流的子类)复制文本文件案例
- Java学习笔记之IO流中的File类
- file跟io流的学习笔记
- io流之file文件类fileReader和FileWriter的读写操作
- 【JavaSE学习笔记】IO流01_File
- 黑马程序员_基础_IO流学习笔记_File对象功能
- java基础之IO流中的FileReader和FileWriter的认识和实现