在IO流中的字符流的使用时,会接触到缓冲区这样一个概念,什么是缓冲区呢?
实际上它就是一个临时的储存室,会暂时的将一些数据放在里面,当缓冲区的数据存满之后,他就会向下一级发送数据(清空缓冲区)。
此时,如果缓冲区接受的文件并没有装满,但是需要传输的数据已经发送完毕,缓冲区的数据会不会发送给下一级呢?
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class MyBrowser {
/**
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException,IOException {
Socket s = new Socket("127.0.0.1", 80);
// 模拟浏览器,给tomcat服务端发送符合http协议的请求消息
PrintWriter out = new PrintWriter(s.getOutputStream());
out.println("GET /myweb/1.html HTTP/1.1");
out.println("Host: 127.0.0.1:80");
out.println("Connection: close");
out.println("Accept: */*");
out.println("Accept-Language: zh-CN");
out.println("User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; SE 2.X MetaSr 1.0)");
out.println("Accept-Encoding: gzip, deflate");
out.println();
out.println() ;
InputStream in = s.getInputStream();
byte b[] = new byte[1024];
int leng = 0;
while ((leng = in.read(b)) != -1) {
String str = new String(b, 0, leng);
System.out.println(str);
}
s.close();
}
}
此时运行程序,会发现并不能得到从服务器发送过来的回馈信息,而且程序没有结束运行。
这一切的原因就是因为缓冲区储存了数据但是没有装满,他还继续等待着上一级继续向他发送数据,直到装满之后,再向下一级发送它所缓存的所有数据。
有什么方法能解决这一问题呢?
此时就需要用到public abstract void flush() throws IOException 这一方法,该方法的作用就是下达一条命令给缓冲区,让它将所储存的数据全部清空,即发送给下一级。
发散:
本例中使用的PrintWriter类,有一个构造方法可以实现自动刷新
public PrintWriter(OutputStream out, boolean autoFlush)
out
- 输出流
autoFlush
- boolean 变量;如果为 true,则
println、
printf 或
format 方法将刷新输出缓冲区
OutputStreamWriter.OutputStreamWriter(java.io.OutputStream)
本例修正一:
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class MyBrowser {
/**
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException,IOException {
Socket s = new Socket("127.0.0.1", 80);
// 模拟浏览器,给tomcat服务端发送符合http协议的请求消息
PrintWriter out = new PrintWriter(s.getOutputStream(),true); //这里的ture表示流会自动刷新,在后面可以不用使用flush()方法
out.println("GET /myweb/1.html HTTP/1.1");
out.println("Host: 127.0.0.1:80");
out.println("Connection: close");
out.println("Accept: */*");
out.println("Accept-Language: zh-CN");
out.println("User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; SE 2.X MetaSr 1.0)");
out.println("Accept-Encoding: gzip, deflate");
out.println();
out.println() ;
InputStream in = s.getInputStream();
byte b[] = new byte[1024];
int leng = 0;
while ((leng = in.read(b)) != -1) {
String str = new String(b, 0, leng);
System.out.println(str);
}
s.close();
}
}
修正二:
public class MyBrowser {
/**
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException,IOException {
Socket s = new Socket("127.0.0.1", 80);
// 模拟浏览器,给tomcat服务端发送符合http协议的请求消息
PrintWriter out = new PrintWriter(s.getOutputStream()); //这里的ture表示流会自动刷新,在后面可以不用使用flush()方法
out.println("GET /myweb/1.html HTTP/1.1");
out.println("Host: 127.0.0.1:80");
out.println("Connection: close");
out.println("Accept: */*");
out.println("Accept-Language: zh-CN");
out.println("User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; SE 2.X MetaSr 1.0)");
out.println("Accept-Encoding: gzip, deflate");
out.println();
out.println() ;
out.flush();
InputStream in = s.getInputStream();
byte b[] = new byte[1024];
int leng = 0;
while ((leng = in.read(b)) != -1) {
String str = new String(b, 0, leng);
System.out.println(str);
}
s.close();
}
}
总结:在使用IO流并且使用到缓冲区的时候,一定要谨记flush()方法的使用,也许其它需要使用到缓冲区的地方,有可能也需要使用到刷新缓冲区这样类似的方法。