printWriter的write(String x)和println(String x)区别分析

来源:互联网 发布:hadoop与java的关系 编辑:程序博客网 时间:2024/05/16 17:53

当当当当~第一篇技术博客来了,虽然是非常简单非常小白的一篇分析,但毕竟是一个开始。以后这些东西都不再只躺在我的有道云笔记里了,so,必须更加严谨,更加扎实的理解和总结~

前言:
在写一个socket通信的小模块,client端一开始用了PrintWriter的write(String x)方法,结果server端一直没反映,后来改为println(String x)方法功能正常了。于是自己分析了一下这两个方法的源码,看一下两者的区别。

具体分析:
两种写法分别如下

   写法1   out =new PrintWriter(socket.getOutputStream());   out.**write**("hellow server");   **out.flush()**;   写法2   out =new PrintWriter(socket.getOutputStream());      out.**println**("hellow server");   **out.flush()**;

这两种写法都做了flush,所以不可能是flush的问题。先看一下println(String x)方法源码

   public void println(String x) {         synchronized (lock) {             print(x);             println();         }    }
    public void print(String s) {         if (s == null) {             s = "null";         }         write(s);    }

通过这两个方法的追踪可以发现,println也是调用write方法,但是比write方法多了一个println()执行,

   public void println() {         newLine();    }
    private void newLine() {     try {             synchronized (lock) {                  ensureOpen();                  out.write(lineSeparator);                  if (autoFlush)                          out.flush();                    }         } catch (InterruptedIOException x) {              Thread.currentThread().interrupt();        } catch (IOException x) {              trouble = true;         }    }

重点就是这句 out.write(lineSeparator);

这时候不禁要问“lineSeparator什么鬼”了

lineSeparator = (String) java.security.AccessController.doPrivileged(               new sun.security.action.GetPropertyAction("line.separator"));

看了之后依然一头雾水 ,那我们换一个角度,研究下server端Reader的readLine是怎么做的,readLine方法比较长,把其中比较关键的截取一下:

 charLoop:  for (i = nextChar; i < nChars; i++) {      c = cb[i];      if ((c == '\n') || (c == '\r')) {           eol = true;           break charLoop;      }  }
  if (eol) {      String str;      if (s == null) {           str = new String(cb, startChar, i - startChar);      } else {           s.append(cb, startChar, i - startChar);           str = s.toString();      }          nextChar++;          if (c == '\r') {               skipLF = true;          }          return str;  }

我们看到标红的部分当遇到\n或者\r的时候才会返回一行记录,否则将一直等待的。立刻,写代码验证了一下:

os.writer("hellow server\n");os.writer("hellow server\r");os.writer("hellow server\n\r");

这三种方式都能成功的让server端打印出收到的数据。所以不难猜测lineSeparator就是“\n\r”了。

总结:

有时候源码就像一层窗户纸,在外面觉得很神秘,实际捅破以后就豁然开朗了。今天虽然只是分析了一个非常非常简单的东西,但是知识不在小,滴水成海,所以,继续翻滚吧,代码君!

0 0
原创粉丝点击