Java I/O流操作(二)---缓冲流[转]

转自:http://blog.csdn.net/johnny901114/article/details/8710403

一、BufferWriter类

IO的缓冲区的存在就是为了提高效率,把要操作的数据放进缓冲区,然后一次性把缓冲区的内容写到目的地,而不是写一次就往目的地写一次.

在这里要注意的是当我们关闭了缓冲区对象实际也关闭了与缓冲区关联的流对象。

BufferWriter

try {

  FileWriter fw
=new FileWriter("test.txt");

  //使用缓冲区必须要与一个流对象相关联

  BufferedWriter bw
=new BufferedWriter(fw);

  bw.write("hello world!");

  //使用缓冲区的时候要注意刷新
  bw.flush();

  //关闭缓冲区的对象,实际上是关闭与它关联的流对象最好放在finally执行

  bw.close();

catch (IOException e) {

  e.printStackTrace();

}

其实BufferReader也是差不多的,这里就不多讲

?





1

2

3

4

5

6

7

FileReader fr =new
FileReader("test.txt");

BufferedReader br =new
BufferedReader(fr);

String line =null;

//注意readLine方法读取的内容不包括换行符

while((line=br.readLine())!=null){

    System.out.println(line);

}

readLine原理:

无论是读一行,获取多个字符,最终都是在硬盘上一个一个读取,所以最终使用的还是read方法一次读一个的方法。

二、装饰模式

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

package
i18n;

public class test {

}

class Person {

    public
void eat() {

        System.out.println("吃饭");

    }

}

public
class PersonEnhance {

    private
Person p;

    // 把需要增强 的类传进去初始化

    public
PersonEnhance(Person p) {

        this.p = p;

    }

    public
void enhanceEat() {

        System.out.println("开胃酒");

        p.eat();

        System.out.println("甜点");

    }

}

装饰模式作用:就是在原有类的基础上把某个方法增强功能 
但是这让我想到了java
的动态代理,他也是在某个方法的基础上增加额外的功能,那么她们有什么区别呢? 
装饰类和被装饰的类是应该继承或实现相同的接口,而java的动态代理不是,

还有一个不同点就是动态代理可以横切多个面,也就是同时对多个方法进行增强.

通过装饰模式和继承的区别发现了程序设计之美,虽然继承也可以增强某个方法,但是它使得类的体系很臃肿,并且可扩展性不好

因为装饰模式中,我们可以把被装饰类的父类当作参数传进装饰类的构造方法内,那么你这一个装饰类就可以应用于这个体系的了,这也是java多态性的好处.

相比较之下使用装饰模式降低了类之间的关系.

装饰类是因为增强了已有的对象,具有的功能和已有的是相同的,是不过提供了更强的功能,所以装饰类和被装饰类通常属于一个体系中的.

在API中可以看到BufferedReader类还有一个子类LineNumberReader

通过API对得知,这是一个字符缓冲输出流,该类保持对行号的跟踪,可以通过该类的setLineNumber(int) andgetLineNumber() 方法分别设置获取行号

例如程序:

?





1

2

3

4

5

6

7

8

public static void main(String[] args) throws
IOException {

        FileReader fr = new
FileReader("test.txt");

        LineNumberReader lnr = new
LineNumberReader(fr);

        String num = null;

        while
((num = lnr.readLine()) != null) {

            System.out.println(lnr.getLineNumber() + ":"
+ num);

        }<br>}

控制台输出:  

但是我们也可以改变行号的开始值

?





1

2

3

4

5

6

7

8

9

10

11

public static void main(String[] args) throws
IOException {

    FileReader fr = new
FileReader("test.txt");

    LineNumberReader lnr = new
LineNumberReader(fr);

    String num = null;

    // 设置行号的开始值为100

    lnr.setLineNumber(100);

    while
((num = lnr.readLine()) != null) {

        System.out.println(lnr.getLineNumber() + ":"
+ num);

    }

}

输出结果为:  

LineNumberReader

EnhanceLineNumberReader

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

public String readLine() throws
IOException {

    int
lineNumber=0;

    lineNumber++;

    StringBuilder buffer =new
StringBuilder();

    int
i = 0;

    while
((i =reader.read()) != -1) {

        if
((char) i ==‘\r‘) {

            continue;

        }

        if
((char) i ==‘\n‘) {

            return
buffer.toString();

        }else
{

            buffer.append((char) i);

        }

    }

    if
(buffer.length() != 0) {

        return
buffer.toString();

    }

    return
null;

}

书出结果是一样的

下面开始学习字节流

通过API文档字节流的顶级类为InputStream和OutputStream

首先来看一下FileOutputStream和FileInputStream

?





1

2

3

4

public static void writeData()throws
Exception{

    OutputStream out =new
FileOutputStream("D:\\test2.txt");

    out.write("hello inputStream!".getBytes());

}

执行上面代码后,发现在D盘创建了test2.txt文件并且内容是hello inputStream!

从上面可以看出这和字符流是有区别的,因为当我们在使用字符流的时候,如果没有刷新并且没有关闭那么文件内容是空的,而这里刚好相反.

但是最好我们还是调用close方法,关闭资源.提高性能.

下面实现读取操作:

?





1

2

3

4

5

6

7

public static void readData() throws
Exception {

    InputStream is = new
FileInputStream("D:\\test2.txt");

    int
num = 0;

    while
((num = is.read()) != -1) {

        System.out.println((char) num);

    }

}

但是这样效率比较低,因为读取一次写一次,我们可以使用缓冲:  

?





1

2

3

4

5

6

7

8

9

public static void readData2()throws
Exception {

    InputStream is =new
FileInputStream("D:\\test2.txt");

    int
num = 0;

    byte[] buffer =newbyte[1024];

    //把读取到的数据放进字节数组里面

    while
((num = is.read(buffer)) != -1) {

        System.out.println(new
String(buffer, 0, num));

    }

}

在InputStream类中有这样一个方法available()返回int
他的作用是返回文件内容的长度 那么我们就可以这样读取数据,而不用while循环了  


public static void readData3()throws Exception {
InputStream is =new FileInputStream("D:\\test2.txt");
//返回文件的长度
int num = is.available();
把字节数组的长度定义成文件长度,那么这个数组就刚好装下这个文件了
byte[] buffer =newbyte[num];
is.read(buffer);
System.out.println(new String(buffer));
}

但是这样有一个缺陷,如果一个文件非常大,那么这就会出现内存溢出了.所以这是用操作小型 的文件.

练习,复制一份图片:代码片段:

?





1

2

3

4

5

6

7

8

9

InputStream is = new
FileInputStream("D:\\imagetest\\desk.jpg");

OutputStream os = new
FileOutputStream("E:\\desk1.jpg");

byte[] buffer = new
byte[1024];

int readNum = 0;

int a=0;

while((readNum=is.read(buffer))!=-1){

    System.out.println(a++);

    os.write(buffer, 0, readNum);

}

使用java缓冲输出流  

?





1

2

3

4

5

6

7

8

BufferedOutputStream buffOs =new
BufferedOutputStream(new
FileOutputStream("F:\\KuGou\\baby2 - baby one more time.mp3"));

BufferedInputStream buffIs =new
BufferedInputStream(new
FileInputStream("F:\\KuGou\\baby - baby one more time.mp3"));

int len = 0;

while((len=buffIs.read())!=-1){

    buffOs.write(len);

}

buffOs.close();

buffIs.close();

获取键盘录入:

System.out对应的是标准的输出设备一般指控制台

System.in对应的是标准输入设备:键盘

下面模拟一个键盘录入的功能:

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

public static void main(String[] args) throws
IOException {

    InputStream is = System.in;

    StringBuilder buffer = new
StringBuilder();

    int
i = 0;

    while
(true) {

        i = is.read();

        if
(‘\r‘ == i)

            continue;

        if
(‘\n‘ == i) {

            String value = buffer.toString();

            // 如果录入的是over那么则退出

            if
("over".equals(buffer.toString()))

                break;

            System.out.println(value);

            // 清空缓冲区 以免下次录入时不会和前面录入的汇合

            buffer.delete(0, buffer.length());

        } else
{

            buffer.append((char) i);

        }

    }

}

注意在输入流在读取数据的时候连回车也会读取的.在windows中\r\n代表换行 例如下面简单的程序

InputStream is = System.in;

System.out.println(is.read());

System.out.println(is.read());

控制台输出:

13

10

对于键盘录入功能我们可以使用更加简单的方式:因为他这个功能实际上就是读取一行 的操作:

那么就可以考虑使用readLine方法,然后该方法是字符六BufferedReader的方法

然而InputStream又是字节流.那么怎么办呢?

我们可以使用InputStreamReader类,这个类是字节流到字符流的桥梁,

?





1

2

3

4

5

6

7

8

9

10

11

12

public static void main(String[] args) throws
IOException {

    InputStream is = System.in;

    InputStreamReader isr = new
InputStreamReader(is);

    BufferedReader br = new
BufferedReader(isr);

    String line = null;

    while
((line = br.readLine()) != null) {

        if
(line.equals("over")) {

            break;

        }

        System.out.println(line.toUpperCase());

    }

}

对应的OutputStreamWriter是字符流向字节流转换的桥梁 也就是读进来的是字符,写进去的是字节,在上面的基础上我们可以这样改写:  

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public static void main(String[] args) throws
IOException {

    InputStream is = System.in;

    InputStreamReader isr = new
InputStreamReader(is);

    BufferedReader br = new
BufferedReader(isr);

    OutputStreamWriter osw = new
OutputStreamWriter(System.out);

    BufferedWriter bw = new
BufferedWriter(osw);

    String line = null;

    while
((line = br.readLine()) != null) {

        if
(line.equals("over")) {

            break;

        }

        bw.write(line);

        // 注意使用字符流要注意flush

        bw.flush();

        // System.out.println(line.toUpperCase());

    }

}

但是控制台输出为:

发现输出的数据没有换行

当然我们可以在line后面加上\r\n

但是这是不跨品台的

我们可以这样解决:

我们可以使用

BufferedWriter 的newLine方法

在bw.write(line);后面加上bw.newLine(); 即可

总结: 下面总结一下IO的操作规律:

1,明确源和目的:

源 :输入流,InputStream  Reader

目的: 输入流 OutpuStream Writer

3当明确体系后,在明确使用哪个具体的对象

通过设备来进行区分:

源设备:  存 硬盘 键盘

目的设备:  内存  硬盘
控制台

  

  

  

  

  

  

  

  

Java I/O流操作(二)---缓冲流[转],布布扣,bubuko.com

时间: 2024-08-05 06:56:43

Java I/O流操作(二)---缓冲流[转]的相关文章

文件流之字节缓冲流(BufferedInputStream BufferedOutputStream)

缓冲流的优势是: BufferedInputStream: 输入缓冲流:先从磁盘中将要读取的内容放入到内存中,再一次性从内存中取出来,避免了读一段取一段: BufferedOutputStream: 输出缓冲流:先将要输出的内容放入到内存中,再一次性全都输出. 缓冲流的构造函数: public BufferedInputStream(InputStream in) { this (in, DEFAULT_BUFFER_SIZE); } public BufferedInputStream(Inp

Java学习总结(7)——(File类,IO流,(缓冲流,转换流等),Properties类)

一.File类 java.io.File类代表系统文件(文件和目录) 访问文件属性步骤 (1)创建文件对象 格式:File file=new File(String pathname); (2)调用方法:操作文件目录的属性(路径,权限,日期和时间等) File类的属性(separator默认名称分隔符) (1)在UNIX系统上,此字段的值为 '/ ';在window系统上,它为'\' (2)为了程序的跨平台性,文件的路径应该用这个属性值来代表 File类的常用方法 方法名称 说明 Boolean

java字节缓冲流和字符缓冲流

一.字节缓冲流 1.介绍 字节缓冲流根据流的方向,分为: 1.写入数据到流中,字节缓冲输出流 BufferedOutputStream 2.读取流中的数据,字节缓冲输入流 BufferedInputStream 它们的内部都包含了一个缓冲区,通过缓冲区读写,就可以提高了IO流的读写速度 2.字节缓冲输出流BufferedOutputStream 构造方法: public BufferedOutputStream(OutputStream out):创建一个新的缓冲输出流,以将数据写入指定的底层输

JAVA笔记12__字节、字符缓冲流/打印流/对象流/

/** * !!:以后写流的时候一定要加入缓冲!! * 对文件或其它目标频繁的读写操作,效率低,性能差. * 缓冲流:好处是能更高效地读写信息,原理是将数据先缓冲起来,然后一起写入或读取出来. * * BufferedInputStream:字节缓冲流(有一个内部缓冲区数组,用于缓冲数据) */ public class Main { public static void main(String[] args) { input(); output(); } /** * 使用字节缓冲流进行读取操作

java IO流之三 使用缓冲流来读写文件

原文:http://blog.csdn.net/haluoluo211/article/details/52183219 一.通过BufferedReader和BufferedWriter来读写文件 使用缓冲流的好处是,能够更高效的读写信息,原理是将数据先缓冲起来,然后一起写入或者读取出来.经常使用的是readLine()方法,表示一次读取一行数据. package org.example.io; import java.io.BufferedReader; import java.io.Buf

Java IO流之字符缓冲流

字符流: 1.加入字符缓存流,增强读取功能(readLine) 2.更高效的读取数据 BufferedReader 从字符输入流读取文本,缓冲各个字符,从而实现字符.数组和行的高效读取. FileReader:内部使用InputStreamReader,解码过程,byte->char,默认缓存大小为8k BufferReader:默认缓存大小为8k,但可以手动指定缓存大小,把数据读取到缓存中,减少每次转换过程,效率更高 //字符输入缓冲流 private static void charRead

Java核心类库-IO-包装流概述和缓冲流原理

处理流/包装流(相对于节点流更高级): 1. 隐藏了底层的节点流的差异,并对外提供了更方便的输入/输出功能,让我们之关心高级流操作. 2. 使用处理包装流包装了节点流程序直接操作处理流,让节点流与底层的设备做IO操作. 3. 只需要关闭处理流即可 包装流如何分区:写代码的时候,发现创建对象的时候,需要传递另一个流对象.new 包装流(流对象): 什么是缓冲流: 是一个包装流,目的起缓存作用. BufferedInputStream: BufferedOutputStream: BufferedR

缓冲流之字符缓冲流

字符缓冲流 字符缓冲输入流 BufferedReader 字符缓冲输出流 BufferedWriter 完成文本数据的高效的写入与读取的操作 1  字符缓冲输出流 BufferedWriter void newLine() 根据当前的系统,写入一个换行符 public static void method01() throws IOException{ //明确目的地 FileWriter fw =new FileWriter("E:\\java\\demo01.txt"); //添加

10.4 缓冲流 BufferedReader &amp; BufferedWriter&amp; 缓冲流特殊功能readLine

缓冲流和正常流的使用大致相同,缓冲流效率更高. package day10_io_fileWrite_Read.buffer_stream; import java.io.*; /* * BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符.数组和字符串的高效写入. * BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符.数组和行的高效读取. */ public class BufferedStream { public static