java.io 字节流
基类 InputStream 和 OutputStream
字节流主要操作 byte 类型数据,以 byte 数组为准,java 中每一种字节流的基本功能依赖于基本类 InputStream 和 Outputstream,他们是抽象类,不能直接使用。字节流能处理所有类型的数据(如图片、avi 等)。
InputStream
InputStream 是所有表示字节输入流的基类,继承它的子类要重新定义其中所有定义的抽象方法.InputStream是从装置来源地读取数据的抽象表示,例如System中的标准输入流in对象就是一个InputStream类型的实例。
我们先来看看InputStream类的方法:
方法
说明
read()throws IOException
从输入流中读取数据的下一个字节(抽象方法)
skip(long n) throws IOException
跳过和丢弃此输入流中数据的n个字节
available() throws IOException
返回流中可用字节数
mark(int readlimit) throws IOException
在此输入流中标记当前的位置
reset() throws IOException
将此流重新定位到最后一次对此输入流调用mark方法时的位置
markSupport() throws IOException
测试此输入流是否支持mark 和 reset 方法
close() throws IOException
关闭流
在InputStream类中,方法read()提供了三种从流中读数据的方法;
int read(): 从输入流中读一个字节,形成一个0~255之间的整数返回(是一个抽象方法)
int read(byte b[]): 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中。
int read(byte b[], int off,int len): 从输入流中读取长度为len的数据,写入数组b中从索引off开始的位置,并返回读取的字节数。
对于这三个方法,若返回-1,表明流结束,否则,返回实际读取的字符数。
OutputStream
OutputStream 是所有表示字节输出流类的基类。子类要重新定义其中所定义的抽象方法,OutputStream 是用于将数据写入目的地的抽象表示。例如 System 中的标准输出流对象 out 其类型是 java.io.PrintStream,这个类是 OutputStream 的子类。
OutputStream 类方法:
方法
说明
write(int b)throws IOException
将指定的字节写入此输出流(抽象方法)
write(byte b[])throws IOException
将字节数组中的数据输出到流中
write(byte b[], int off, int len)throws IOException
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流
flush()throws IOException
刷新此输出流并强制写出所有缓冲的输出字节
close()throws IOException
关闭流
看个例子
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class test {
/**
* 把输入流中的所有内容赋值到输出流中
* @param in
* @param out
* @throws IOException
*/
public void copy(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[4096];
int len = in.read(buf);
//read 是一个字节一个字节地读,字节流的结尾标志是-1
while (len != -1){
out.write(buf, 0, len);
len = in.read(buf);
}
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
test t = new test();
System.out.println("输入字符:");
t.copy(System.in, System.out);
}
}
文件流
在 I/O 处理中,最常见的就是对文件的操作。java.io 包中所提供的文件操作类包括
用于读写本地文件系统中的文件:FileInputStream 和 FileOutputStream
描述本地文件系统中的文件或目录: File、FileDescriptor 和 FilenameFilter
提供对本地文件系统中文件的随机访问支持:RandomAccessFile
今天我们来学习文件流的FileInputStream 和 FileOutputStream
FileInputStream 类用于打开一个输入文件,若要打开的文件不存在,则会创建一个新的文件,否则原文件的内容会被新写入的内容所覆盖;
在进行文件的读/写操作时,会产生非运行时异常IOException,必须捕获或声明抛弃(其他的输入/输出流处理时也同样需要进行输入/输出异常处理)
文件构造方法:
//打开一个以 f 描述的文件作为输入
FileInputStream(File f)
//打开一个文件路径名为 name 的文件作为输入
FileInputStream(String name)
//创建一个以 f 描述的文件作为输出
//如果文件存在,则其内容被清空
FileOutputStream(File f)
//创建一个文件路径名为 name 的文件作为输出
//文件如果已经存在,则其内容被清空
FileOutputStream(String name)
//创建一个文件路径名为 name 的文件作为输出
//文件如果已经存在,则在该输出上输出的内容被接到原有内容之后
FileOutputStream(String name, boolean append)
示例代码 :
File f1 = new File("file1.txt");
File f2 = new File("file2.txt");
FileInputStream in = new FileInputStream(f1);
FileOutputStream out = new FileOutputStream(f2);
输入流的参数是用于指定输入的文件名,输出流的参数则是用于指定输出的文件名
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class test {
public static void main(String[] args) {
try {
//inFile 作为输入流的数据文件必须存在,否则抛出异常
File inFile = new File("/Users/mumutongxue/Documents/file1.txt");
//file2.txt 没有,系统可以创建,在 workspace 的 Test 项目下可以找到
File outFile = new File("file2.txt");
FileInputStream fis = new FileInputStream(inFile);
FileOutputStream fos = new FileOutputStream(outFile);
int c;
while((c = fis.read()) != -1){
fos.write(c);
}
//打开了文件一定要记着关,释放系统资源
fis.close();
fos.close();
}catch(FileNotFoundException e) {
System.out.println("FileStreamsTest:" + e);
}catch(IOException e){
System.err.println("FileStreamTest:" + e);
}
}
}
缓冲流
类BufferedInputStream 和 BufferedOutoutStream 实现了带缓冲的过滤流,它提供了缓冲机制,把任意的I/O流“捆绑”到缓冲流上,可以提高I/O流的读取效率
在初始化时,除了要指定所连接的I/O流之外,还可以指定缓冲区的大小,缺省时是用32字节大小的缓冲区;最优的缓冲区大小以来于主机操作系统、可使用的内存空间以及机器的配置等;一般缓冲区的大小为内存页或磁盘块等的整数倍
BufferedInputStream 的数据成员buf是一个位数组,默认为2048字节,当读取数据来源时例如文件,BufferedInputStream 会尽量将buf填满。当使用read() 方法时,实际上是先读取buf中的数据,而不是直接对数据来源作读取。当buf中的数据不足时,BufferedInputStream 才会再实现给定的InputStream对象的read() 方法,从指定的装置中提取数据。
BufferedInputStream 的数据成员 buf 是一位数组,默认为512字节。当使用write() 方法写入数据时,实际上会先将数据写至buf中,当buf已满时才会实现给定的OutputStream 对象的write() 方法,将buf数据写至目的地,而不是每次都对目的地作写入的动作。
构造方法:
//[ ] 里的内容代表选填
BufferedInputStream(InputStream in [, int size])
BufferedOutputStream(OutputStream out [, int size])
举个例子,将缓冲流与文件流相接
FileInputStream in = new FileInputStream("file.txt");
FileOutputStream out = new FileOutputStream("file2.txt");
//设置输入缓冲区大小为 256 字节
BufferedInputStream bin = new BufferedInputStream(in,256)
BufferedOutputStream bout = new BufferedOutputStream(out,256)
int len;
byte bArray[] = new byte[256];
len = bin.read(bArray); //len 中得到的是实际读取的长度,bArray 中得到的是数据
对于 BufferedOutputStream,只有缓冲区满时,才会将数据真正送到输出流,但可以使用 flush() 方法人为地将尚未填满的缓冲区中的数据送出。
例如方法copy();
public void copy(InputStream in, OutputStream out) throws IOException {
out = new BufferedOutputStream(out, 4096);
byte[] buf = new byte[4096];
int len = in.read(buf);
while (len != -1) {
out.write(buf, 0, len);
len = in.read(buf);
}
//最后一次读取得数据可能不到 4096 字节
out.flush();
}
数据流
接口 DataInput 和 DataOutput,设计了一种较为高级的数据输入输出方式:除了可处理字节和字节数组外,还可以处理 int、float、boolean 等基本数据类型,这些数据在文件中的表示方式和它们在内存中的一样,无须转换,如 read(), readInt(), readByte()...; write(), writeChar(), writeBoolean()... 此外,还可以用 readLine() 方法读取一行信息。
方法 :
方法
返回值
说明
readBoolean()
boolean
readByte()
byte
readShort()
short
readChar()
char
readInt()
int
readLong()
long
readDouble()
double
readFloat()
float
readUnsignedByte()
int
readUnsignedShort()
int
readFunlly(byte[] b)
void
从输入流中读取一些字节,并将它们存储在缓冲区数组b中
reaFully(byte[] b, int off, int len)
void
从输入流中读取len个字节
skipBytes(int n)
int
与InputStream.skip 等价
readUTF()
String
按照UTF-8形式从输入中读取字符串
readLine()
String
按回车(\r)换行(\n)为分隔符读取一行字符串,不完全支持UNICODE
writeBoolean(boolean v)
void
writeByte(int v)
void
writeShort(int v)
void
writeChar(int v)
void
writeInt(int v)
void
writeLong(long v)
void
writeFloat(float v)
void
writeDouble(double v)
void
write(byte[] b)
void
与OutputStream.write 同义
write(byte[] b,int off,int len)
void
与OutputStream.write 同义
write(int b)
void
与OutputStream.write 同义
writeBytes(String s)
void
只输出每个字符的低 8 位;不完全支持 UNICODE
writeChars(String s)
void
每个字符在输出中都占两个字节
数据流类 DataInputStream 和 DataOutputStream 的处理对象除了是字节或字节数组外,还可以实现对文件的不同数据类型的读写;
分别实现了DataInput 和 DataOutput 接口
在提供字节流的读写手段同时,以统一的形式向输入流中写入boolean,int,long,double 等基本数据类型,并可以再次把基本数据类型的值取回来
提供了字符串读写的手段
数据流可以连接一个已经建立好的数据对象,例如网络连接、文件等。数据流可以通过如下方式建立;
FileInputStream fis = new FileInputStream("file1.txt");
FileOutputStream fos = new FileOutputStream("file2.txt");
DataInputStream dis = new DataInputStream(fis);
DataOutputStream dos = new DataOutputStream(fos);
接下来我们通过具体的代码,看一看它的用法吧;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataStream {
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
//向文件 a.txt 写入
FileOutputStream fos = new FileOutputStream("a.txt");
DataOutputStream dos = new DataOutputStream(fos);
try {
dos.writeBoolean(true);
dos.writeByte((byte)123);
dos.writeChar('J');
dos.writeDouble(3.1415926);
dos.writeFloat(2.122f);
dos.writeInt(123);
}
finally {
dos.close();
}
//从文件 a.txt 读出
FileInputStream fis = new FileInputStream("a.txt");
DataInputStream dis = new DataInputStream(fis);
try {
System.out.println("\t" + dis.readBoolean());
System.out.println("\t" + dis.readByte());
System.out.println("\t" + dis.readChar());
System.out.println("\t" + dis.readDouble());
System.out.println("\t" + dis.readFloat());
System.out.println("\t" + dis.readInt());
}
finally {
dis.close();
}
}
}
标准流、内存读写流、顺序输入流
标准流
语言包 java.lang 中的System类管理标准输入/输出流和错误流
System.in 从InputStream中继承而来,用于从标准输入设备中获取输入数据(通常是键盘)
System.out 从PrintStream 中继承而来,把输入送到缺省的显示设备(通常是显示器)
System.err 也是从PrintStream中继承而来,把错误信息送到缺省的显示设备(通常是显示器)
每当mian方法被执行时,就会自动生产上述三个对象。这里就不再写代码验证了。
内存读写流
为了支持在内存上的I/O,java.io 中提供了类;ByteArrayInputStream、ByteArrayOutputStream 和 StringBufferInputStream
ByteArrayInputStream 可以从指定的字节数组中读取数据
ByteArrayOutputStream 中提供了 缓冲区可以存放数据(缓冲区大小可以在构造方法中设定,缺省为32),可以用write() 方法 向其中写入数据,然后用toByArray() 方法将缓冲区中的有效字节写到字节数组中去。size() 方法可以知道写入的字节数; reset() 可以丢弃所有内容
StringBufferInputStream 与 ByteArrayInputStream 相类似,不同点在于它是从字符缓冲区 StringBuffer 中读取 16位的 Unicode 数据,而不是 8 位的字节数据(已被StringReader取代)
这里只做简要的介绍,有兴趣的同学可以查看一下这些类里具体的方法。
顺序输入流
java.io 中提供了类SequenceInputStream, 使应用程序可以将几个输入流顺序连接起来。顺序输入流提供了将多个不同的输入流统一为一个输入流的功能,这使得程序可能变得更加简洁
例如:
FileInputStream f1,f2;
String s;
f1 = new FileInputStream("file1.txt");
f2 = new FileInputStream("file2.txt");
SequenceInputStream fs = new SequenceInputStream(f1,f2);
DataInputeStream ds = new DataInputStream(fs);
while((s = ds.readLine()) != null) {
System.out.println(s);
}
参考连接