Java IO:面向流、同步、堵塞式IO(BIO)
转载请注明出处:jiq•钦's technical Blog
备注:阅读此文之前,建议先看我这篇博文了解堵塞式IO和非堵塞式IO的基本概念。
JAVA BIO是面向流(字节流、字符流)的,即从流中一次读取一个或者多个字节,读取和写入时都须要同步堵塞直至完毕。
一、流(Stream)
1、字节流
输入(InputStream)
介质流 | ||
FileInputStream | 从文件里读取信息 | |
PipedInputStream | 产生用于写入相关PipedOutputStream的数据,实现“管道化”概念 | |
ByteArrayInputStream | 同意将内存缓冲区当做InputStream使用 | |
处理流 | ||
SequenceInputStream | 将两个或多个InputStream转换为单个InputStream | |
ObjectInputStream | 对象输入流 | |
FilterInputStream子类 | ||
| BufferedInputStream | 防止每次读取时都进行实际写操作。代表“使用缓冲区” |
DataInputStream | 与DataOutputStream配合使用,能够依照可移植的方式从流读取基本数据类型(int、char、long等) | |
LineNumberInputStream |
| |
PushbackInputStream |
| |
输出(OutputStream)
介质流 | ||
FileOutputStream | 用于将信息写至文件 | |
PipedOutputStream | 不论什么写入当中的信息都会自己主动作为相关PipedInputStream的输出,实现“管道化”概念 | |
ByteArrayOutputStream | 在内存中创建缓冲区,全部送往“流”的数据都放置在此缓冲区 | |
处理流 | ||
ObjectOutputStream | 对象输出流 | |
FilterOutputStream子类 | ||
| BufferedOutputStream | 避免每次发送数据时都要进行实际的写操作,代表“使用缓冲区” |
DataOutputStream | 与DataInputStream配合使用,依照可移植的方式向流中写入基本类型数据(int、char、long等) | |
PrintStream | 用于产生格式化输出,DataOutputStream处理数据的存储,PrintStream处理显示 | |
2、字符流
输入(Reader)
介质流 | |
FileReader | FileInputStream的相应 |
CharArrayReader | ByteArrayInputStream的相应 |
PipedReader | PipedInputStream的相应 |
处理流 | |
BufferedReader | BufferedInputStream的相应 |
InputStreamReader | 用于将InputStream转换为Reader |
输出(Writer)
介质流 | |
FileWriter | FileOuputStream的相应 |
CharArrayWriter | ByteArrayOutputStream的相应 |
PipedWriter | PipedOutputStream的相应 |
处理流 | |
BufferedWriter | BufferedOutputStream的相应 |
OutputStreamWriter | 用于将OutputStream转换为Writer |
字节流与字符流:
(1)读写单位不同:字节流以字节(8bit)为单位。字符流以字符为单位。依据码表映射字符,一次可能读多个字节。
(2)处理对象不同:字节流能处理全部类型的数据(如图片、avi等)。而字符流仅仅能处理字符类型的数据。
(3)字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的。而字符流在操作的时候下后是会用到缓冲区的。是通过缓冲区来操作流。比方用两种方式分别写文件,可是写完之后不关闭流,最后你能够发现字节流写的文件有内容、而字符流没有。
(4)设计Reader/Writer继承层次主要是为了国际化。字节流仅支持8位的读写。不能非常优点理16位的Unicode字符。java本身的char是16位的,加入字符流就是为了在全部IO操作中都支持Unicode。
建议:
在处理字符、尤其是中文文本时优先选择字符流!
在处理其他格式如图片、音频等文件时仅仅能採用字节流!
由此基本能够觉得,能用字符流就用,一旦无法满足需求,再考虑字节流!
!
!
装饰器设计模式(Decorator):
上面的流中,字节流和字符流各自内部的“处理流”能够包装其他“处理流”和“介质流”。而InputStreamReader和OutputStreamWriter能够包装字节流,提供了字节流到字符流的转换功能。
二、输入输出(IO)
1、文件IO
字节流:
public static void main(String[] args)throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
InputStream in=new FileInputStream(f);
byte[] b=new byte[1024];
int count =0;
int temp=0;
while((temp=in.read())!=(-1)){
b[count++]=(byte)temp;
}
in.close();
System.out.println(new String(b));
}字符流:
public static void main(String[] args)throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
char[] ch=new char[100];
Reader read=new FileReader(f);
int temp=0;
int count=0;
while((temp=read.read())!=(-1)){
ch[count++]=(char)temp;
}
read.close();
System.out.println("内容为"+new String(ch,0,count));
}2、内存IO
public static void main(Stringargs[])throws IOException {
Stringstr = “Hello,jiyiqin”;
ByteArrayInputStreambInput = new ByteArrayInputStream(str.getBytes());
System.out.println("Convertingcharacters to Upper case " );
for(int y = 0 ;y < 1; y++ ) {
while(( c= bInput.read())!= -1) {
System.out.println(Character.toUpperCase((char)c));
}
bInput.reset();
}
}3、管道IO
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class PipedInputStreamTest {
public static void main(String args[]) {
PipedInputStream input = new PipedInputStream();
PipedOutputStream output = new PipedOutputStream();
try {
output.connect(input);
new Thread(new OutputstreamRunnable(output)).start();
new Thread(new InputstreamRunnable(input)).start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//输出管道流线程
class OutputstreamRunnable implementsRunnable {
private OutputStream out;
public OutputstreamRunnable(OutputStream output) {
this.out = output;
}
@Override
public void run() {
String str = "hello pipe";
try {
out.write(str.getBytes());
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//输入管道流线程
class InputstreamRunnable implementsRunnable {
private InputStream in;
public InputstreamRunnable(InputStream in) {
this.in = in;
}
@Override
public void run() {
byte[] bs = new byte[1024];
int len = -1;
try {
if ((len = in.read(bs)) != -1) {
System.out.println(newString(bs, 0, len));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}4、网络IO
服务端代码
public class Server {
public static void main(String args[]) throws IOException {
int port = 8888;
ServerSocket server = new ServerSocket(port);
Socket socket = server.accept();
Reader reader = new InputStreamReader(socket.getInputStream());
char chars[] = new char[64];
int len;
StringBuilder sb = new StringBuilder();
while ((len=reader.read(chars)) != -1) {
sb.append(new String(chars, 0, len));
}
System.out.println("from client: " + sb);
reader.close();
socket.close();
server.close();
}
} 客户端代码
public class Client {
public static void main(String args[]) throws Exception {
String host = "127.0.0.1";
int port = 8888;
Socket client = new Socket(host, port);
Writer writer = new OutputStreamWriter(client.getOutputStream());
writer.write("Hello Server.");
writer.flush();
writer.close();
client.close();
}
}
浙公网安备 33010602011771号