Java基础: 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()); 
	}
}


©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页