2 u011787561 u011787561 于 2014.12.19 11:09 提问

java关于PrintWriter调用write方法之后使用flush方法获取不到内容原因探究求解惑!

PrintWriter ps= new PrintWriter(socket.getOutputStream());

ps.write( "hello" );
ps.flush();
服务端获取不到hello信息,看了下PrintWriter源码,flush()中调用的是BufferedWriter中的flush(),如果这样的话,应该能刷新缓冲得到结果。但是没有。。。网上找到个说法,原文是这样的"为什么客户端调用了write()和flush()后,服务器端依然read不到数据。因为socket.getOutputStream()取到的实现类是java.net.SocketOutputStream,这个类并没有覆写flush方法,它的父类java.io.FileOutputStream也没有覆写,于是最终就调到了最顶层java.io.OutputStream的flush()方法,这就恶心了,这个方法是空的。于是...",如果这个说法是对的话,为什么我定义的PrintWriter对象会调用SocketOutputStream里面的flush()?如果这个说法不对,那么是什么导致调用write()之后flush()无效?求解惑,万分感谢!

5个回答

jk_3699
jk_3699   2014.12.19 11:11

.close()之后才会有内容吧

u011787561
u011787561   2014.12.19 11:12

对,close()确实可以,但是flush()为什么不可以呢

u011787561
u011787561 回复jk_3699: 现在我费解的是PrintWriter中的println(String s)方法flush是可以获取的,但是调用write(String s)之后flush就感觉没有效果
大约 3 年之前 回复
jk_3699
jk_3699 如果非得纠结flush()没有,那就去研究flush()和 close()的代码,flush()不调用也会执行,但是close()如果没有调用数据只是在内存中
大约 3 年之前 回复
yangyanggoods
yangyanggoods   2014.12.20 11:05

为什么我定义的PrintWriter对象会调用SocketOutputStream里面的flush()?

flush是一层层传下去的啊……PrintWriter.flush()调用BufferedWriter.flush(),BufferedWriter.flush()调用OutputStreamWriter.flush(),然后调用StreamEncoder.flush()。StreamEncoder的源代码没找到,但肯定最后还是调用了SocketOutputStream.flush()……

但是SocketOutputStream.flush()为空应该不构成问题,因为SocketOutputStream本身不缓存任何内容,而是将得到字节的立即输出,所以不需要flush

u011787561
u011787561 回复yangyanggoods: 我看了下PrintWriter的println(String s)和write(String s)方法,源码比较大的不同就是多了一句out.write(lineSeparator);这会不会就是println可以flush但是write不行的原因呢
大约 3 年之前 回复
yangyanggoods
yangyanggoods 你能不能给出你服务端和客户端的代码呢?感觉未必是flush的问题
大约 3 年之前 回复
u011787561
u011787561   2014.12.24 09:49

我这里贴下主要的2个方法
public void createClientSocket(){
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Socket s = new Socket("127.0.0.1", 9009);
PrintWriter pw = new PrintWriter(s.getOutputStream());
String str = br.readLine();
while(!"quit".equals(str)){
//这两行server端可以获取str
// pw.println(str);
// pw.flush();
//这两行server端获取不到str
pw.write(str);
pw.flush();
str = br.readLine();
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public void createServerSocket(){
    try {
        ServerSocket ss = new ServerSocket(9009);
        Socket s = ss.accept();
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String str;
        while((str = br.readLine())!=null){
            System.out.println(str);
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
aaaa456287
aaaa456287 回复yangyanggoods: 因为ReadLine的底层是检测\n来判定的,发送了也读不到
10 个月之前 回复
yangyanggoods
yangyanggoods 没测试,不过估计多半是这么个原因:服务端第一次readLine读到了println的数据,然后第二次readLine读到了null,导致过早结束循环,未能接受到客户端第二次flush的数据
大约 3 年之前 回复
tianshishangxin1
tianshishangxin1   2017.12.16 17:34

witer 后 是由于 少个分隔符,加上分隔符 就可以 了
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
out = new PrintWriter(this.socket.getOutputStream(), true);
String currentTime = null;
String body = null;
while (true) {
body = in.readLine();
if (body == null)
break;
LOGGER.info(" The time server receive order :" + body);
currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ?
new java.util.Date(System.currentTimeMillis()).toString() :
"BAD ORDER";
out.write(currentTime);
LOGGER.info(java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("line.separator")));
out.write(java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("line.separator")));
out.flush();
}

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!