→阿童沐

財富==支撐一個人生存多長時間的能力!

导航

InputStream&OutputStream 与 Reader&Writer=

Java 中的字符是Unicode编码的,是双字节的(即:1char = 2bytes)。而InputStream与OutputStream是用来处理字节或字节数组的,在处理字符文本的时候时不太方便,需要编写额外的程序代码。

Java为字符文本的输入输出专门提供了一套单独的类,Reader、Writer两个抽象类与InputStream、OutputStream两个抽象类相对应,他们都有很多的子类,对具体的I/O设备进行字符输入输出,如:FileReader就是用来读取文件流中的字符的。

Reader、Writer与InputStream、OutputStream用法相类似,唯一区别是前者处理字符方便,后者处理字节方便。

另外:FileReader和FileWriter使用了缓冲区,而FileInputStream和FileOutputStream没有使用缓冲区。

例:

InputStream、OutputStream

package cn.edu.bupt;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class FileStream
{
public static void main(String[] args)
{
File f = new File("Hello.txt");

try
{
OutputStream os = new FileOutputStream(f);
byte[] txt = "hello world".getBytes();
os.write(txt);
os.close();
}
catch (IOException e)
{
// TODO: handle exception
e.printStackTrace();
}

try
{
InputStream is = new FileInputStream(f);
byte[] txt = new byte[100];
int len = is.read(txt);
String s = new String(txt, 0, len);
System.out.println(s);
is.close();
}
catch (IOException e)
{
// TODO: handle exception
e.printStackTrace();
}
}
}

 

Reader、Writer

package cn.edu.bupt;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

public class ReaderAndWriter
{
public static void main(String[] args)
{
File f = new File("hello.txt");

try
{
Writer writer = new FileWriter(f);
writer.write("hello,mylady");
writer.close();
}
catch (IOException e) {
e.printStackTrace();
}

try
{
Reader reader = new FileReader(f);
char[] c = new char[100];
int len = reader.read(c);
String s = new String(c, 0, len);
System.out.println(s);
reader.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}


现在介绍一些方法:

InputStream(abstract class

该类中的所有方法在遇到错误的时候都会引发IOException异常.

1> abstract int read()

  返回下一个输入字节(byte)的整型表示,如果返回-1表示遇到了流的末尾.

2> int read(byte[] b)

  在InputStream中读入b.length个字节放到b中,并返回实际读入的字节数.

3> int read(byte[] b, int off, int len)

  这个方法表示把流中的数据读到数组b中从下标为off开始的len个数组元素中.

4> long skip(long n)

  跳过输入流上的n个byte并返回实际跳过的字节数.

5> int available()

  返回当前输入流中的可读的字节数.

6.1> void mark(int readlimit)

  在输入流的当前位置出放置一个游标,允许最多再读入readlimit个字节.

6.2> void reset()

  把输入流中的指针返回到以前所做的游标处.

6.3> boolean markSupported()

  如果当前流支持mark/reset操作就返回true.

7> void close()

  在操作完一个流后要使用此方法将相关的系统资源进行释放.

 

OutputStream(abstract class

这个类中的方法均返回void,并在遇到错误的时候引发IOException异常

1> void write(int b)

  讲一个字节写到输入流,注意这里的参数是int型,它允许write使用表达式而不用强制转换成为byte类型.

  你写入的数值转化成Unicode了,例如你用write(65),你在文件里便就会看到一个大写字母'A'.

  写入的是字节,即使大于8位,只写低8位.

2> void write(byte[] b)

  将整个字节数组写到输出流中.

3> void write(byte[] b, int off, int len)

  将字节数组b中的从off开始的len个字节写到输出流中.

4> void flush()

  彻底完成输出并清空缓冲区.

5> void close()

  关闭输出流.

 例:

package cn.edu.bupt;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class FileStream
{
public static void main(String[] args)
{
new FileStream().transform(System.in, System.out);
}

private void transform(InputStream in, OutputStream out)
{
try
{
int c = -1;
while ((c = in.read()) != -1)
{
out.write(c);
out.flush();
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
System.out.println("close");
try
{
out.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
System.out.println("cannot close");
e.printStackTrace();
}
}
}
}

 具体的基本节点流类有

InputStream:

  1> FileInputStream

  2> PipedInputStream

  3> ByteArrayInputStream

OutputStream:

  1> FileOutputStream

  2> PipedOutputStream

  3> ByteArrayOutputStream

Reader:

  1> FileReader

  2> PipedReader 

  3> StringReader

Writer:

  1> FileWriter

  2> PipedWriter

  3> StringWriter


流的包装类:

包装类是针对基本流类而言的,因为基本流类仅仅提供了读写字节(byte)的方法,我们通过他们只能往文件中写入字节或从文件中读取字节,但是在实际应用中,我们要往文件中写入或读取各种类型的数据,我们就必须先将其他类型的数据转换成为字节数组后写入文件,或是将从文件中读取到的字节数组转换成为其他类型,这个就需要流包专类的帮助。

包装类提供了读写各种类型数据的各种方法,当我们需要写入其他类型的数据的时候,只要调用中间类中的对应的方法即可,在这个中间类的方法内部,他将其他数据类型转换成为字节数组,然后调用底层的节点流类将这个字节数组写入目标设备,这个中间类就是包装类。

例如io包中的DataOutputStream包装类中的方法如下:

public final void writeBoolean(boolean v) throws IOException;
public final void writeShort(short v) throws IOException;
public final void writeChar(char v) throws IOException;
public final void writeInt(int v) throws IOException;
public final void writeLong(long v) throws IOException;
public final void writeFloat(float v) throws IOException;
public final void writeDouble(double v) throws IOException;
public final void writeBytes(String s) throws IOException;

我们还可以用包装类去包装另外一个包装类。

创建包装类对象的时候,必须制定它要调用的那个底层流对象,也就是这些包装类的构造函数中,都必须接受另外一个流对象作为参数。例如:

public DataOutputStream(OutputStream out);

其中的out传入参数可以是OutputStream的任何一个子类或是包装类(其实也是他的子类,查看参考手册可以知道),这样最上层的包装类可以具有下层包装类的性质。

解析DataInputStream与DataOutputStream

DataOutputStream提供了三种写入字符串的方法:

public final void writeBytes(String s) throws IOException
public final void writeChars(String s) throws IOException
public final void writeUTF(String str) throws IOException

区别:

Java中的字符是Unicode编码,是双字节的,writeBytes()值时将字符串中的每一个字符的低字节位内容写入到目标设备中;而writeChars()将字符串中的每一个字符的两个字节内容都写入到目标设备中;writeUTF对字符串按照UTF的格式写入目标设备,UTF是带有长度头的,最开始的两个字节是对字符串进行UTF编码后的字节长度,然后才是每个字符的UTF编码。

在于DataOUtputStream类对应的输入流DataInputStream类中只提供了一个readUTF方法返回字符串,而没有提供其他两个与之对应的方法读入字符串,这是因为我们要在一个连续的字节流读取一个字符串(只是六种的一段内容),如果没有特殊的标记作为一个字符串的结尾,而且我们实现也不知道这个字符串的长度,我们是没有办法知道读取到什么位置才是这个字符串的结束。

在DataoutputStream类中只有writeUTF方法项目表设备中写入了字符串的长度,所以我们只能准确的读回这个方法写入的字符串。

例:

package cn.edu.bupt;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;



public class FileStream
{
public static void main(String[] args)
{
try
{
FileOutputStream fos = new FileOutputStream("hello.txt"); //基本节点流类
BufferedOutputStream bos = new BufferedOutputStream(fos);
DataOutputStream dos = new DataOutputStream(bos);

dos.writeUTF("abc 中国");
dos.writeBytes("abc 中国");
dos.writeChars("abc 中国");

dos.close();

FileInputStream fis = new FileInputStream("hello.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);

// byte[] b = new byte[100];
// int len = fis.read(b);
// String s = new String(b, 0, len); //按照字节数组读入,会出现乱码,因为读入的byte类型数据的机制不同
String s = dis.readUTF();
System.out.println(s);
dis.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}


PrintStream包装类:

PrintStream类提供了一些列的print和println方法

 

posted on 2012-03-12 12:05  阿童沐  阅读(501)  评论(0)    收藏  举报