IO流(二)
一.IO流分类
根据流向可以分为:输入流和输出流
根据处理数据类型可以分为:字节流和字符流
二.思维导图
三.字符流
3.1 Writer 是输出流,用于 写,是抽象类,常用子类:BufferedWriter,OutputStreamWriter,PrintWriter。FileWriter是OutputStreamWriter的子类。
BufferedWriter 是带缓冲的输出流。提高了性能。
OutputStreamWriter是字符流通向字节流的桥梁。
PrintWriter 打印流,提供了print 系列的方法。
FileWriter 是操作的文件的便捷类。
Reader 是输入流,用于读,同样也是抽象类。常用子类:BufferedReader,InputStreamReader。而FileReader是InputStreamReader的直接子类。
BufferedReader:带缓冲的输入流。
InputStreamReader:字节流通向字符流的桥梁。
FileReader,操作文件的便捷类
3.1.2 字符流一般处理文本文件,输出字符入门例子:
1 public static void main(String[] args) 2 { 3 fw(); 4 } 5 6 7 8 public static void fw() 9 { 10 FileWriter fw = null; 11 try 12 { 13 fw = new FileWriter("2.txt"); 14 15 fw.write("ssss"); 16 17 fw.append('a'); 18 19 20 } catch (IOException e) 21 { 22 e.printStackTrace(); 23 }finally 24 { 25 try 26 { 27 if(fw != null) 28 fw.close(); 29 } catch (IOException e) 30 { 31 // TODO Auto-generated catch block 32 e.printStackTrace(); 33 } 34 } 39 }
运行结果:在当前目录会创建 ” 2.txt “ 文件。里面的内容是 "ssssa"。
注1:异常处理一般都是捕获 。
注2:如果当前目录已经存在 “2.txt” ,那么执行代码会将 “2.txt” 文件删除,再创建一个新的 “2.txt” 文件。
3.2 文件续写:如果想在原来的文本后面接着写,而不是覆盖掉原本的文本文件。那么需要不同的构造函数。
利用不同的构造函数。
FileWriter fw = new FileWriter("2.txt",true);
3.3 文件读取方式
3.3.1 read() 读取单个字符,返回 int 类型(返回的是读取的字符),如果已经达到流的末尾,返回-1.
例:
public static void read() { FileReader fr = null; try { fr = new FileReader("2.txt"); int r = 0; while((r=fr.read())!=-1) { System.out.print((char)r); } } catch (Exception e) { e.printStackTrace(); }finally { try { if(fr != null) fr.close(); } catch (IOException e) { e.printStackTrace(); } } }
3.3.2 read( char[] cbuf) 将字符读入数组中,返回int 型,(返回的是读取字符的个数)如果已经达到流的末尾则返回-1.
例:
public static void readChar() { FileReader fr = null; try { fr = new FileReader("2.txt"); int r = 0; char[] buff = new char[512]; while((r=fr.read(buff))!= -1) { System.out.print(new String(buff,0,r)); } } catch (IOException e) { e.printStackTrace(); }finally { try { if(fr!=null) fr.close(); } catch (IOException e) { e.printStackTrace(); } } }
3.4 文件拷贝练习。
思路:将一个文件读取,然后写入另一个文件。
代码:
public static void copyFile() { //创建输入流读取文件。 FileReader fr = null; //创建输出流,方便写入文件 FileWriter fw = null; try { fr = new FileReader("2.txt"); fw = new FileWriter("d:\\2copy.txt"); int r = 0; char[] buff = new char[512]; while((r=fr.read(buff))!=-1) { //将读到的字符数据写入到要拷贝的文件中。 fw.write(buff, 0, r); } System.out.println("copy 完成"); } catch (IOException e) { e.printStackTrace(); }finally { if(fr != null) try { fr.close(); } catch (IOException e) { e.printStackTrace(); } if(fw != null) try { fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
3.5 BufferedWriter,BufferedReader
前缀有Buffered 的都是带缓冲的。它是使用装饰模式。增强了Reader,Writer 。里面有一些增强方法。
构造方法:BufferedWriter(Writer out) ; BufferedReader(Reader in) ;
注:只要用到了缓冲区,就一定要刷新,即是用 flush() 方法。
例:
public static void readLine() { BufferedReader br = null; try { br = new BufferedReader(new FileReader("2.txt")); String str = null; while((str=br.readLine())!=null) { System.out.println(str); } } catch (Exception e) { }finally { if(br != null) try { br.close(); } catch (IOException e) { e.printStackTrace(); } } }
3.5.1 特有方法:
1.BufferedWriter
newLine() ;跨平台的行分隔符。在Windows下是"\r\n",在Linux下是"\n".
原理:在Windows下:
write("\r\n");
在Linux下:
write("\n");
2.BufferedReader
readLine() ; 读取一行,返回的是字符串。(返回的就是读取到的字符串,可以用于判断,如果流已经被读完,则返回null)。
原理:
Windows下:
public String myReadLine() throws IOException { sb = new StringBuilder(); while((r=fr.read())!=-1) { if(r=='\r') continue; if(r=='\n') return sb.toString(); //① else sb.append((char)r); } if(sb.length()>0) //② return sb.toString(); return null; }
注1:文本最后一行如果没有 回车,就无法执行①,但是StringBuilder中是有数据的,所以需要②来判断。StringBuilder 时候有数据。
注2:如果是linux环境下,就只需要判断是否 等于"\n"。
四.字节流
OutputStream,是字节输出流,抽象类。
入门示例:
public static void fileOut() { FileOutputStream fos = null; try { fos = new FileOutputStream("2.txt"); fos.write(97); } catch (IOException e) { e.printStackTrace(); }finally { if(fos!=null) try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
可以看出,其实字节流和字符流仅仅是“字节”与“字符”之间的差距,在使用时很多用法都是相同的。
同理,BufferedOutputStream,BufferedInputStream和字符流中的BufferedWriter,BufferedReader 一样。
public static void buff() { BufferedOutputStream bos = null; try { bos = new BufferedOutputStream(new FileOutputStream("2.txt")); bos.write(99); bos.flush(); } catch (IOException e) { e.printStackTrace(); }finally { if(bos!= null) try { bos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
4.1 拷贝图片
示例
public static void copyPic() { BufferedInputStream bis = null; BufferedOutputStream bos = null; try { bis = new BufferedInputStream(new FileInputStream("C:\\Users\\Administrator\\Pictures\\Screenshots\\io.png")); bos = new BufferedOutputStream(new FileOutputStream("d:\\ioCopy.png")); byte[] buff = new byte[1024]; int r = 0; while((r=bis.read(buff))!= -1) { bos.write(buff, 0, r); bos.flush(); } System.out.println("拷贝完成"); } catch (IOException e) { e.printStackTrace(); }finally { if(bis!=null) try { bis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(bos!=null) try { bos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
五.其他
5.1 键盘录入
使用System下的in 字段。
public static void jianPan() { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = null; try { while((line=br.readLine())!=null) { if(line.equals("over")) break; System.out.println(line); } } catch (IOException e) { e.printStackTrace(); }finally { if(br!=null) try { br.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
5.2 使用 与System.in 对应的System.out 进行输出
public static void jianPan() { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; try { while((line=br.readLine())!=null) { if(line.equals("over")) break; bw.write(line); bw.flush(); } } catch (IOException e) { e.printStackTrace(); }finally { if(br!=null) try { br.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(bw!=null) try { bw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
注:当使用输出流时,一定要使用flush() 方法刷新。
5.3 改变输入,输出流设备。
默认的输入流是键盘,输出流是控制台。但是,我们也可以改变它。
System.setIn(InputStream in) //改变输入流 System.setOut(PrintStream out) //改变输出流
作用:可以将异常信息写入一个文本文件。
示例:
System.setOut(new PrintStream("exception.log")); try { bw.close(); } catch (IOException e) { e.printStackTrace(System.out); }