PrintWriter应用实例

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

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

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

1. Socket服务端

[java] view plain copy print ?
  1. package mark.zhang;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.InputStream;  
  5. import java.io.InputStreamReader;  
  6. import java.net.ServerSocket;  
  7. import java.net.Socket;  
  8.   
  9. public class Server {  
  10.   
  11.     public static void main(String[] args) throws Exception {  
  12.         ServerSocket server = new ServerSocket(3000);  
  13.         Socket socket = server.accept();  
  14.         InputStream is = socket.getInputStream();  
  15.         BufferedReader br = new BufferedReader(new InputStreamReader(is));  
  16.         String info = br.readLine();  
  17.         System.out.println("server receive info: " + info);  
  18.     }  
  19.   
  20. }  
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客户端

[java] view plain copy print ?
  1. package mark.zhang;  
  2.   
  3. import java.io.OutputStream;  
  4. import java.io.PrintWriter;  
  5. import java.net.Socket;  
  6.   
  7. public class Client {  
  8.     public static void main(String[] args) throws Exception {  
  9.         Socket client = new Socket("127.0.0.1"3000);  
  10.         OutputStream os = client.getOutputStream();  
  11.         PrintWriter pw = new PrintWriter(os, true);  
  12.         pw.print("Hello,Server");  
  13.         pw.close();  
  14.         // pw.println("Hello,Server");   
  15.     }  
  16. }  
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()方法源码:

[java] view plain copy print ?
  1. public void close() throws IOException {  
  2.     synchronized (lock) {  
  3.         if (out == null) {  
  4.         return;  
  5.         }  
  6.         try {  
  7.             flushBuffer();  
  8.         } finally {  
  9.             out.close();  
  10.             out = null;  
  11.             cb = null;  
  12.         }  
  13.     }  
public void close() throws IOException {
	synchronized (lock) {
	    if (out == null) {
		return;
	    }
	    try {
	        flushBuffer();
	    } finally {
	        out.close();
	        out = null;
	        cb = null;
	    }
	}
OutputStreamWriter的close()方法源码:
[java] view plain copy print ?
  1. public void close() throws IOException {  
  2.     se.close();  
  3. }  
public void close() throws IOException {
	se.close();
}
StreamEncoder的close()方法源码可以参看 http://blog.csdn.net/androidbluetooth/article/details/6460726这篇文章的代码。

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

[java] view plain copy print ?
  1. package mark.zhang;  
  2.   
  3. import java.io.OutputStream;  
  4. import java.io.PrintWriter;  
  5. import java.net.Socket;  
  6.   
  7. public class Client {  
  8.     public static void main(String[] args) throws Exception {  
  9.         Socket client = new Socket("127.0.0.1"3000);  
  10.         OutputStream os = client.getOutputStream();  
  11.         PrintWriter pw = new PrintWriter(os, true);  
  12.         pw.print("Hello,Server");  
  13.         // pw.close();   
  14.         // pw.println("Hello,Server");   
  15.     }  
  16. }  
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");
	}
}
服务端打印结果:

[java] view plain copy print ?
  1. server receive info: null  
server receive info: null
也就是说,没有接收到任何信息。也就是说,这种方式在服务端无法接收到信息。

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

[java] view plain copy print ?
  1. package mark.zhang;  
  2.   
  3. import java.io.OutputStream;  
  4. import java.io.PrintWriter;  
  5. import java.net.Socket;  
  6.   
  7. public class Client {  
  8.     public static void main(String[] args) throws Exception {  
  9.         Socket client = new Socket("127.0.0.1"3000);  
  10.         OutputStream os = client.getOutputStream();  
  11.         PrintWriter pw = new PrintWriter(os, true);  
  12.         //pw.print("Hello,Server");   
  13.         //pw.close();   
  14.         pw.println("Hello,Server");  
  15.     }  
  16. }  
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方法源码:

[java] view plain copy print ?
  1. public void println(String x) {  
  2.     synchronized (lock) {  
  3.         print(x);  
  4.         println();  
  5. }  
public void println(String x) {
	synchronized (lock) {
	    print(x);
	    println();
}
[java] view plain copy print ?
  1. public void print(String s) {  
  2.     if (s == null) {  
  3.         s = "null";  
  4.     }  
  5.     write(s);  
  6. }  
public void print(String s) {
	if (s == null) {
	    s = "null";
	}
	write(s);
}
[java] view plain copy print ?
  1. public void println() {  
  2.     newLine();  
  3. }  
public void println() {
	newLine();
}
newLine()就是加入一个回车符:

[java] view plain copy print ?
  1. private void newLine() {  
  2.     try {  
  3.         synchronized (lock) {  
  4.         ensureOpen();  
  5.         out.write(lineSeparator);  
  6.         if (autoFlush)  
  7.             out.flush();  
  8.         }  
  9.     }  
  10.     catch (InterruptedIOException x) {  
  11.         Thread.currentThread().interrupt();  
  12.     }  
  13.     catch (IOException x) {  
  14.         trouble = true;  
  15.     }  
  16.     }  
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定义:
[java] view plain copy print ?
  1. lineSeparator = (String) java.security.AccessController.doPrivileged(  
  2.                new sun.security.action.GetPropertyAction("line.separator"));  
lineSeparator = (String) java.security.AccessController.doPrivileged(
               new sun.security.action.GetPropertyAction("line.separator"));
服务端的readLine()方法,遇到回车符就读一次数据(一行一行的读)。所以服务端可以收到信息。

3. 研究一下readLine

再次修改Client.java代码:

[java] view plain copy print ?
  1. package mark.zhang;  
  2.   
  3. import java.io.DataOutputStream;  
  4. import java.io.OutputStream;  
  5. import java.net.Socket;  
  6.   
  7. public class Client {  
  8.     public static void main(String[] args) throws Exception {  
  9.         Socket client = new Socket("127.0.0.1"3000);  
  10.         OutputStream os = client.getOutputStream();  
  11.         DataOutputStream dos = new DataOutputStream(os);  
  12.         dos.writeBytes("Hello,Server1");  
  13.         dos.writeBytes("\n");  
  14.         dos.writeBytes("Hello,Server2");  
  15.         //dos.close();   
  16.     }  
  17. }  
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();
	}
}
服务端接收信息:

[java] view plain copy print ?
  1. server receive info: Hello,Server1  
server receive info: Hello,Server1
说明,没有接收到Hello,Server2。这就说明,readLine遇到回车就算读完信息。

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

[java] view plain copy print ?
  1. package csdn.zhwx;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.BufferedWriter;  
  5. import java.io.File;  
  6. import java.io.FileInputStream;  
  7. import java.io.FileOutputStream;  
  8. import java.io.IOException;  
  9. import java.io.InputStreamReader;  
  10. import java.io.OutputStreamWriter;  
  11. import java.nio.charset.Charset;  
  12.   
  13. public class BufferedReaderTest {  
  14.   
  15.     public static void getFile(String readFilePath, String readFileName,  
  16.             String writeFilePath, String writeFileName) {  
  17.         File reaFile = null;  
  18.         FileInputStream fis = null;  
  19.         BufferedReader bReader = null;  
  20.   
  21.         File writeFile = null;  
  22.         FileOutputStream fos = null;  
  23.         BufferedWriter bWriter = null;  
  24.   
  25.         try {  
  26.             if (!(readFileName == null || readFileName.length() <= 0)) {  
  27.                 reaFile = new File(readFilePath + readFileName);  
  28.                 fis = new FileInputStream(reaFile);  
  29.                 // bReader = new BufferedReader(new InputStreamReader(fis,"GBK"));//指定GBK编码,一般用在汉化windows上。   
  30.                 // bReader = new BufferedReader(new InputStreamReader(fis));//默认编码,和系统编码一致。linux为UTF-8   
  31.                 bReader = new BufferedReader(  
  32.                         new InputStreamReader(fis, "UTF-8"));// 指定UTF-8编码   
  33.   
  34.                 writeFile = new File(writeFilePath, writeFileName);  
  35.                 fos = new FileOutputStream(writeFile);  
  36.                 // bWriter = new BufferedWriter(new OutputStreamWriter(fos));//默认编码,和系统编码一致。linux为UTF-8   
  37.                 bWriter = new BufferedWriter(new OutputStreamWriter(fos,  
  38.                         "UTF-8"));// 指定UTF-8编码   
  39.   
  40.                 String str = null;  
  41.                 while ((str = bReader.readLine()) != null) {// 该方法不会将读取到的换行\n写到文件中   
  42.                     // System.out.println(str);   
  43.                     // 要自己手动加\n   
  44.                     bWriter.write(str + "\n");  
  45.                       
  46.                     /*bWriter.write(str); 
  47.                     bWriter.newLine();*/  
  48.                       
  49.                     // 不刷新的话,文件不会有内容   
  50.                     bWriter.flush();  
  51.                 }  
  52.             }  
  53.   
  54.         } catch (Exception e) {  
  55.             e.printStackTrace();  
  56.             try {  
  57.                 fis.close();  
  58.                 bReader.close();  
  59.                 fos.close();  
  60.                 bWriter.close();  
  61.             } catch (IOException e1) {  
  62.                 e1.printStackTrace();  
  63.             }  
  64.         } finally {  
  65.             try {  
  66.                 fis.close();  
  67.                 bReader.close();  
  68.                 fos.close();  
  69.                 bWriter.close();  
  70.             } catch (IOException e1) {  
  71.                 e1.printStackTrace();  
  72.             }  
  73.         }  
  74.     }  
  75.   
  76.     public static void main(String[] args) {  
  77.         getFile("/home/zhihui/Downloads/""hello.txt",  
  78.                 "/home/zhihui/Downloads/""copyFormHello.txt");  
  79.           
  80.         //linux下测试   
  81.         /*当前JRE:1.6.0_23 
  82.         当前JVM的默认字符集:UTF-8*/  
  83.         System.out.println("当前JRE:" + System.getProperty("java.version"));  
  84.         System.out.println("当前JVM的默认字符集:" + Charset.defaultCharset());   
  85.     }  

你可能感兴趣的:(java学习)