源程序:
Client:
class TcpClient4 { public static void main(String[] args) { Socket s=null;//要在块外定义,不然catch中无法找到!------->并初始化,否则finally中判断时提示你可能尚未初始化!! try { s=new Socket("127.0.0.1",10013);//单独try,连不上直接终止运行,没有继续运行下面程序的必要! try { //经测试,按记事本默认编码保存,这里只有用UTF-8解码复制结果是乱码!按utf-8保存,复制结果仍然不一致(字节数都不一致!),但竟然不乱码!(开头多了个?) //这里的测试:其中sscc.txt是utf-8文件,文本:“你妈逼你结婚了吗?”30个字节。故意用gb2312解码,结果当然乱码:字节、内容都不一致,但这里按utf-8正常解码,下面一切默认,则不乱码,前边多了个?,并且字节数不一致,显示是21个字节,说明是GBK或GB2312编码! BufferedReader bufr=new BufferedReader(new InputStreamReader(new FileInputStream("c:\\sscc.txt"),"utf8"));//底层都是读字节,这里可以指定码表,并且是用转换流转成字符流读取方式 //BufferedReader bufr=new BufferedReader(new FileReader("c:\\x.txt")); //这是默认编码GBK PrintWriter pw=new PrintWriter(s.getOutputStream(),true);//第二个参数true:自动刷新 String line=null; while((line=bufr.readLine())!=null){ pw.println(line);//自动加回车换行,那边readLine可以判断并成功读取一行 } } catch (Exception ex) { throw new RuntimeException(ex); } } catch (Exception e) { throw new RuntimeException(e); } finally{ try { //s是引用 if(s!=null) s.close(); } catch (Exception exc) { throw new RuntimeException(exc); } } } }
class TcpServer4 { public static void main(String[] args) { ServerSocket ss=null;//要在块外定义,不然catch找不到! Socket s=null; try { ss=new ServerSocket(10013); s=ss.accept(); try { BufferedReader bufr=new BufferedReader(new InputStreamReader(s.getInputStream())); PrintWriter pw=new PrintWriter(new FileWriter("c:\\x2.txt"),true); String line=null; while((line=bufr.readLine())!=null){ pw.println(line); } } catch (Exception ex) { throw new RuntimeException(ex); } } catch (Exception e) { throw new RuntimeException(e); } finally{ try { if(s!=null) s.close(); if(ss!=null) ss.close(); } catch (Exception exc) { throw new RuntimeException(exc); } } } }关于异常处理:
1.Socket相关要单独try处理,连接出现问题就没有继续运行下面代码的必要;
2.Socket(引用)要在try块外定义,不然catch块找不到!
3.Socket需要在定义时初始化,不然编译提示:finally中的if判断可能会出现Socket尚未初始化的情况!
按不同码表复制的结果:
经测试验证:按照记事本默认ANSI编码保存,程序中一切按照默认码表处理,正常复制,结果的内容和字节数均与源文件一致,没有问题:ANSI对应中文编码为GBK,而FileReader,FileWriter等的默认码表也是GBK,不乱码
按照UTF-8保存文本(可以从字节数看出来,UTF-8中文一个汉字3个字节),客户端读取时按照UTF-8正常解码(解码出汉字字符串),其他地方一切按默认编码,结果并不乱码,只是文本开头莫名多了一个?
结论:有些原因不明,只能看实际结果,不要主观臆测,想当然!实际编程中只要严格按照同一种码表编码和解码就不会出现问题!抓住这一点,其他一切不要深究,不要冒险尝试!!!
上传成功后反馈信息的程序改进:
注意在客户端的while循环结束后(它是可以结束的,读文件),如果没有额外再输出一个结束标记,那么由于其下面还有一个阻塞式的readLine等待反馈信息,而服务端那边的while得不到结束标记,则两端都会陷入阻塞。
Client:
class TcpClient4 { public static void main(String[] args) { Socket s=null;//要在块外定义,不然catch中无法找到!------->并初始化,否则finally中判断时提示你可能尚未初始化!! try { s=new Socket("127.0.0.1",10013);//单独try,连不上直接终止运行,没有继续运行下面程序的必要! try { BufferedReader bufr=new BufferedReader(new InputStreamReader(new FileInputStream("c:\\xxcc.txt"),"gbk")); //BufferedReader bufr=new BufferedReader(new FileReader("c:\\x.txt")); PrintWriter pw=new PrintWriter(s.getOutputStream(),true);//第二个参数true:自动刷新 String line=null; while((line=bufr.readLine())!=null){ pw.println(line);//自动加回车换行,那边readLine可以判断并成功读取一行 } //可以定义结束标记那边判断(读取,传过去,那边得到后判断,用DataOutputStream),比如空行(Tomcat的做法,分割请求和响应的头和主体)和时间戳(长整型,DataInputStream的readLong方法),这里调用Socket的方法关闭输出流 s.shutdownOutput();//关闭客户端的输出流,相当于给流中加入一个结束标记-1,让那边的循环停下来 //读取一个上传成功的反馈 BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream())); String str=bufIn.readLine();//一样需要换行符 System.out.println(str); bufr.close(); s.close();//和Socket相关的流随Socket关闭而自然关闭 } catch (Exception ex) { throw new RuntimeException(ex); } } catch (Exception e) { throw new RuntimeException(e); } finally{ try { //s是引用 if(s!=null) s.close(); } catch (Exception exc) { throw new RuntimeException(exc); } } } }
class TcpServer4 { public static void main(String[] args) { ServerSocket ss=null;//要在块外定义,不然catch找不到! Socket s=null; try { ss=new ServerSocket(10013); s=ss.accept(); try { BufferedReader bufr=new BufferedReader(new InputStreamReader(s.getInputStream())); PrintWriter pw=new PrintWriter(new FileWriter("c:\\x2.txt"),true); String line=null; while((line=bufr.readLine())!=null){ pw.println(line); } //那边关闭Socket输出流以结束这边的循环,那么这里仍然可以调用,难道是重新打开? PrintWriter pout=new PrintWriter(s.getOutputStream(),true); pout.println("Upload Succeed.");//必须有回车换行,那边才能readLine pw.close();//和Socket有关的流随Socket关闭而自然关闭! } catch (Exception ex) { throw new RuntimeException(ex); } } catch (Exception e) { throw new RuntimeException(e); } finally{ try { if(s!=null) s.close(); if(ss!=null) ss.close(); } catch (Exception exc) { throw new RuntimeException(exc); } } } }
D:\java\practice3>java TcpClient4
Upload Succeed.
D:\java\practice3>