一、装饰设计模式装饰设计模式。解决的问题:给已有的对象提供增强额外的功能。还不用对原有对象进行修改。 比继承更为灵活。 Writer|--TextWriter|--MediaWriter现有一个体系用于各种数据的写入。但是,发现写入效率有点低。想要对其进行效率的提高。可以使用缓冲技术来完成的。已有对象中的写入方法,不够高效,可以通过派生子类的形式对其进行复写,定义高效的写入动作。 Writer|--TextWriter|--BufferTextWriter |--MediaWriter|--BufferMediaWriter|--DataWriter|--BufferDataWriter通过继承的方式提高了效率。但是对于扩展性是一个问题。而且所需的功能越多,子类就越多。如何解决这个问题呢?优化!既然都需要缓冲,对数据写入效率进行提高
。可以转变一下思想,这样来做,将缓冲技术单独进行封装。哪个对象需要缓冲,就把哪个对象传递给缓冲对象即可。 class Buffer{Buffer(TextWriter w){}Buffer(MediaWriter w){}} 体系就变成了这样: Writer|--TextWriter |--MediaWriter |--BufferWriterBufferWriter的出现,增强了Writer体系中的功能。这种设计方式比原理更为灵活,避免了继承的臃肿。将这样解决方式就定义了一个名称方便于后人使用:装饰设计模式。记住:装饰类和被装饰类都所属于同一个体系。
二、行号装饰类public static void main(String[] args) throws IOException {FileReader fr = new FileReader("tempfile\\demo.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();}三、字符流:FileReaderFileWriterBufferedReaderBuffereWriter字节流。InputStream
OutputStreamFileInputStream FileOutputStreamBufferedInputStream BufferedOutputStream转换流:字节流--->字符流的桥梁。InputStreamReader 字符流--->字节流的桥梁。OutputStreamWriterpublic static void main(String[] args) throws IOException {需求:将一个字符串写入一个文件中。使用FileOutputStream来演示。FileOutputStream
fos = new FileOutputStream("tempfile\\fos.txt");fos.write("abcdef".getBytes());//字节流的直接操作文件写入时,直接将数据写入到目的地。为啥FileWriter就需要刷呢?那是因为FileWriter底层使用了字节流在操作字符数据时,会先将这些数据进行临时存储,并查指定的编码表。按照指定的编码表中的内容写入到目的地。"你好"FileWriter ---> 编码表 GBK--->数字字节--->目的地。而字节流处理的数据不一定都是文字数据,所以是不需要指定查表的。
直接在操作文件数据时,就将具体的字节数据写入到目的地。fos.flush();使用的是父类OutputStream的flush。该方法什么都没有做,只有OutputStram某一些子类定义了该方法的具体内容。 fos.close();//必须有,因为要关闭资源。}需求:读取一个文件。用字节流。int ch = fis.read();System.out.println("ch="+ch);//一次读一个,打一个。int ch = 0;while((ch=fis.read())!=-1){System.out.println((char)ch);}//读取并存储到数组,将数组打印。以该种方式。byte[]
buf = new byte[1024];int len = 0;while((len=fis.read(buf))!=-1){System.out.println(new String(buf,0,len));}//直接创建一个刚刚好的大小的数组缓冲区。byte[] buf = new byte[fis.available()];//如果文件过大,内存溢出,bang 一声!慎用!// fis.read(buf);//将数据存储到刚刚好的数组中。 System.out.println(new String(buf));
fis.read(); System.out.println(fis.available());//获取流关联的文件的字节数。 fis.close();四、复制mp31、自定义数组缓冲区的方式。 public static void copy_1() throws IOException {//1,读取流对象,和mp3关联。FileInputStream fis = new FileInputStream("C:\\0.mp3");//2,写入流对象,明确存储mp3数据的目的。FileOutputStream
fos = new FileOutputStream("c:\\1.mp3");//3,定义一个字节缓冲区。byte[] buf = new byte[1024*8];int len = 0;while((len=fis.read(buf))!=-1){fos.write(buf,0,len);}fos.close();fis.close();}2、不建议。使用刚刚好的缓冲区。因为文件过大会溢出。public static void copy_3() throws IOException {FileInputStream
fis = new FileInputStream("C:\\0.mp3"); FileOutputStream fos = new FileOutputStream("c:\\3.mp3");byte[] buf = new byte[fis.available()];fis.read(buf);fos.write(buf);fos.close();fis.close();}3、使用字节流已有的缓冲区。 public static void copy_2() throws IOException {FileInputStream
fis = new FileInputStream("C:\\0.mp3"); FileOutputStream fos = new FileOutputStream("c:\\2.mp3");BufferedInputStream bufis = new BufferedInputStream(fis);BufferedOutputStream bufos = new BufferedOutputStream(fos);int by = 0;while((by=bufis.read())!=-1){bufos.write(by);}bufos.close();bufis.close();
}4、读一个 写一个public static void copy_4() throws IOException {FileInputStream fis = new FileInputStream("C:\\0.mp3");FileOutputStream fos = new FileOutputStream("c:\\4.mp3"); int by = 0;while((by=fis.read())!=-1){fos.write(by);}fos.close();fis.close();五、键盘录入读取键盘录入。
public static void readKey() throws IOException{//获取到读取键盘录入的流对象。类型是InputStreamInputStream in = System.in;//用流读取数据。如果没有数据录入,那么控制台会一致等待输入。read方法就是一个阻塞式的方式。 int ch = in.read(); System.out.println("ch="+ch);int ch1 = in.read(); System.out.println("ch1="+ch1);int
ch2 = in.read(); System.out.println("ch2="+ch2);in.close();//不需要关闭。 //注意:系统中获取的流对象都是唯一的,如果将其关闭,就不能在使用了。//想要在使用只有重新再次运行这个程序才可以。 //所以一般情况下,从System获取到的流对象,一般不需要关闭。随着程序的停止而结束。 // InputStream in2 = System.in;这里会出错 。// int ch4 = in2.read();// System.out.println("ch4="+ch4);六、键盘录入练习
需求:读取键盘录入的数据,将这些数据转成大写打印在屏幕上,如果录入的是 over, 程序结束。 思路:1,通过键盘录入读取字节数据。2,将这些读到的字节数据进行存储以变成字符串。3,对这个字符串进行判断。如果不是over就将其转成大写打印。如果是over就结束。 public static void readKey2() throws IOException {//1,获取键盘录入流对象。 InputStream in = System.in;//2,定义一个容器用于存储读取到的字节。StringBuilder
sb = new StringBuilder();//3,循环读取键盘。int ch = 0;while((ch=in.read())!=-1){//需要对读取到的字节进行判断。//如果是/r 或者 /n,不存储,并视为一次录入内容结束符。对之前的录入数据进行判断。if(ch=='\r')continue;if(ch=='\n'){String s = sb.toString();if("over".equals(s)){//记住:如果要使用键盘录入,一定要自定义结束标记。break;}else{System.out.println(s.toUpperCase());//清空缓冲区。
sb.delete(0, sb.length());}}elsesb.append((char)ch);}}七、转换流 既然键盘录入转成大写输出,并判断over结束的程序中使用了到对字节数据的存储,并对回车符进行判断。 发现这个功能和readLine方法一致。因为readLine是字符流BufferedReader对象中过的方法。而键盘录入是字节流。能不能将这个字节读取流转成字符流呢?因为BufferedReader只能对字符流进行装饰 。这就用到了转换流转换流:字节流--->字符流的桥梁。InputStreamReader
字符流--->字节流的桥梁。OutputStreamWriter从键盘读取数据,转成大写,显示在屏幕上。 获取键盘录入,数据源。InputStream in = System.in;为了处理文字数据方便。将字节数据转成字符数据.这个功能在转换流中。InputStreamReaderInputStreamReader isr = new InputStreamReader(in);//为了提高了读取的效率。使用缓冲区。 BufferedReader bufr = new BufferedReader(isr);//打印到显示器上。目的。OutputStream
out = System.out;//因为要打印到显示器上的数据都是文字数据。所以必须将这些文字数据转成字节数据。//具备这个功能的对象是OutputStreamWriter.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();//newLine()需要有BufferedWriter对象bufw.flush();
}//因为是从System获取的流可以不关闭,随着系统的结束而结束。bufw.close();bufr.close();}八、流的操作规律:规律就是四个明确?1,明确源和目的。源:InputStream Reader 一定是被读取的。目的:OutputStream Writer 一定是被写入的。 2,处理的数据是否是纯文本的数据?是:使用字符流。Reader Writer否:使用字节流。 InputStream OutputStream如果是源并且是纯文本,Reader如果是目的并且是纯文本,Writer到这里,两个明确确定完,就可以确定出要使用哪个体系。接下来,就应该明确具体这个体系要使用哪个具体的对象。3,明确数据所在的设备:源设备:键盘(System.in)硬盘(FileXXX)内存(数组)网络(Socket)目的设备:显示器(控制台System.out)硬盘(FileXXX)内存(数组)网络(Socket)具体使用哪个对象就可以明确了。4,明确是否需要额外功能?1,是否需要高效?缓冲区Buffered2,是否需要转换?转换流
后面会学到更多。九、需求练习需求1:复制一个文本文件。直接明确具体对象并创建。FileReader fr = new FileReader("a.txt");FileWriter fw = new FileWriter("b.txt");然后是频繁的读写操作。需要额外功能吗?需要,高效。 使用缓冲区。BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));BufferedWriter bufw = new BufferedWriter(new
FileWriter("b.txt"));需求3:读取键盘录入,存储到一个文件中。明确是否是纯文本?一般键盘录入的都是文字,所以是纯文本的。 InputStream in = System.in;FileWriter fw = new FileWriter("a.txt");需要将键盘录入的字节转成字符。使用转换流。而且是 将字节-->字符的转换流对象。InputStreamReaderInputStreamReader isr = new InputStreamReader(System.in);FileWriter
fw = new FileWriter("a.txt");需要,高效。BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));BufferedWriter bufw = new BufferedWriter(new FileWriter("a.txt"));需求4:读取一个文本文件,显示到显示器上。FileReader fr = new FileReader("a.txt");OutputStream out =
System.out;需要将已有的字符数据转成字节。字符-->字节的桥梁 OutputStreamWriterFileReader fr = new FileReader("a.txt");OutputStreamWriter osw = new OutputStreamWriter(System.out);需要高效。BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));BufferedWriter bufw = new BufferedWriter(new
OutputStreamWrier(System.out));需求5:读取一个文本文件,将文件中文本按照指定的编码表UTF-8写入到另一个文件中。 FileReader fr = new FileReader("a.txt");FileWriter fw = new FileWriter("b.txt");这样做不行,满足不了需求,为什么呢?因为这个两个对象在操作文本数据,都是用了默认的编码表。在我的本机中默认码表是GBK.而需求中希望写入到文件的数据是按照utf-8的码表。其实这两个对象就是字节流+默认编码表。
源对象不变。FileReader fr = new FileReader("a.txt");需要目的为指定编码表。这时就要用到转换流。因为转换流中可以指定具体的编码表。 需要往里传递一个字节流,而且要操作文件,FileOutputStreamOutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"),"UTF-8");需要高效BufferedReader bufr = new BufferedReader(new
FileReader("a.txt"));BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("b.txt"),"UTF-8"));
流
最新推荐文章于 2025-05-10 17:38:36 发布