day19字符流的缓冲区。自己MyBufferReader的readLine方法。装饰设计模式。字节流。自定义一个缓冲区模拟BufferedInputStream。读取键盘

来源:互联网 发布:知错改错不认错下一句 编辑:程序博客网 时间:2024/05/16 12:02
/*字符流的缓冲区。自己MyBufferReader的readLine方法。装饰设计模式。字节流。自定义一个缓冲区模拟BufferedInputStream。读取键盘录入。转换流。流操作的基本规律*//*字符流的缓冲区缓冲区的出现提高了对流数据的操作效率对应类BufferedWriterBufferedReader缓冲区要结合流才可以使用在流的基础上对流的功能进行了增强很多软件都有自己的缓冲区。比如迅雷。二个构造方法必须有参数,必须有流才能使用。BufferedWriter缓冲区中提供了一个跨平台的换行符。newLine();/r/n不跨平台。*/import java.io.*;class  BufferWriter{public static void main(String[] args) throws IOException{bufWriter();/*//创建一个字符写入流对象FileWriter fw = new FileWriter("buf.txt");//为了提高字符写入流的效率,加入了缓冲技术。//缓冲原理:对象里面封装了数组//只要将需要被提高效率的流对象作为参数传递给//缓冲区的构造方法就可。BufferedWriter bufw =new BufferedWriter(fw);bufw.write("abcde");//记住,只要用到BufferedWriter缓冲区,就要记得刷新bufw.flush();//其实关闭缓冲区,就是在关闭缓冲区中的流对象bufw.close();*/}public static void bufWriter() throws IOException{FileWriter fw = new FileWriter("demo.txt");BufferedWriter bufw = new BufferedWriter(fw);for (int x= 0;x<5 ;x++){bufw.write("abcd"+x);bufw.newLine();//跨平台的换行。bufw.flush();}bufw.close();}}/*字符读取流缓冲区:BufferReader该缓冲区提供了一个一次读一行的方法:readLine(),方便于对文本数据的获取,当读到null时,表示读到文件的末尾。readLine()方法返回的时候只返回回车符之前的数据内容,并不返回回车符。所以我们自己写的时候要加newLine();原理:无论是读一行,获取读取多个字符,其实最终都是在硬盘上一个一个读取,所以最终还是使用read()一次读一个方法。*/import java.io.*;class  BufferReader{public static void main(String[] args) throws IOException{//创建一个读取流对象和文件相关联FileReader fr = new FileReader("demo.txt");//为了提高效率。加入缓冲技术,将字符读取流对象//作为参数传递给缓冲对象的构造函数BufferedReader bufr = new BufferedReader(fr);String s1 = null;while((s1=bufr.readLine())!=null){System.out.println("s1="+s1);}bufr.close();}}/*练习通过缓冲区复制一个.java文件*/import java.io.*;class  BufferCopyJava{public static void main(String[] args) {BufferedReader bufr = null;BufferedWriter bufw = null;try{bufr = new BufferedReader(new FileReader("BufferWriter.java"));bufw = new BufferedWriter(new FileWriter("CopyBufferJava.txt"));String line = null;while ((line = bufr.readLine())!=null){bufw.write(line);bufw.newLine();bufw.flush();}}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("写入关闭失败");}}}}/*定义一个自己MyBufferReader的readLine方法原理:无论是读一行,获取读取多个字符,其实最终都是在硬盘上一个一个读取,所以最终还是使用read()一次读一个方法。*/import java.io.*;class  MyBufferReader{private FileReader r;MyBufferReader(FileReader r){this.r = r;}public String myReadLine() throws IOException{//定义一个临时容器,源程序中封装的是字符数组。//这里为了演示方便,定义一个StringBuilder容器,因为最终还要是将数据变成字符串StringBuilder sb = new StringBuilder();int buf = 0;while((buf=r.read())!= -1){if (buf=='\r'){continue;}if (buf=='\n'){return sb.toString();//sb.delete(0,sb.length());???//是因为return后,sb会自己清空。生命周期。//还是每次都新一个new StringBuilder??}elsesb.append((char)buf);}if (sb.length()!=0){return sb.toString();}return null;}public void myClose()throws IOException{r.close();}}class MyBuffer{public static void main(String[] args) throws IOException{FileReader fr = new FileReader("demo.txt");MyBufferReader mbr = new MyBufferReader(fr);String s = null;while ((s = mbr.myReadLine())!=null){//return s;System.out.println(s);}mbr.myClose();}}/*装饰设计模式:当想要对已有的对象进行功能增强时,可以定义一个类,将已有对象传入,基于已有对象的功能,并提供加强功能那么自定义的该类就称为装饰类装饰类通常会通过构造方法接收被装饰对象,并基于被装饰对象的功能提供更强大的功能。*/class Person{public void chifan(){System.out.println("吃饭");}}class SuperPerson{private Person p;SuperPerson(Person p){this.p = p;}public void superChifan(){System.out.println("开胃酒");//System.out.println("吃饭");p.chifan();System.out.println("甜点");System.out.println("来一根");}}class  PersonDemo{public static void main(String[] args) {Person p = new Person();//p.chifan();SupperPerson sp = new SupperPerson(p);sp.superChifan();}}/*MyReader//专门用于读取数据的类 |--MyTextReader|--MyBufferTextReader|--MyMediaReader|--MyBufferMediaReader|--MyDateReader|--MyBufferDateReaderclass MyBufferReader{MyBufferReader(MyTextReader text){}MyBufferReader(MyMediaReader media){}}//这个类扩展类很差,可以找其参数的共同类型,//通过多态的形式,可以提高扩展性class MyBufferReader extends MyReader{private MyReader r;MyBufferReader(MyReader r){}//从继承变结合结构}后来的体系MYReader//专门用于读取数据的类 |--MyTextReader|--MyMediaReader|--MyDateReader|--MyBufferReader装饰模式比继承更灵活,避免了继承体系的臃肿而且降低了类之间的关系。装饰类因为增强已有对象,具备的功能和已有对象是相同的,只不过提供了更强的功能,所以装饰类和被装饰类都属于一个体系中。建设继承要写,但不要以继承为主,继承太多了会臃肿。*//*自己定义一个模拟BufferedReader的方法readLine()通过read()方法*/import java.io.*;class MyBufferedReader extends Reader//继承{private Reader r;//修改了FileReader,更具扩展性MyBufferedReader( Reader r){this.r = r;}public String myReadLine()throws IOException{int buf = 0;StringBuilder sb = new StringBuilder();while ((buf = r.read())!=-1){if(buf == '\r'){continue;}if(buf=='\n'){return sb.toString();}elsesb.append((char)buf);}if (sb.length()!=0){return sb.toString();}return null;}//覆盖Reader类中的二个抽象方法,继承必须复写public int read(char[] cbuf,int off,int len)throws IOException{return r.read( cbuf, off,len);//子类肯定要实现,调用它就可以了。}public void close()throws IOException{r.close();}public void myClose()throws IOException{r.close();}}class  MyBufferedReaderDemo{public static void main(String[] args) throws IOException{FileReader fr = new FileReader("demo.txt");MyBufferedReader mybuf = new MyBufferedReader(fr);String line = null;while ((line=mybuf.myReadLine())!=null){System.out.println(line);}mybuf.myClose();}}//练习。自定义一个带行号的readLine();LineNumberReaderimport java.io.*;class MyLineNumberReader{private Reader r ;private int lineNumber ;MyLineNumberReader(Reader r){this.r = r;}public void setLineNumber(int lineNumber){this.lineNumber = lineNumber;}public int getLineNumber(){return lineNumber;}public String myReaderLine()throws IOException{ lineNumber++;StringBuilder sb = new StringBuilder();int buf =0;while ((buf = r.read())!=-1){if(buf=='\r'){continue;}if (buf=='\n'){return sb.toString();}elsesb.append(buf);}if(sb.length()!=0)return sb.toString();return null;}public void myColse()throws IOException{r.close();}}class MyLineNumberReaderDemo{public static void main(String[] args)throws IOException{FileReader fr = new FileReader("MyBuffer.java");MyLineNumberReader mylnr = new MyLineNumberReader(fr);String line = null;while ((line = mylnr.myReaderLine())!=null){System.out.println(mylnr.getlineNumber()+":::"+line);}mylnr.close();}}/*class  LineNumberReaderDemo{public static void main(String[] args) throws IOException{//第一次,这是java提供的。FileReader fr = new FileReader("MyBuffer.java");LineNumberReader lnr = new LineNumberReader(fr);String line = null;lnr.setLineNumber(100);while ((line = lnr.readLine())!=null){System.out.println(lnr.getLineNumber()+":"+line);}lnr.close();}}*///以上可以简化程序,因为父类已经提供了相关方法。这里我就不写了/*字符流FileReaderFileWriterBufferedReaderBufferedWriter字节流InputStream OutputStream需求:想要操作图片数据。这时就要用到字节流。字节流不需要缓冲。不需要刷新。但需要关闭资源。*/import java.io.*;class  FileStream{public static void main(String[] args) throws IOException{stream_3();}public static void stream_1()throws IOException{FileOutputStream fo = new FileOutputStream("fos.txt");fo.write("abcdef".getBytes());FileInputStream fi = new FileInputStream("fos.txt");int num = 0;while ((num = fi.read())!=-1){System.out.println((char)num);}fi.close();fo.close();}public static void stream_2()throws IOException{FileInputStream fi = new FileInputStream("fos.txt");byte[] buf = new byte[1024];int len = 0;while ((len = fi.read(buf))!=-1){System.out.println(new String(buf,0,len));}fi.close();}public static void stream_3()throws IOException{FileInputStream fi = new FileInputStream("fos.txt");byte buf[] = new byte[fi.available()];//字节流特有的,返回字符个数。换行符(\r\n)等于二个字节。//定义一个刚刚好的缓冲区,不用循环了。fi.read(buf);System.out.println(new String(buf));fi.close();}}/*复制一个图片思路:1,用字节读取流对象和图片关联2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。3,通过循环读写,完成数据的存储4,关闭资源。最后问:用字符流可以复制吗?可以,但是有可能打不开。因为要去表里面查字符,有可能这个字符没有,就用相似的表示了。所以不要用字符流拷贝媒体文件。*/import java.io.*;class CopyPic{public static void main(String[] args) {FileInputStream fi = null;FileOutputStream fo = null;try{fi = new FileInputStream("c:\\1.jpg");fo = new FileOutputStream("c:\\2.jpg");byte[] buf = new byte[1024];int len = 0;while ((len = fi.read(buf))!=-1){fo.write(buf,0,len);}}catch (IOException e){new RuntimeException("复制失败");}finally{try{if (fi != null){fi.close();}}catch (IOException e){new RuntimeException("1111复制失败");}try{if (fo != null){fo.close();}}catch (IOException e){new RuntimeException("222复制失败");}}}}/*演示MP3的复制,通过缓冲区*/import java.io.*;class CopyMp3{public static void main(String[] args) throws IOException{long start = System.currentTimeMillis();copy1();long end = System.currentTimeMillis();System.out.println("end-start:"+ (end-start)+"毫秒");}public static void copy1()throws IOException{BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3"));BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));int len = 0;while ((len = bufis.read())!=-1)//缓冲区里取。{bufos.write(len);//字节流可以不用刷新。}bufis.close();bufos.close();}}import java.io.*;/*自定义一个缓冲区模拟BufferedInputStreammyRead方法原理和具体实现。myRead函数主要是把数据抓到缓冲区里,并从缓冲区里一次读一个字节那么原理是定义一个数组,把流里面的数据抓到数据里面,但是数组长度固定,定义的数组可能装不下;此时就要用循环读取,但是最后一次读的数组可能就不是数组的长度,此时要把数组里面元素的有效位数找到,通过read(byte[] b)方法。用一个count变量记住一次读的字节的数量,每读myRead一次时,就把缓冲区里的字节赋值给一个变量,怎么赋值?这根把数组元素的值赋给变量一样,并且每次赋值时,数组指针会随myRead读取次数向后移1位,故会有pos++,并且把count--(为了后面的count==0),并把变量处理后返回出去;当count为0时候,此时又会调用一次read(byte[] b) 方法,如此循环,直到count小于(或等于(最后一次))自己定义的数组长度,当读到最后一次字节再往下读的时,此时count为0,又会执行read(byte[] b) 方法,但此时的count返回-1,就不要在继续读取下去了。需要注意的是:每读取一次myRead方法,就爱需要读取下一个字节,就需要pos++;int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。*/class MyBufferedInputStream{private FileInputStream r;private int pos = 0,count = 0;byte[] buf = new byte[1024];MyBufferedInputStream (FileInputStream r){this.r = r;}public int myRead()throw IOException//返回int是为了避免出现byte为-1情况。{//一次性全部读到缓冲区,不要再到硬盘里读,所以速度比较快。if (count ==0){count = r.read(buf);if (count < 0){return -1;}pos = 0; byte b = buf[pos];pos++;count--;return b&255;}if (count > 0){byte b = buf[pos];pos++;count--;return b&255;/*1111-1111———>提升了一个int类型,那不还是-1吗?是-1的原因是因为在前面补1的原因造成的。那么我只要在前面补0,可以保留原字节数据不变,又可以避免-1出现。怎么补0呢?就是与上255.b&255;也可以写成b&0xff。*/}return -1;}public void myClose()throw IOException{r.close();}}class MyBufferedInputStreamDemo{public static void main(String[] args)throw IOException{long start = System.currentTimeMillis();copy2();//这是一个比较快的复制文件的方法。自定义的读取流缓冲。long end = System.currentTimeMillis();System.out.println((end-start)+"毫秒");}public static int copy2()throw IOException{FileInputStream fis = new FileInputStream("c:\\0.mp3");MyBufferedInputStream mybuf = new MyBufferedInputStream(fis);BufferedOutputStream bufout = new BufferedOutputStream(new FileOutputStream("c:\\3.mp3"));int num = 0;while ((num = mybuf.myRead())!=-1){bufout.write(num);//上面提升了4倍大小,byte->int...其实write在自动做一个强转动作。}//把最低的八位写出去,其他的全部砍掉。mybuf.myClose();bufout.close();}private static void copy3() throws IOException{//15最快啊。这是最快的复制文件的方法BufferedInputStream bufin = new BufferedInputStream(new FileInputStream("1.mp3"));BufferedOutputStream bufout = new BufferedOutputStream(new FileOutputStream("2copy.mp3"));int i = 0;byte[] buf = new byte[1024];while((i=bufin.read(buf))!=-1){//读一片,写一片。bufout.write(buf,0,i);}bufout.close();bufin.close();}}/*读取键盘录入System.out:对应的是标准输出设备,控制台System.in:对应的标准输入设备:键盘需求:通过键盘录入数据当录入一行数据后,就将该行数据进行打印如果录入的数据是over,那么停止录入*/import java.io.*;class  SystemOut{public static void main(String[] args) throws IOException{InputStream in = System.in;//键盘录入StringBuilder sb = new StringBuilder();while (true){int num = in.read();if (num == '\r'){continue;}if (num == '\n'){String s = sb.toString();if (s.equals("over")){break;}System.out.println(s.toUpperCase());sb.delete(0,sb.length());//这里不是返回,所以要删除。}else//为什么要写上这个over才会停止?break跳出当前循环sb.append((char)num);}//int by = in.read();//阻塞式方法//int by1 = in.read();//阻塞式方法//System.out.println(by);//System.out.println(by1);//System.out.println('\r'+0);//验证'\r'的int/*int num = 0;while ((num = in.read())!=-1){System.out.println(num);//这也是可以的,一个一个字节,还不能判断-1;}*/}}/*转换流本来就有字节流,字符流可以更方便的操作字符数据,所以把转换流放到字符流里。*/import java.io.*;class  InputStreamReaderDemo{public static void main(String[] args) throws IOException{//获取键盘录入。//InputStream in = System.in;//将字节流转换成字符流对象。//InputStreamReader isr = new InputStreamReader(in);//缓冲//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);String line = null;while ((line = bufr.readLine())!=null){if ("over".equals(line)){break;}bufw.write(line.toUpperCase());bufw.newLine();bufw.flush();//字符输出流要刷新}}}/*流操作的基本规律最痛苦的就是流对象有很多,不知道该用哪一个通过三个明确来完成1.明确源和目的源:输入流。InputStream Reader目的:输出流。OutputStream Writer.2.操作的数据是否是纯文本。是;字符流不是:字节流。3.当体系明确后,再明确要使用哪个具体的对象通过设备来进行区分源设备:内存,硬盘,键盘目的设备:内存,硬盘,控制台 需求:1.将一个文本文件中的数据存储到另一个文件中。复制文件。源:输入流InputStream Reader,是一个文本文件,用Reader.设备是硬盘,FileReader fr = new FileReader("a.txt");需要高效:BufferedReader bufr = new BufferedReader(fr);目的:输出流。OutputStream Writer. 是一个文本,Writer设备是硬盘,FileWriter fw = new FileWriter("b.txt");需要高效:BufferedWriter bufw = new BufferedWriter();2:将键盘录入的数据保存到一个文件中。源:输入流InputStream Reader,是否纯文本?是!Reader.设备是键盘,InputStream fis = System.in;不是选择Reader吗?System.in对应的不是字节流吗?为了操作键盘的文本数据方便,转成字符流操作字符串最方便。所以明确了Reader,那就将System.in转成字符流用到Reader体系中的转换流。InputStreamReaderInputStreamReader isr = new InputStreamReader(System.in);提高效率:BufferedReader bufr = new BufferedReader(isr);目的:输出流。OutputStream Writer.是一个文本,Writer.设备:硬盘。FileWriter fw = new FileWriter("c.txt");高效:BufferedWriter bufw = new BufferedWriter(fw);---------------------------扩展一下,想要把录入的数据按照指定的编码表(UTF-8),将数据存入到文件中。目的:输出流。OutputStream Writer.是一个文本,Writer.设备:硬盘。FileWriter 。但是!!!FileWriter 是使用的默认编码表。GBK在存储时,要加入指定的编码表UTF- 8,指定编码表只有转换流可以。所以指定的对象是OutputStreamWriter!!!而转换流要接收一个字节输出流,而且是可以操作文件的字节输出流FileOutputStream!!!FileOutputStream fos = new FileOutputStream("d.txt");OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");高效:BufferWriter bufw = new BufferedWriter(osw);所以记住,转换流什么时候使用。1.字符和字节之间的桥梁,通常涉及到编码表时,就要使用。2.当源和目的是字节流时,而操作的是字符。!*//*System.setIn();改变输入System.setOut();改变输出。如:System.setOut(new PrintStream("zz.txt"))*/import java.io.*;import java.text.*;import java.util.Date;//建立java异常信息。。。其实网络上有专门的工具。log4jclass  ExceptionInfo{public static void main(String[] args) throws IOException{int[] arr = new int[2];Date date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String s = sdf.format(date);try{System.out.println(arr[3]);//这里会出错。}catch (Exception e){//e.printStackTrace();try{PrintStream ps = new PrintStream("b.txt");//ps.write(date.toString().getBytes());//ps.println(date.toString());ps.println(s);System.setOut(ps);//System.out.println(s.toString());}catch (IOException ex){throw new RuntimeException("日志文件创建失败");}e.printStackTrace(System.out);//e.printStackTrace(new PrintStream("exceptioninfo.txt"));}}}import java.io.FileNotFoundException;import java.io.PrintStream;import java.util.Properties;public class SystemInfo {/** * @param args * @throws FileNotFoundException  */public static void main(String[] args) throws FileNotFoundException {// TODO Auto-generated method stubProperties prop = System.getProperties();//System.out.println(prop);//打印在控制台上//prop.list(System.out);//自己的方法打印在控制台上prop.list(new PrintStream("systemInfo.txt"));//改变输出的目的。}}
原创粉丝点击