IO流概述
一、IO即Input、Ouput组合;
二、IO流特点:
1、IO流用来处理设备之间的数据传输
2、Java对数据的操作是通过流的方式
3、Java用于操作流的对象都在IO包中
三、IO流分类
1、按照操作数据分:字符流和字节流
字节流:字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的(如图片,音频)
字符流:字符流只能操作纯字符数据,比较方便(不能操作音频和图片)。
2、按照流向分为:输入流和输出流
四、字节流和字符流
1、字节流的抽象基类
InputStram(输入流),OutputSteam(输出流)
2、字符流的抽象基类
Reader(输入流)、Writer(输出流)
住:由这四个类派生出来的子类的名称都是以其父类名称作为后缀来命名的
如:InputStream的子类FileInputSteam
OutputStram的子类FileOutputStram
Reader的子类FileReader
Writer的子类FileWriter
字符流
一、字符流是什么?
1、字符流是可以直接读取字符的IO流
2、字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要写出字符, 需要把字符转为字节再写出.
二、FielReader和FileWriter
FileReader
<span style="font-size:14px;">/*FileReader 步骤:1、创建文件读取流对象,并指定路径下的文件名称,如果没指定路径, 则默认是读取该源文件所在的路径下的文件 2、调用读取流对象的read方法,返回读取的字符在ASCII中对应的数字, 如果读取到则返回-1 3、因为没调用一次read方法,仅仅只是读取一个字符,所以要使用循环 4、关闭流 */ import java.io.*; class FileReaderDemo { public static void main(String[] args) { /*FileReader是IO流中的字符输入流,是从硬盘上读取数据用的*/ //步骤1 FileReader fr = null; try{ fr = new FileReader("d:\\file.txt"); //会抛出FileNotFoundException异常 /*因为是读取文件,所以要指定文件以及文件所在的路径,必须保证文件存在 如果要读取得文件不存在,则会发生FileNotFoundException文件找不到异常 */ //步骤2 int charNum = 0; //调用read方法,循环读取文件 while((charNum = fr.read())!=-1){ //read会抛出IOExcepion异常 System.out.print((char)charNum); } } catch(IOException e){ System.out.println(e.toString()); } finally{ //流是必须要关闭的,所以放在finally语句块中 try { if(fr!=null) fr.close(); //会抛出IOException异常 } catch (IOException e) { System.out.println(e.toString()); } } } } </span>
注:输出流中flush和close的区别:
flush是用来刷新缓冲区的,刷完之后还可以写出
close方法是用来关闭流的,在关闭之前会刷新一次缓冲区,刷完之后关闭,不可以再写出
FileWriter
<span style="font-size:14px;">/*FileReader 步骤:1、创建文件写入流对象,并指定路径下的文件名称,如果该路径下没有指定文件, 则会在该路径下创建一个文件,如果有则会覆盖 2、调用输入流对象的write方法,将数据写入文件中 3、清空缓存或关闭流 */ import java.io.*; class FileWriterDemo { public static void main(String[] args) { /*FileWriter是IO流中的字符输出流,是将读取到的数据写入指定文件中*/ //步骤1 FileWriter fw = null; try{ fw = new FileWriter("d:\\file_Copy.txt"); //会抛出IOException异常 //步骤2 fw.write("abcdefg"); } catch(IOException e){ System.out.println(e.toString()); } finally{ //流是必须要关闭的,所以放在finally语句块中 try { if(fw!=null) fw.close(); //会抛出IOException异常 } catch (IOException e) { System.out.println(e.toString()); } } } } </span>
三、什么情况下使用字符流
1、字符流也可以拷贝文本文件,但不推荐使用,因为读取时会把字节转换成字符,写入时会把字符转回字节
2、程序需要读取一段文本,或者需要写出一段文件的时候可以使用字符流
四、字符流是否可以拷贝非纯文本的文件
1、不可以拷贝非纯文本的文件
2、因为在读的时候会将字节转换为字符,在转换过程中,可能找不到对应的字符,就会用?代替,写出的时候会将字符转换成字节写出去
3、如果是?,直接写出,这样写出之后的文件就乱了,看不了了
五、自定义的数组拷贝
<span style="font-size:14px;">/*自定义数组拷贝 提高效率 思路:当使用FileReader的read方法时,一次只读取一个字符调用一次输出一次, 比较麻烦,所以我们能不能把读取的数据存入数组中,等达到一定数量后,在输出呢? 步骤:1、定义输入输出流 2、定义数组,用于保存读取到的数据 3、将数组中的数据写入到指定文件中 */ import java.io.*; class FileReaderFileWriterDemo { public static void main(String[] args) { //定义输入流 FileReader fr = null; //定义输出流 FileWriter fw = null; try { fr = new FileReader("d:\\file.txt"); fw = new FileWriter("d:\\file_copy.txt"); //定义数组存放字符 char [] ch = new char[10]; //这里一般把数组的长度定义成1024也就是2kB int index = 0; //把读到的字符存入数组 while((index = fr.read(ch))!=-1){ //从字符中读取数据写入文件中 fw.write(ch,0,index); fw.flush(); } } catch (IOException e) { System.out.println(e.toString()); } finally{ //分别关闭输入输出流 try { if(fr!=null) fr.close(); } catch (IOException e) { System.out.println(e.toString()); } finally{ try { if(fw!=null) fw.close(); } catch (IOException e) { System.out.println(e.toString()); } } } } } </span>
六、带缓冲的字符流
1、BufferedReader的read()方法读取字符时会一次读取若干字符到缓冲区, 然后逐个返回给程序, 降低读取文件的次数, 提高效率
2、BufferedWriter的write()方法写出字符时会先写到缓冲区, 缓冲区写满时才会写到文件, 降低写文件的次数, 提高效率
注:1、BufferedReader中有一个特有的方法 readerLine() 用于读取一行文本,还有就是用readerLine读取的数据不会自动换行,那是因为readerLine方法返回的时候只返回回车符之前的数据内容,并不返回回车符
2、 BufferedWriter中也有一个特有的方法 newLine() 是一个跨平台的换行符
<span style="font-size:14px;">/*带缓冲的字符流 */ import java.io.*; class BufferedReaderBufferedWriterDemo { public static void main(String[] args) { BufferedReader br = null; BufferedWriter bw = null; try { br = new BufferedReader(new FileReader("d:\\file.txt")); bw = new BufferedWriter(new FileWriter("d:\\file_copy.txt")); /*缓冲区的作用是为了提高流的操作效率而出现的,所以在创建缓冲区 之前,必须要先有流对象,所以要把流对象作为实际参数传递给缓冲区 的构造函数*/ String str = ""; while((str=br.readLine())!=null){ bw.write(str); bw.newLine(); bw.flush(); } } catch (IOException e) { System.out.println(e.toString()); } finally{ //分别关闭输入输出流 try { if(br!=null) br.close(); } catch (IOException e) { System.out.println(e.toString()); } finally{ try { if(bw!=null) bw.close(); } catch (IOException e) { System.out.println(e.toString()); } } } } } </span>
七、写一个自己的缓冲区
<span style="font-size:14px;">/* 明白了BufferedReader类中特有方法readLine的原理后, 可以自定义一个类中包含一个功能和readLine一致的方法。 来模拟一下BufferedReader */ import java.io.*; class MyBufferedReader { private FileReader fr; MyBufferedReader(FileReader fr){ this.fr = fr; } public String readLine()throws IOException{ int charNum = 0; String str = ""; while((charNum = fr.read())!=-1){ if(charNum=='\r') continue; if(charNum=='\n') return str; else str+=(char)charNum; } if(str.length()!=0) return str; return null; } public void close()throws IOException{ fr.close(); } } class MyBufferedReaderMyBufferedWriterDemo { public static void main(String[] args) { MyBufferedReader br = null; BufferedWriter bw = null; try { br = new MyBufferedReader(new FileReader("d:\\file.txt")); bw = new BufferedWriter(new FileWriter("d:\\file_copy.txt")); String str = ""; while((str=br.readLine())!=null){ bw.write(str); bw.newLine(); bw.flush(); } } catch (IOException e) { System.out.println(e.toString()); } finally{ //分别关闭输入输出流 try { if(br!=null) br.close(); } catch (IOException e) { System.out.println(e.toString()); } fi