Java IO: PrintWriter

希望您在看这篇博客之前,知道Java IO技术,至少写过IO操作的Demo!

另外建议您看看:Java IO:IO流中的flush方法

这篇博客,主要使用Socket实例(很简单的小例子)来引出问题,然后在探讨问题。

1. Socket服务端

package mark.zhang; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(3000); Socket socket = server.accept(); InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String info = br.readLine(); System.out.println("server receive info: " + info); } } 2. Socket客户端

package mark.zhang; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; public class Client { public static void main(String[] args) throws Exception { Socket client = new Socket("127.0.0.1", 3000); OutputStream os = client.getOutputStream(); PrintWriter pw = new PrintWriter(os, true); pw.print("Hello,Server"); pw.close(); // pw.println("Hello,Server"); } }代码很简单,主要是客户端向服务端发送一个字符串,服务端将接收到的信息打印出来。

上面代码,运行(先运行Server.java后运行Client.java)之后,一切正常!

经过Debug,我发现,调用层次:

PrintWriter的 close()方法 ---> BufferedWriter的close()方法 --->OutputStreamWriter的close()方法 --->StreamEncoder的close()方法

BufferedWriter的close()方法源码:

public void close() throws IOException { synchronized (lock) { if (out == null) { return; } try { flushBuffer(); } finally { out.close(); out = null; cb = null; } }OutputStreamWriter的close()方法源码:
public void close() throws IOException { se.close(); }StreamEncoder的close()方法源码可以参看http://blog.csdn.net/androidbluetooth/article/details/6460726这篇文章的代码。

那么,我们做点调整,改变这些正常反应吧!修改客户端代码(注释掉pw.close()):

package mark.zhang; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; public class Client { public static void main(String[] args) throws Exception { Socket client = new Socket("127.0.0.1", 3000); OutputStream os = client.getOutputStream(); PrintWriter pw = new PrintWriter(os, true); pw.print("Hello,Server"); // pw.close(); // pw.println("Hello,Server"); } }服务端打印结果:

server receive info: null也就是说,没有接收到任何信息。也就是说,这种方式在服务端无法接收到信息。

恶作剧一把之后,我们再次修改代码,如下:

package mark.zhang; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; public class Client { public static void main(String[] args) throws Exception { Socket client = new Socket("127.0.0.1", 3000); OutputStream os = client.getOutputStream(); PrintWriter pw = new PrintWriter(os, true); //pw.print("Hello,Server"); //pw.close(); pw.println("Hello,Server"); } }ok,服务端可以接收到信息。看看PrintWriter类的println方法源码:

public void println(String x) { synchronized (lock) { print(x); println(); }public void print(String s) { if (s == null) { s = "null"; } write(s); }public void println() { newLine(); }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; } }lineSeparator定义:
lineSeparator = (String) java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("line.separator"));服务端的readLine()方法,遇到回车符就读一次数据(一行一行的读)。所以服务端可以收到信息。

3. 研究一下readLine

再次修改Client.java代码:

package mark.zhang; import java.io.DataOutputStream; import java.io.OutputStream; import java.net.Socket; public class Client { public static void main(String[] args) throws Exception { Socket client = new Socket("127.0.0.1", 3000); OutputStream os = client.getOutputStream(); DataOutputStream dos = new DataOutputStream(os); dos.writeBytes("Hello,Server1"); dos.writeBytes("\n"); dos.writeBytes("Hello,Server2"); //dos.close(); } }服务端接收信息:

server receive info: Hello,Server1说明,没有接收到Hello,Server2。这就说明,readLine遇到回车就算读完信息。

关于readLine()方法的其它用法,见下代码:

package csdn.zhwx; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.nio.charset.Charset; public class BufferedReaderTest { public static void getFile(String readFilePath, String readFileName, String writeFilePath, String writeFileName) { File reaFile = null; FileInputStream fis = null; BufferedReader bReader = null; File writeFile = null; FileOutputStream fos = null; BufferedWriter bWriter = null; try { if (!(readFileName == null || readFileName.length() <= 0)) { reaFile = new File(readFilePath + readFileName); fis = new FileInputStream(reaFile); // bReader = new BufferedReader(new InputStreamReader(fis,"GBK"));//指定GBK编码,一般用在汉化windows上。 // bReader = new BufferedReader(new InputStreamReader(fis));//默认编码,和系统编码一致。linux为UTF-8 bReader = new BufferedReader( new InputStreamReader(fis, "UTF-8"));// 指定UTF-8编码 writeFile = new File(writeFilePath, writeFileName); fos = new FileOutputStream(writeFile); // bWriter = new BufferedWriter(new OutputStreamWriter(fos));//默认编码,和系统编码一致。linux为UTF-8 bWriter = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"));// 指定UTF-8编码 String str = null; while ((str = bReader.readLine()) != null) {// 该方法不会将读取到的换行\n写到文件中 // System.out.println(str); // 要自己手动加\n bWriter.write(str + "\n"); /*bWriter.write(str); bWriter.newLine();*/ // 不刷新的话,文件不会有内容 bWriter.flush(); } } } catch (Exception e) { e.printStackTrace(); try { fis.close(); bReader.close(); fos.close(); bWriter.close(); } catch (IOException e1) { e1.printStackTrace(); } } finally { try { fis.close(); bReader.close(); fos.close(); bWriter.close(); } catch (IOException e1) { e1.printStackTrace(); } } } public static void main(String[] args) { getFile("/home/zhihui/Downloads/", "hello.txt", "/home/zhihui/Downloads/", "copyFormHello.txt"); //linux下测试 /*当前JRE:1.6.0_23 当前JVM的默认字符集:UTF-8*/ System.out.println("当前JRE:" + System.getProperty("java.version")); System.out.println("当前JVM的默认字符集:" + Charset.defaultCharset()); } }

你可能感兴趣的:(java,操作系统)