您的位置:首页 > 编程语言 > Java开发

Java IO 技术之基本流类 ~~~~~~~~ (图+讲解+代码) 好好看 有好处

2016-01-13 16:21 561 查看
流式IO

流(Stream)是字节的源或目的。



两种基本的流是:输入流(Input Stream)和输出流(Output Stream)。可从中读出一系列字节的对象称为输入流。而能向其中写入一系列字节的对象称为输出流。

InputStream 是所有的输入字节流的父类,它是一个抽象类。

ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。

ObjectInputStream 和所有FilterInputStream的子类都是装饰流(装饰器模式的主角)。意思是FileInputStream类可以通过一个String路径名创建一个对象,FileInputStream(String name)。而DataInputStream必须装饰一个类才能返回一个对象,DataInputStream(InputStream in)。

流的分类

节点流:从特定的地方读写的流类,例如:磁盘或一块内存区域。

过滤流:使用节点流作为输入或输出。过滤流是使用一个已经存在的输入流或输出流连接创建的。

InputStream



三个基本的读方法

abstract int read() :读取一个字节数据,并返回读到的数据,如果返回-1,表示读到了输入流的末尾。

int read(byte[]?b) :将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。

int read(byte[]?b, int?off, int?len) :将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。off指定在数组b中存放数据的起始偏移位置;len指定读取的最大字节数。

其它方法

long skip(long?n) :在输入流中跳过n个字节,并返回实际跳过的字节数。

int available() :返回在不发生阻塞的情况下,可读取的字节数。

void close() :关闭输入流,释放和这个流相关的系统资源。

void mark(int?readlimit) :在输入流的当前位置放置一个标记,如果读取的字节数多于readlimit设置的值,则流忽略这个标记。

void reset() :返回到上一个标记。

boolean markSupported() :测试当前流是否支持mark和reset方法。如果支持,返回true,否则返回false。

java.io包中 InputStream的类层次

OutputStream



三个基本的写方法

abstract void write(int?b) :往输出流中写入一个字节。

void write(byte[]?b) :往输出流中写入数组b中的所有字节。

void write(byte[]?b, int?off, int?len) :往输出流中写入数组b中从偏移量off开始的len个字节的数据。

其它方法

void flush() :刷新输出流,强制缓冲区中的输出字节被写出。

void close() :关闭输出流,释放和这个流相关的系统资源。

java.io包中 OutputStream的类层次

-------------------------------------------------------------------------------

-------------------------------------------------------------------------------

Demo1:在控制台读取键盘输入,然后显示。Ctrl+C结束运行

-------------------------------------------------------------------------------


import java.io. * ;




public class StreamDemo {




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


int data;




while ((data = System.in.read()) != - 1 ) {


System.out.write(data);


}




}




}



-------------------------------------------------------------------------------

-------------------------------------------------------------------------------

基本的流类

1、FileInputStream和FileOutputStream

节点流,用于从文件中读取或往文件中写入字节流。如果在构造FileOutputStream时,文件已经存在,则覆盖这个文件。

-------------------------------------------------------------------------------

Demo2:将字符串写入特定文件,注意write方法只接收字符数组。

-------------------------------------------------------------------------------


import java.io. * ;




public class StreamDemo {




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


FileOutputStream fos = new FileOutputStream( " 1.txt " );




/**/ /*


* 注意:FileOutputStream的write方法接收字符数组,不能接收String字符串,


* 所以要用String的getBytes方法生成一个字符数组


*/


fos.write( " http://www.cnblogs.com " .getBytes());


fos.close();




}




}

-------------------------------------------------------------------------------

-------------------------------------------------------------------------------

String的构造方法的API:

------------

Java API:

------------

String

public String(byte[] bytes,

int offset,

int length)

构造一个新的 String,方法是使用指定的字符集解码字节的指定子数组。新的 String 的长度是一个字符集函数,因此不能等于该子数组的长度。

当给定字节在给定字符集中无效的情况下,该构造方法无指定的行为。当需要进一步控制解码过程时,应使用 CharsetDecoder 类。

参数:

bytes - 要解码为字符的字节

offset - 要解码的首字节的索引

length - 要解码的字节数

抛出:

IndexOutOfBoundsException - 如果 offset 和 length 参数索引字符超出 bytes 数组的范围

从以下版本开始:

JDK1.1

-------------------------------------------------------------------------------

-------------------------------------------------------------------------------

Demo3:将字符串写入特定文件,注意write方法只接收字符数组。

然后通过文件输出流读取数据,注意使用String特定的构造方法。

-------------------------------------------------------------------------------


import java.io. * ;




public class StreamDemo {




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


FileOutputStream fos = new FileOutputStream( " 1.txt " );




/**/ /*


* 注意:FileOutputStream的write方法接收字符数组,不能接收String字符串,


* 所以要用String的getBytes方法生成一个字符数组


*/


fos.write( " http://www.cnblogs.com " .getBytes());


fos.close();




// 使用String的这个构造方法:


// String(byte[] bytes, int offset, int length)




FileInputStream fis = new FileInputStream( " 1.txt " );


byte [] buf = new byte [ 100 ];


int len = fis.read(buf);




// 使用String的这个构造方法:


// String(byte[] bytes, int offset, int length)


System.out.println( new String(buf, 0 , len));


fis.close(); // 使用完后记得关闭文件流




}




}

-------------------------------------------------------------------------------

运行结果:http://www.cnblogs.com/

-------------------------------------------------------------------------------

2、BufferedInputStream和BufferedOutputStream

过滤流,需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率。

------------

Java API:

------------

构造方法摘要

BufferedOutputStream(OutputStream out)

创建一个新的缓冲输出流,以将数据写入指定的基础输出流。

BufferedOutputStream(OutputStream out, int size)

创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的基础输出流。

-------------------------------------------------------------------------------

BufferedOutputStream

public BufferedOutputStream(OutputStream out)

创建一个新的缓冲输出流,以将数据写入指定的基础输出流。

参数:

out - 基础输出流。

BufferedOutputStream

public BufferedOutputStream(OutputStream out,

int size)

创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的基础输出流。

参数:

out - 基础输出流。

size - 缓冲区的大小。

抛出:

IllegalArgumentException - 如果 size <= 0

-------------------------------------------------------------------------------

-------------------------------------------------------------------------------

Demo4:通过一个OutputStream对象来构造一个BufferedOutputStream对象。

而FileOutputStream类是OutputStream类的子类,所以可以用它来构造。

-------------------------------------------------------------------------------

1

import java.io. * ;

2


3

public class StreamDemo {

4


5

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

6


7

FileOutputStream fos = new FileOutputStream( " 1.txt " );

8

BufferedOutputStream bos = new BufferedOutputStream(fos);

9

bos.write( " http://www.cnblogs.com " .getBytes());

10

}

11


12

}

-------------------------------------------------------------------------------

运行结果:1.txt文件为空。原因:缓冲区没有写满,程序没有向文件写数据。

-------------------------------------------------------------------------------

-------------------------------------------------------------------------------

解决方法1:使用flush()方法:

-------------------------------------------------------------------------------

Demo4:使用flush()方法,可以使程序立即向文件写数据。

-------------------------------------------------------------------------------

1

import java.io. * ;

2


3

public class StreamDemo {

4


5

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

6


7

FileOutputStream fos = new FileOutputStream( " 1.txt " );

8

BufferedOutputStream bos = new BufferedOutputStream(fos);

9

bos.write( " http://www.cnblogs.com " .getBytes());

10


11

bos.flush();

12

}

13


14

}

-------------------------------------------------------------------------------

运行结果:数据被写入相应的文件。

-------------------------------------------------------------------------------

解决方法2:使用close()方法:

-------------------------------------------------------------------------------

Demo5:使用close()方法,同样可以使程序立即向文件写数据。

-------------------------------------------------------------------------------

1

import java.io. * ;

2


3

public class StreamDemo {

4


5

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

6


7

FileOutputStream fos = new FileOutputStream( " 1.txt " );

8

BufferedOutputStream bos = new BufferedOutputStream(fos);

9

bos.write( " http://www.cnblogs.com " .getBytes());

10


11

bos.close();

12

}

13


14

}

-------------------------------------------------------------------------------

运行结果:数据被写入相应的文件。

-------------------------------------------------------------------------------

flush()和close()的区别:

还要使用流对象,还需要写数据,使用flush(),否则使用close()。

另外,使用close()将关闭自己的流对象,同时会关闭与之相关的流对象,如FileOutputStream流。

-------------------------------------------------------------------------------

Demo6:使用BufferedInputStream流,从文件中读取数据。

同样要用InputStream流对象或者其子类的对象来构造。

-------------------------------------------------------------------------------

1

import java.io. * ;

2


3

public class StreamDemo {

4


5

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

6


7

FileOutputStream fos = new FileOutputStream( " 1.txt " );

8

BufferedOutputStream bos = new BufferedOutputStream(fos);

9

bos.write( " http://www.cnblogs.com " .getBytes());

10


11

bos.close();

12


13

FileInputStream fis = new FileInputStream( " 1.txt " );

14

BufferedInputStream bis = new BufferedInputStream(fis);

15

byte [] buf = new byte [ 100 ];

16

int len = bis.read(buf);

17


18

// 使用String的这个构造方法:

19

// String(byte[] bytes, int offset, int length)

20

System.out.println( new String(buf, 0 , len));

21

bis.close();

22

}

23


24

}

-------------------------------------------------------------------------------

运行结果:输出http://www.cnblogs.com/

-------------------------------------------------------------------------------

3、DataInputStream和DataOutputStream

过滤流,需要使用已经存在的节点流来构造,提供了读写Java中的基本数据类型的功能。

------------

Java API:

------------

java.io

类 DataOutputStream

java.lang.Object

java.io.OutputStream

java.io.FilterOutputStream

java.io.DataOutputStream

所有已实现的接口:

Closeable, DataOutput, Flushable

public class DataOutputStream

extends FilterOutputStream

implements DataOutput

数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。

从以下版本开始:

JDK1.0

-------------------------------------------------------------------------------

构造方法摘要

DataOutputStream(OutputStream out)

创建一个新的数据输出流,将数据写入指定基础输出流。

-------------------------------------------------------------------------------

DataOutputStream

public DataOutputStream(OutputStream out)

创建一个新的数据输出流,将数据写入指定基础输出流。计数器 written 被设置为零。

参数:

out - 基础输出流,将被保存供以后使用。

-------------------------------------------------------------------------------

Demo7:使用DataOutputStream流,将基本数据类型以二进制形式写入文件中。

同样要用InputStream流对象或者其子类的对象来构造,

这里使用BufferedOutputStream对象来构造。

-------------------------------------------------------------------------------

1

import java.io. * ;

2


3

public class StreamDemo {

4


5

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

6


7

FileOutputStream fos = new FileOutputStream( " dos.txt " ); // 获得写入文件功能

8

BufferedOutputStream bos = new BufferedOutputStream(fos); // 获得缓冲功能

9

DataOutputStream dos = new DataOutputStream(bos); // 获得写入基本类型功能

10


11

/*

12

* 定义8种基本类型的对象

13

*/

14

byte b = 3 ;

15

short s = 4 ;

16

int i = 78 ;

17

long l = 100000 ;

18

char ch = ' a ' ;

19

boolean bl = false ;

20

float f = 4.5f ;

21

double d = 4.0001 ;

22


23

/*

24

* 将8种基本类型的对象写入文件中

25

*/

26

dos.writeByte(b);

27

dos.writeShort(s);

28

dos.writeInt(i);

29

dos.writeLong(l);

30

dos.writeChar(ch);

31

dos.writeBoolean(bl);

32

dos.writeFloat(f);

33

dos.writeDouble(d);

34

dos.close();

35

}

36


37

}

-------------------------------------------------------------------------------

运行结果:8种基本类型的数据以二进制形式写入指定的文件中。

-------------------------------------------------------------------------------

-------------------------------------------------------------------------------

Demo8:从指定的文件中读取8种基本类型的数据

-------------------------------------------------------------------------------

1

import java.io. * ;

2


3

public class StreamDemo {

4


5

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

6


7

FileOutputStream fos = new FileOutputStream( " dos.txt " ); // 获得写入文件功能

8

BufferedOutputStream bos = new BufferedOutputStream(fos); // 获得缓冲功能

9

DataOutputStream dos = new DataOutputStream(bos); // 获得写入基本类型功能

10


11

/*

12

* 定义8种基本类型的对象

13

*/

14

byte b = 3 ;

15

short s = 4 ;

16

int i = 78 ;

17

long l = 100000 ;

18

char ch = ' a ' ;

19

boolean bl = false ;

20

float f = 4.5f ;

21

double d = 4.0001 ;

22


23

/*

24

* 将8种基本类型的对象写入文件中

25

*/

26

dos.writeByte(b);

27

dos.writeShort(s);

28

dos.writeInt(i);

29

dos.writeLong(l);

30

dos.writeChar(ch);

31

dos.writeBoolean(bl);

32

dos.writeFloat(f);

33

dos.writeDouble(d);

34

dos.close();

35


36

FileInputStream fis = new FileInputStream( " dos.txt " );

37

BufferedInputStream bis = new BufferedInputStream(fis);

38

DataInputStream dis = new DataInputStream(bis);

39

System.out.println(dis.readByte());

40

System.out.println(dis.readShort());

41

System.out.println(dis.readInt());

42

System.out.println(dis.readLong());

43

System.out.println(dis.readChar());

44

System.out.println(dis.readBoolean());

45

System.out.println(dis.readFloat());

46

System.out.println(dis.readDouble());

47

dis.close();

48

}

49


50

}

-------------------------------------------------------------------------------

运行结果:数据正常输出:

3

4

78

100000

a

false

4.5

4.0001

-------------------------------------------------------------------------------

4、PipedInputStream和PipedOutputStream

管道流,用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流。

-------------------------------------------------------------------------------

------------

Java API:

------------

java.io

类 PipedInputStream

java.lang.Object

java.io.InputStream

java.io.PipedInputStream

所有已实现的接口:

Closeable

public class PipedInputStream

extends InputStream

传送输入流应该连接到传送输出流;传送输入流会提供要写入传送输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能会死锁该线程。传送输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。

从以下版本开始:

JDK1.0

-------------------------------------------------------------------------------

------------

Java API:

------------

java.io

类 PipedOutputStream

java.lang.Object

java.io.OutputStream

java.io.PipedOutputStream

所有已实现的接口:

Closeable, Flushable

public class PipedOutputStream

extends OutputStream

传送输出流可以连接到传送输入流,以创建通信管道。传送输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream 读取。不建议对这两个对象尝试使用单个线程,因为这样可能会死锁该线程。

从以下版本开始:

JDK1.0

-------------------------------------------------------------------------------

------------

Java API:

------------

connect

public void connect(PipedInputStream snk)

throws IOException

将此传送输出流连接到接收者。如果此对象已经连接到其他某个传送输入流,则抛出 IOException。

如果 snk 为未连接的传送输入流,而 src 为未连接的传送输出流,则可以通过以下任一调用使其连接:

src.connect(snk)

或:

snk.connect(src)

这两个调用的效果相同。

参数:

snk - 要连接的传送输入流。

抛出:

IOException - 如果发生 I/O 错误。

-------------------------------------------------------------------------------

-------------------------------------------------------------------------------

-------------------------------------------------------------------------------

Demo9:利用管道输入流和输出流进行通讯。

-------------------------------------------------------------------------------

1

import java.io. * ;

2


3

public class PipedStreamDemo {

4


5

public static void main(String[] args) {

6

PipedOutputStream pos = new PipedOutputStream();

7

PipedInputStream pis = new PipedInputStream();

8


9

try {

10

pos.connect(pis);

11

// pis.connect(pos); 二选一即可

12


13

new Producer(pos).start();

14

new Consumer(pis).start();

15

} catch (IOException e) {

16

// TODO 自动生成 catch 块

17

e.printStackTrace();

18

}

19

}

20


21

}

22


23

/*

24

* 生产者线程

25

*/

26

class Producer extends Thread {

27


28

private PipedOutputStream pos;

29


30

public Producer(PipedOutputStream pos) {

31

this .pos = pos;

32

}

33


34

public void run() {

35

try {

36

pos.write( " Hello, welcome you! " .getBytes());

37

pos.close();

38

} catch (Exception e) {

39

e.printStackTrace();

40

}

41

}

42


43

}

44


45

/*

46

* 消费者线程

47

*/

48

class Consumer extends Thread {

49


50

private PipedInputStream pis;

51


52

public Consumer(PipedInputStream pis) {

53

this .pis = pis;

54

}

55


56

public void run() {

57

try {

58

byte [] buf = new byte [ 100 ];

59

int len = pis.read(buf);

60

System.out.println( new String(buf, 0 , len));

61

pis.close(); // 关闭输入流

62

} catch (Exception e) {

63

e.printStackTrace();

64

}

65

}

66


67

}

68


-------------------------------------------------------------------------------

运行结果:输出Hello, welcome you!

-------------------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: