---------------------- android培训、java培训、期待与您交流! ---------------------
-一、字符流的缓冲区
1、缓冲区的出现提高了对数据的读写效率
2、对应类
(1)、BufferdWriter
(2)、BufferdReader
3、缓冲区要结合流才可以使用
4、在流的基础上对流的功能进行了增强
5、
void close() 关闭此流,但要先刷新它。
void flush() 刷新该流的缓冲
void newLine() 写入一个行分隔符。 跨平台
/* 缓冲区的出现是为了提高流的操作效率而出现的 所以在创建缓冲区之前,必须要现有流对象。 */ import java.io.*; class Demo{ public static void main(String args[]) throws IOException{ //创建一个字符写入流对象 FileWriter fw = new FileWriter("Demo.txt"); //为了提高字符写入流的效率,加入了缓冲技术,只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可 BufferedWriter bufw = new BufferedWriter(fw); bufw.write("abcde"); bufw.newLine(); bufw.write("fghi"); //只要用到缓冲区,结束时就要刷新, //bufw.flush(); bufw.close();//其实关缓冲区,就是在关闭缓冲区中的流对象。 //fw.close();不用写 } }
二、IO流(BufferedReader)
readLine() 读取一个文本行。返回:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null ,所有要手动写入换行
/* 字符读取流缓冲区: 该缓冲区提供了一个一次读一行的方法 readLine ,方便于对文本数据的获取 当返回 null 时,表示读到文件的末尾 readLine() 方法返回的时候只返回回车符之前的数据内容,并不返回回车符 */ import java.io.*; class Demo{ public static void main(String args[]) throws IOException{ //创建一个读取流对象和文件相关联 FileReader fr = new FileReader("Demo.java"); //为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数 BufferedReader bufr = new BufferedReader(fr); String s1 = bufr.readLine(); System.out.println(s1); } }
三、IO流(通过缓冲区复制文本文件)
/* 通过缓冲区复制一个 .java 文件 */ import java.io.*; class Demo{ public static void main(String args[]) throws IOException{ BufferedReader bufr = null; BufferedWriter bufw = null; try{ bufr = new BufferedReader(new FileReader("Demo.java")); bufw = new BufferedWriter(new FileWriter("Demo.txt")); //每行数据临时变量 String line = null; //循环写入每行数据 while((line = bufr.readLine())!=null){ bufw.write(line); bufw.flush(); bufw.newLine();//必须写 } }catch(IOException e){ throw new RuntimeException("读写失败"); }finally{ //关闭读取流 try{ if(bufr!=null) bufr.close(); }catch(IOException e){ throw new RuntimeException("读关闭失败"); } //关闭写入流 try{ if(bufw!=null) bufw.close(); }catch(IOException e){ throw new RuntimeException("写关闭失败"); } } } }
四、IO流(readLine的原理图例)
readLine()方法原理
不论是读一行,获取多个字符,其实最终都是在硬盘上一个一个读取,所以最终使用的还是 read() 方法一次读一个的方法
因为跨平台性,换行符不一样,所以读取的时候缓存中不存入换行,让使用者自己输入换行
五、IO流(MyBufferedReader)
明白了 BufferedRead 类中特有方法 readLine 的原理后,
可以自定义一个类中包含一个功能和readLine一致的方法
来模拟一下BufferedReadLine
/* 通过缓冲区复制一个 .java 文件 */ import java.io.*; class Demo{ public static void main(String args[]) throws IOException{ FileReader fr = new FileReader("Demo.java"); MyBufferedReader myBuf = new MyBufferedReader(fr); String line = null; while((line=myBuf.myReadLine())!=null){ System.out.println(line); } myBuf.myClose(); } } class MyBufferedReader{ private FileReader fr; MyBufferedReader(FileReader fr){ this.fr = fr; } //可以一次读一行数据的方法 public String myReadLine() throws IOException{ //定义一个临时容器,原BufferedReader封装的是字符数组 //为了方便,定义一个StringBuilder容器,因为最终还是要将数据变成字符串 StringBuilder sb = new StringBuilder(); int ch = 0; while((ch=fr.read())!=-1){ if(ch=='\r') continue; if(ch=='\n') return sb.toString(); else sb.append((char)ch); } //防止最后一行没有换行的情况 if(sb.length()!=0){ return sb.toString(); }else{ return null; } } public void myClose() throws IOException{ fr.close(); } }
六、IO流(装饰设计模式)
1、当想要对已有对象进行功能增强时,可以定义一个类,将已有对象传入,基于已有的功能,并提供加强功能,那么该自定义类称为装饰类
2、装饰类通常会通过构造方法接收被装饰的对象。并基于被装饰的功能,提供更强的功能。
七、IO流(装饰和继承的区别)
八、IO流(自定义装饰类)
九、IO流(LineNumberReader)
跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。
import java.io.*; class Demo{ public static void main(String args[]) throws IOException{ FileReader fr = new FileReader("Demo.java"); LineNumberReader lnr = new LineNumberReader(fr); String line = null; lnr.setLineNumber(2); while((line=lnr.readLine())!=null){ System.out.println(lnr.getLineNumber()+":"+line); } lnr.close(); } }
十、IO流(MyineNumberReader)
自己写的修饰类
import java.io.*; class Demo{ public static void main(String args[]) throws IOException{ FileReader fr = new FileReader("Demo.java"); myLineNumberReader lnr = new myLineNumberReader(fr); String line = null; while((line=lnr.myReadLine())!=null){ System.out.println(lnr.myGetLineNumber()+":"+line); } lnr.close(); } } class myLineNumberReader{ private BufferedReader br = null; private int lineNumber = 0; myLineNumberReader(FileReader fr){ br = new BufferedReader(fr); } public void lineNumberadd(){ lineNumber++; } public int myGetLineNumber(){ return lineNumber; } public String myReadLine() throws IOException{ lineNumberadd(); return br.readLine(); } public void close() throws IOException{ br.close(); } }
十一、IO流(字节流File读写操作)
/* 字符流 FileReader FileWriter BufferedReader BufferedWriter 字节流 InputStream OutputStream */ /* 需求:想要操作图片数据。据悉要到字节流 */ import java.io.*; class Demo{ public static void main(String args[]) throws IOException{ //writeFile(); readFile_3(); } //写文件 public static void writeFile() throws IOException{ FileOutputStream fos = new FileOutputStream("demo.txt"); fos.write("ab张c".getBytes()); fos.close(); } //读文件 第一种方式 public static void readFile_1() throws IOException{ FileInputStream fis = new FileInputStream("demo.txt"); int ch = 0; while((ch=fis.read())!=-1){ System.out.println((char)ch); } fis.close(); } //读文件 第二种方式 这种适用 public static void readFile_2() throws IOException{ FileInputStream fis = new FileInputStream("demo.txt"); byte[] buf = new byte[1024]; int len = 0; while((len = fis.read(buf))!=-1){ System.out.println(new String(buf,0,len)); } fis.close(); } //读文件 第三种方式 这种内存太大 public static void readFile_3() throws IOException{ FileInputStream fis = new FileInputStream("demo.txt"); byte[] buf = new byte[fis.available()]; fis.read(buf); System.out.println(new String(buf)); fis.close(); } }
十二、IO流(拷贝图片)
/* 复制一个图片 思路: 1、用字节读取流对象和图片关联 2、用字节写入流对象创建一个图片文件。用于存储获取到的图片数据 3、通过循环读写,完成数据的存储 4、关闭资源 */ import java.io.*; public class Demo{ public static void main(String args[]){ FileOutputStream fos = null; FileInputStream fis = null; try{ fos = new FileOutputStream("yujinxiang.jpg"); fis = new FileInputStream("C:\\Users\\Public\\Pictures\\Sample Pictures\\yujinxiang.jpg"); byte[] buf = new byte[1024]; int len = 0; while((len=fis.read(buf))!=-1){ fos.write(buf,0,len); } }catch(IOException e){ throw new RuntimeException("复制文件失败"); }finally{ try{ if(fis!=null){ fis.close(); } }catch(IOException e){ throw new RuntimeException("读取关闭失败"); } try{ if(fos!=null){ fos.close(); } }catch(IOException e){ throw new RuntimeException("写入关闭失败"); } } } }
十三、IO流(字节流的缓冲区)
BufferedInputStream
BufferedInputStream
/* 演示MP3的复制,通过缓冲区 BufferedInputStream BufferedOnputStream */ import java.io.*; public class Demo{ public static void main(String args[])throws IOException{ long start = System.currentTimeMillis(); copy_mp3(); long end = System.currentTimeMillis(); } public static void copy_mp3()throws IOException{ BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("C:\\Users\\Public\\Music\\Sample Music\\Kalimba.mp3")); BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("Kalimba.mp3")); int by = 0; while((by=bufis.read())!=-1){ bufos.write(by); } bufis.close(); bufos.close(); } }
十四、IO流(自定义字节流的缓冲区-read和write的特点)
import java.io.*; public class Demo{ MYBufferedInputStream bufis = new MYBufferedInputStream(new FileInputStream("C:\\Users\\Public\\Music\\Sample Music\\Kalimba.mp3")); BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("Kalimba.mp3")); int by = 0; while((by=bufis.myRead())!=-1){ bufos.write(by); } bufis.myclose(); bufos.close(); } class MyBufferedInputStream{ private InputStream in; private byte[] buf = new byte[1024]; private int pos =0,count = 0; MyBufferedInputStream( InputStream in){ this.in = in; } //一次读一个字节,从缓冲区(字节数组)获取 public int myRead(){ //通过 in 对象 读取硬盘上数据,并存储 buf 中 if(count==0){ count = in.read(buf); if(count<0) return -1; pos = 0; byte b = buf[pos]; count--; pos++; return b&255; }else if(count>0){ byte b = buf[pos]; count--; pos++; return b&255; } } public void myclose(){ in.close(); } }
十五、15-IO流(读取键盘录入)
System.out:对应的是标准输出设备:控制台
System.in:对应的是标准输入设备 :键盘
/* 需求,通过键盘录入数据。 当录入一行数据后,就将改行数据进行打印,如果录入数据是over,那么停止录入 */ import java.io.*; public class Demo{ public static void main(String args[]) throws IOException{ InputStream in = System.in; StringBuilder sb = new StringBuilder(); while(true){ int ch = in.read(); if(ch=='\r') continue; if(ch=='\n'){ String s = sb.toString(); if("over".equals(s)) break; System.out.println(s.toUpperCase()); sb.delete(0,sb.length()); }else{ sb.append((char)ch); } } } }
十六、IO流(读取转换流)
通过键盘录入一行数据,并打印其大写,发现其实就是读一行数据的原理,也就是readLine方法来完成键盘录入的一行数据的读取呢?
/* 需求,通过键盘录入数据。 当录入一行数据后,就将改行数据进行打印,如果录入数据是over,那么停止录入 */ import java.io.*; public class Demo{ public static void main(String args[]) throws IOException{ //获取键盘录入对象 InputStream in = System.in; //将字节流对象转换成字符流对象,使用转换流,InputStreamReader InputStreamReader isr = new InputStreamReader(in); //为了提高效率,将字符进行缓冲区技术高效操作,使用bufferedReader BufferedReader bufr = new BufferedReader(isr); String line = null; while((line = bufr.readLine())!=null){ if(line.equals("over")){ break; } System.out.println(line.toUpperCase()); } bufr.close(); } }
十七、IO流(写入转换流)
/* 需求,通过键盘录入数据。 当录入一行数据后,就将改行数据进行打印,如果录入数据是over,那么停止录入 */ import java.io.*; public class Demo{ public static void main(String args[]) throws IOException{ //获取键盘录入对象 InputStream in = System.in; //将字节流对象转换成字符流对象,使用转换流,InputStreamReader InputStreamReader isr = new InputStreamReader(in); //为了提高效率,将字符进行缓冲区技术高效操作,使用bufferedReader BufferedReader bufr = new BufferedReader(isr); //以上可以用一句话代替 //BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); OutputStream out = System.out; OutputStreamWriter osw = new OutputStreamWriter(out); BufferedWriter bufw = new BufferedWriter(osw); //以上可以用一句话代替 //BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while((line = bufr.readLine())!=null){ if(line.equals("over")){ break; } bufw.write(line.toUpperCase()); bufw.newLine(); bufw.flush(); } bufr.close(); } }
十八、IO流(流操作规律-1)
1、 源:键盘录入
目的:控制台
2、 源:键盘
目的:文件
/* 需求,通过键盘录入数据。 当录入一行数据后,就将改行数据进行打印,如果录入数据是over,那么停止录入 */ import java.io.*; public class Demo{ public static void main(String args[]) throws IOException{ //获取键盘录入对象 InputStream in = System.in; //将字节流对象转换成字符流对象,使用转换流,InputStreamReader InputStreamReader isr = new InputStreamReader(in); //为了提高效率,将字符进行缓冲区技术高效操作,使用bufferedReader BufferedReader bufr = new BufferedReader(isr); //以上可以用一句话代替 //BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("demo.txt")); BufferedWriter bufw = new BufferedWriter(osw); //以上可以用一句话代替 //BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while((line = bufr.readLine())!=null){ if(line.equals("over")){ break; } bufw.write(line.toUpperCase()); bufw.newLine(); bufw.flush(); } bufr.close(); } }
3、需求:想要讲一个文件的数据打印在控制而台上
源:文件
目的:控制台
/* 需求,通过键盘录入数据。 当录入一行数据后,就将改行数据进行打印,如果录入数据是over,那么停止录入 */ import java.io.*; public class Demo{ public static void main(String args[]) throws IOException{ //将字节流对象转换成字符流对象,使用转换流,InputStreamReader InputStreamReader isr = new InputStreamReader(new FileInputStream("Demo.java")); //为了提高效率,将字符进行缓冲区技术高效操作,使用bufferedReader BufferedReader bufr = new BufferedReader(isr); //以上可以用一句话代替 //BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); OutputStream out = System.out; OutputStreamWriter osw = new OutputStreamWriter(out); BufferedWriter bufw = new BufferedWriter(osw); //以上可以用一句话代替 //BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while((line = bufr.readLine())!=null){ if(line.equals("over")){ break; } bufw.write(line.toUpperCase()); bufw.newLine(); bufw.flush(); } bufr.close(); } }
4、流操作的基本规律:最痛苦的就是流对象有很多,不知道该用那一个
通过明确来完成。
(1)、明确源和目的
源:输入流 InputStream Reader
目的:输出流 OutputStream Writer
(2)、操作的数据是否是纯文本
是:字符流
不是:字节流
(3)、当体系明确后,再明月要使用那个具体的对象
通过设备来进行区分:
源设备:内存 硬盘 键盘
目的设备:内存 硬盘 控制盘
5、需求
(1)、将一个文本文件中数据存储到另一个文件中。复制文件
源:
因为是源,所以使用读取流。IputStream reader
是不是操作文本文件:
是,所以使用 Reader
家下来明确要使用该体系中的那个对象:
明确设备,硬盘,一个文件,
Reader 体系中可以操作文件的是,FileReader
FileReader fr = new FileReader("a.txt");
是否需要提高效率?
BufferedReader bufr = new BufferedReader(fr);
目的:
OutputStream Writer
是否是纯文本
是:wirter
设备
硬盘,一个文件
Writer体系中可以操作文件的对象 FileWriter
FileWriter fw = new FileWriter("b.txt");
是否需要提高效率?
BufferedWriter bufr = new BufferedWriter(fr);
练习:讲一个图片文件中数据存储到另一个文件中。复制文件。要按照以上格式自己完成三个明确
十九、IO流(流操作规律-2)
1、需求:将键盘录入的数据保存到一个文件中
这个需求中有源和目的都存在,那么分别分析
源:InputStream Reader
是不是纯文本?:是纯文本,用Reader
是不是设备?:是,键盘,对应的对象是 System.in
不是选择Reader吗?System.in 对应的不是字节流吗?
为了操作键盘的文本数据方便,字节流可以转换成字符流,按照字符串操作最方便。
既然明确了 Reader 就将 System.in 转换成 Reader
用到了Reader 体系中的转换流,InputSteamReader
InputStreamReader isr = InputStreamReader(System.in);
需要提高效率吗?需要,BufferedReader
BufferedReader bufr = new BufferedReader(isr);
目的:OutputStream Writer
是否是纯文本?是,Writer
是不是设备?是,硬盘,使用,FileWriter
FileWriter fw = new FileWriter("b.txt");
需要提高效率吗?需要
BufferedWriter bufw = new BufferedWriter(fw);
2、扩展
想要把录入的数据按照指定的编码表(UTF-8),将数据存到文件中,使用转换流,里面可以指定编码
目的:OutputStream Writer
是否是纯文本?是,Writer
是不是设备?是,硬盘,使用,FileWriter
但是存储是,需要加入指定的编码表,而制定的编码表,只有转换流可以指定。
所以要使用的对象是 OutputStreamWriter.
而该转换流对象要接收一个字节输出流。而且还可以操作文件的字节输出流,FileOutputStream
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");
需要高效吗?需要
BufferedWriter bufw = new BufferedWriter(osw);
所以,记住,转化暖流什么时候使用,字符和字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流
3、讲一个文本数据打印在控制台上
二十、IO流(改变标准输入输出设备)
static void setIn(InputStream in)
重新分配“标准”输入流。
static void setOut(PrintStream out)
重新分配“标准”输出流。
二十一、21-IO流(异常的日志信息)
import java.io.*; import java.util.*; import java.text.*; public class Demo{ public static void main(String args[]){ try{ int[] arr = new int[2]; System.out.println(arr[3]); }catch(Exception e){ try{ Date d = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String s = sdf.format(d); PrintStream ps = new PrintStream("exeception.txt"); ps.println(s); System.setOut(ps); }catch(IOException ex){ throw new RuntimeException("日志文件创建失败"); } e.printStackTrace(System.out); } } }
二十二、IO流(系统信息)
import java.io.*; import java.util.*; import java.text.*; import java.text.*; public class Demo{ public static void main(String args[]) throws IOException{ Properties prop = System.getProperties(); prop.list(new PrintStream("demo.txt")); } }
---------------------- android培训、java培训、期待与您交流! ----------------------