流
网络程序所做的很大一部分工作就是简单的输入输出:将 数据字节从一个系统移动到另一个系统。
java的IO建立在流之上,输入流读取数据,输出流写入数据,不同的流类会读某个特定的数据源。
所有的输入输出流都有相同的基本方法来写入和读出数据.创建流后,就可以忽略读写的具体细节.
过滤器流
过滤器流可以串联到输入输出流上.读写数据时,过滤器可以修改数据(例如加密或压缩),或提供额外的方法,将读/写数据转换为其他格式.
例如:DataInputStream类就提供了一个方法,可以将int转换为4字节,并把这些字节写入底层的输出流。
阅读器和书写器
可以串联到输入输出流上,允许读写字符文本,而不是字节。只要正确 的使用,阅读器和书写器还可以处理很多字符编码,包括多字节字符(UTF-8)
输出流 OutPutStream
五种基本方法
- write(int b):参数是一个0-255之间的整数(无符号字节)
- wirte(byte[] data)
- write(byte[] data,int offset,int length)
- flush()
- close()
输出流的子类利用以上方法想不同的介质中写入数据
每次写单个字节
//字符生成器,think in java中有该段代码,每次只写入一个字节
public static void generateCharacters(OutputStream out) throws IOException{
int firstPintableCharater = 33;
int numberOfprintableCharaters = 94;
int numberOfCharatersPerLine = 72;
int start = firstPintableCharater;
final boolean flag = true;
while(flag){
for(int i = start;i< start + numberOfCharatersPerLine;i++){
out.write((
(i-firstPintableCharater) % numberOfprintableCharaters) + firstPintableCharater);
}
out.write('\r');//回车
out.write('\n');//换行
start = ((start + 1) - firstPintableCharater) % numberOfprintableCharaters + firstPintableCharater;
}
}
每次写一个字节数组
public static void generateCharacters2(OutputStream out) throws IOException{
int firstPintableCharater = 33;//起始字符
int numberOfprintableCharaters = 94;//一共有多少字符
int numberOfCharatersPerLine = 72;//每行有多少字符
int start = firstPintableCharater;
byte[] line = new byte[numberOfCharatersPerLine+2];//+2对应回车和换行
while(true){
for(int i=start;i<start + numberOfCharatersPerLine;i++){
line[i - start] = (byte) ((i - firstPintableCharater)
% numberOfprintableCharaters + firstPintableCharater);
}
line[72] = (byte)'\r';
line[72] = (byte)'\n';
out.write(line);
start = ((start + 1) - firstPintableCharater)
% numberOfprintableCharaters + firstPintableCharater;
}
}
缓冲流
写完数据后一定要flush()避免死锁。因为默认情况下只有缓冲区满才会发送数据,
流结束
当一个流结束后一定要调用close方法将其关闭。一旦输入流关闭,继续写入就会发生IOException异常
模板:
//处理一个输出流的模板
OutPutStream out = null;
try{
out = new FileOutPutstream("/tmp/data.txt");
//处理输出流
}catch(IOException e){
System.err.println(e.getMessage());
}finally{
if(out != null){
fry{
out.close();
}catch(IOException e){
//忽略
}
}
}
以上模板成为释放模式,不仅适用于流,也使用与socket、通道、JDBC连接等
带资源的try
java7引进了带资源的try,可以简洁的完成这个清理。流可以在try块的参数表中声明。
try(OutputStream out = new FileOutPutStream("/tmp/data.txt")){
//处理流
}catch(IOException e){
System.err.println(e.getMessage());
}
输入流
InputStream的子类从各种介质中读取数据,
基本方法
- int read():从输入流的源中读取一个字节作为int返回。
- int read(byte[] input)从输入源填充指定的数组input
- int read(byte[] input,int offset,int length)
- long skip(long n)
- int available()
- close()
方法2尝试填充一个数组,单不一定会成功,例如input[1024],但输入源只有512个字节,考虑到这一点,方法会返回实际读取的字节数
byte[] input = new byte[1024];
//bytesRead就是本次读取到的实际字节数
int bytesRead = in.read(input)
//下面这段代码非常重要
int bytesRead = 0; //从输入流读取的字节数
int bytesToRead = 1024; //一共要读取的字节数
byte[] input = new byte[bytesToRead];
while(){
bytesRead += in.read(
input,//存储读取数据的数组
bytesRead,//已经读取的字节数,本次读取以它为起点开始
bytesToRead - bytesRead//剩余的字节数量
);
}
}