Java 输入输出(IO)与网络编程

@version 1.0 2011.01.08


IO/输入输出

 

→File类

唯一代表磁盘文件本身信息的类(不是文件中的内容

文件操作方法

→RandomAccessFile类

提供了众多的文件访问方法

支持“随机访问”方式(如实现断点下载、多线程下载)

读写等长记录格式文件

只读/读写两种构造方法

→eg

→节点流

→流  字节序列的抽象概念(数据传输时的形态)

→节点流类/过滤流类(处理流类)

 

→InputStream类

→OutputStream类

 void flush()  IO缓冲区 

 

→FileInputStream与FileOutputStream类

→Reader与Writer类  是所有字符流类的抽象基类 用于读写文本数据

 二进制文件、文本文件(专用于存储文本字符,没有包含文本之外的数据) 

 →FileWriter/FileReader类

 

→PipedInputStream与PipedOutPutStream类  用于应用程序中的创建管道通信

 eg.线程通信

 import java.io.*;

 public class Sender extends Thread{

private PipedOutputStream out = new PipedOutputStream();

private PipedOutputStream getOutputStream(){

return out;

}

public void run(){

String strInfo = new String("Hello,Sender");

try{

out.write(strInfo.getBytes());

out.close();

}catch(Exception ex){}

}

 }

 

 import java.io.*;

 public class Receiver extends Thread{

private PipedInputStream in = new PipedInputStream();

private PipedInputStream getInputStream(){

return in;

}

public void run(){

byte[] buf = new byte[1024];

try{

int len = in.read(buf);

System.out.println(

                                          "the following message comes from sender :"

                                           +new String(buf,0,len));

in.close();

}catch(Exception ex){}

}

 }

 

 public class PipedStreamTest{

public static void main(String [] args) throws Exception{

Sender t1 = new Sender();

Receiver t2 = new Receiver();

PipedOutputStream out = t1.getOutputStream();

PipedInputStream in = t2.getInputStream();

out.connect(in); //in.connect(out);

t1.start();

t2.start();

}

 }

 

→PipedWriter和PipedReader类

使用管道流类,可以实现各个程序模块之间的松耦合通信

数据压缩、加密等

 

→ByteArrayInputStream与ByteArrayOutputStream类

用于以IO流的方式完成对字节数组内容的读写,来支持类似内存虚拟文件或者内存印象文件的功能

         ByteArrayInputStream(byte[] buf)

ByteArrayInputStream(byte[] buf,int offset,int.length)

ByteArrayOutputStream()

ByteArrayOutputStream(int)

可用于内存创建临时数据,而不用访问硬盘操作,极大提高效率

→重视IO接口程序的复用性

→字符编码(★)

→计算机软件一切都是用数字来表示的  ASCII码(0-127)

 中文字符的每个字节的最高位bit都是1,GB2312、GBK(包括繁体)

 台湾地区中文字符集 BIG5(大五码)

 Unicode编码  

   全世界所有符号统一编码(两个字节/2^16=65536个)

其中0xD800-0xDFFF区间为代理区,UTF-16即是据此扩充

→转码

 UTB-8编码 (通常都要EF BB BF作为文件开头的三个字节数据进行标记)

\u0001和\u0007f之间的字符,占用两个字节,UTF-8编码为:

(byte)c

0001-007E 0xxxxxxx (7bis)

\u0000或范围在\u0080和\u07ff之间的字符,占用两个字节,

                 UTF-8编码为:

(byte)(0xc0|(0x1f&(c>>6))),(byte)(0x80|(0x3f&c))

0000和0080-07FF  110xxxxx 10xxxxxx (11bits)

\u0800和\uffff之间的字符,占用三个字节,UTF-8编码为:

(byte)(0xe0|(0x0f&(c>>12))),

                        (byte)(0x80|(0x3f&(c>>6))),

                        (byte)(0x80|(0x3f&c))

0800-FFFF 1110xxxx 10xxxxxx 10xxxxxx (16bits)

优点:

不出现内容为0x00字节

便于应用程序检测数据在传输过程中是否发生了错误

直接处理使用ASCII码的英文

缺点:

某些字符需要3字节编码

→字符编码编程应用

public static void main(String [] args) throws Exception{

 

System.setProperty("file.encoding","iso8859-1");

System.getProperties().list(System.out);

 

String strChina = "中国";

//Unicode

for(int i=0;i<strChina.length();i++){

System.out.println(Integer.toHexString((int)strChina.charAt(i)));

}

//GB2312

byte[] buf = strChina.getBytes("gb2312");

for(int i=0;i<buf.length;i++){

System.out.println(Integer.toHexString(buf[i]));

}

 

for(int i=0;i<buf.length;i++){

System.out.write(buf[i]);

}

System.out.println(); //刷新缓冲区,显示内容

//System.out.write(buf,0,4);

}

...

→过滤流和包装类

包装类的概念与作用

→BufferedInputStream与BufferedOutputStream类

缓冲流为IO流增加了内存缓冲区,增加了缓冲区有两个基本目的

 →允许java程序一次不只操作一个字节吗,这样提高了程序的性能。

 →由于有了缓冲区,使得在留上执行skip、mark和reset方法都成为可能。

BufferedInputStream和BufferedOutputStream是Java提供的两个缓冲区包装类,

不管底层系统是否使用了缓冲区,这两个类在自己的实例对象中创建缓冲区。

 BufferedInputStream(InputStream in)

 BufferedInputStream(InputStream in,int size)

 BufferedOutputStream(OutputStream out)

 BufferedOutputStream(OutputStream out,int size)

→BufferedReader和BufferedWriter类

→DataInputStream与DataOutputStream类

writeBytes(String s)\writeChars(String s)\writeUTF(String s)

readUTF()  【ps:02_12 2808】

→eg

import java.io.*;

public class DataStreamTest{

public static void main(String [] args) throws Exception{

FileOutputStream fos = new FileOutputStream("count.txt");

BufferedOutputStream bos =

                                                       new BufferedOutputStream(fos);

DataOutputStream dos = new DataOutputStream(bos);

dos.writeUTF("ab中国");

dos.writeBytes("ab中国");

dos.writeChars("ab中国");

dos.close();

FileInputStream fis = new FileInputStream("count.txt");

BufferedInputStream bis = new BufferedInputStream(fis);

DataInputStream dis = new DataInputStream(bis);

System.out.println(dis.readUTF());

byte[] buf = new byte[1024];

int len = dis.read(buf);

System.out.println(new String(buf,0,len));

}

}

→PrintStream类 print()/println() 可以将基本数据类型的数据格式化成字符串输出

→ObjectOutputStream与ObjectInputStream类

所读取对象必须实现了Serializable接口。对象中transient和static类型的成员变量不会被读取和写入

→eg 对象传输【02_13】

→字节流与字符流的转换

InputStreamReader、OutputStreamWriter尽量使用 BufferedInputStream、BufferedOutputStream包装使用

→Java程序与其他进程的数据通信

→字符输入/输出流类关系

→Decoratot设计模式(包装)【02_15 3311】

→F&Q【02_15 8345】

 

 

网络编程

1,网络协议与TCP/IP

→IP+Port、127.0.0.1/localhost、IPv6

→UDP与TCP

TCP,传输控制协议,是面向连接的通信协议、提供更可靠无差错(应答)数据通信。

UDP,用户数据报协议,是无连接通信协议、不保证可靠(无应答)。

→协议类型+源IP+目标IP+源端口+目标端口+帧序号+帧数据

→Socket 数据发送过程

→java.net包

DatagramSocket类用于UDP通信

ServerSocket类用于TCP通信的服务端

Socket类用于TCP通信的服务器和客户端

2,UDP网络程序

→DatagramSocket类

public DatagramSocket()

public DatagramSocket(int port)

public DatagramSocket(int port,InetAddress Iaddr)

close()、send(DatagramPacket p)、receive(DatagramPacket p)

→DatagramPacket类

public DatagramPacket(byte[] buf,int length) //receive

public DatagramPacket(byte[] buf,int length,

                                         InetAddress address,int port)//send

getInetAddress、getPort、getData、getLength

→InetAddress类——表示计算机IP地址

getByName()

getHostAddress()

→eg

import java.net.*;

public class UpdSend{

public static void main(String [] args) throws Exception{

DatagramSocket ds = new DatagramSocket();

String strInfo = "hello,world";

//发送

DatagramPacket dp =

                              new DatagramPacket(strInfo.getBytes(),strInfo.length(),

InetAddress.getByName("192.168.2.121"),3000);

ds.send(dp);

ds.close();

}

}

import java.net.*;

public class UpdRecv{

public static void main(String [] args) throws IOException{

DatagramSocket ds = new DatagramSocket(3000);

byte[] buf = new byte[1024];

DatagramPacket dp = new DatagramPacket(buf,1024);

String strInfo = "hello,world";

//接收

ds.receive(dp);

System.out.println(

                                new String(dp.getData(),0,dp.getLength())

+ "from" +dp.getAddress().getHostAddress()

                                + ":" + dp.getPort()); //192.168.2.121

ds.close();

}

}

→UDP网络聊天程序

 编写图形用户界面、编写网络消息发送功能、编写网络消息接收功能

→私有IP通过网关代理上网的原理【04_04】

 

3,TCP网络程序

→TCP网络程序的工作原理

→ServerSocket类

 public ServerSocket()

 public ServerSocket(int port)

 public ServerSocket(int port,int backlog)

 public ServerSocket(int port,int backlog,InetAddress bindAddr)

 close()、accept()

→Socket类

 public Socket()

 public Socket(String host,int port) //

 public Socket(InetAddress address,int port) //

 public Socket(String host,int port,InetAddress address,int port)

 public Socket(InetAddress host,int port,InetAddress address,int port)

 getInputStream/getOutputStream

→TCP服务器必须先启动运行,TCP客户程序才能连接上TCP服务器

→eg

import java.net.*;

import java.io.*;

public class TcpServer{ //服务器端Socket

public static void main(String [] args) throws Exception{

ServerSocket ss = new ServerSocket(8001);

Socket s = ss.accept(); //对象与服务器Socket建立专线连接(一次只连接一个)

//若未被请求,以下则阻塞

InputStream ips = s.getInputStream();

OutputStream ops = s.getOutputStream();

ops.write("welcome to java".getBytes());

byte[] buf = new byte[1024];

int len = ips.read(buf);

System.out.println(new String(buf,0,len));

//调用完成即关闭

ips.close();

ops.close();

s.close();

ss.close();

}

}

//telnet 可以作为客户端Socket 进行测试

→完善的TCP服务器程序结构模型【04_06】

import java.net.*;

import java.io.*;

public class ReverseServer{ //一对多

public static void main(String [] args) throws Exception{

ServerSocket ss = null;

if(args.length<1){

ss = new ServerSocket(8001);

}else{

ss = new ServerSocket(Integer.parseInt(args[0]));

}

boolean bRunning = true;

while(bRunning){

Socket s = ss.accept();

new Thread(new Servicer(s)).start();

}

ss.close();

}

}

    

import java.net.*;

import java.io.*;

public class Servicer implements Runnable{

private Socket s = null;

public Servicer(Socket s){

this.s = s;

}

public void run(){

InputStream ips = null;

try {

ips = s.getInputStream();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

OutputStream ops = null;

try {

ops = s.getOutputStream();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

BufferedReader br = new BufferedReader(

                                                            new InputStreamReader(ips));

                        //设置自动刷新缓冲区

PrintWriter pw = new PrintWriter(ops,true);


while(true){

String strLine = null;

try {

strLine = br.readLine();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

if(strLine.equalsIgnoreCase("quit")){

break;

}

System.out.println(strLine + strLine.length());

String strEcho =

                                 (new StringBuffer(strLine).reverse()).toString();

pw.println(strLine+"→→→"+strEcho);

//pw.print(strLine+"→→→"+strEcho+"\r\n");

//pw.print(strLine+"→→→"+strEcho+System.getProperty(line.separator));

//注意:使用print方法将"接收不到服务器端的相应信息",

//因为PrintWrite类的print方法即使遇到“\n”、

                                //设置刷新标志也不会刷新,必须调用println。

}

}

}

 

→检测和解决端口冲突问题

netstat -na

配置参数指定TCP服务器程序所使用的端口号/保存配置到文件以便下次运行自动读取端口号

→TCP网络连接上传递对象 ObjectInputStream/ObjectOutputStream 【04_07】

→应用程序协议、网络通信协议的关系

→java.net包中URL、URLDecoder、URLEncoder、URLConnection、HttpURLConnection类

Uniform Resource Locator、HTTP 1.1 

→URL

public URL(String spec)

public URL(String protocol,String host,int port,String file)

public URL(String protocol,String host,int port,String file,URLStreamHandler handler)

public URL(URL context,String spec)

getProtocol、getHost、getPort、getFile、openConnection

→工厂模式

→URLConnection、HttpURLConnection类

setRequestProperty\getHeaderFields\getInputStream\getOutputStream\

getHeaderField\getContentLength\getContentEncoding\getContentType

→eg

import java.net.*;

import java.io.*;

import java.util.*;

public class GetGoogle{

public static void main(String [] args) throws Exception{

System.out.println("获取日文页面");

getContentByLanguage("ja");

System.out.println("\n");

System.out.println("获取中文页面");

                         //实际运行时zh-cn超时-Google已结束中文(zh-cn)服务

getContentByLanguage("zh-cn");

}

public static void getContentByLanguage(String country)

                                                                            throws Exception{

URL urlGoogle = new URL("http://www.google.com");

HttpURLConnection googleConnection =                                                                                                          (HttpURLConnection)urlGoogle.openConnection();

googleConnection.setRequestProperty(

                                           "Accept-Language",country);

Map requests = googleConnection.getRequestProperties();

Set reqFields = requests.keySet();

Iterator itrReq = reqFields.iterator();

while(itrReq.hasNext()){

String field = (String)itrReq.next();

System.out.println(field + ":"

                                    + googleConnection.getRequestProperty(field));

}

googleConnection.connect();

Map responses = googleConnection.getHeaderFields();

Set resFields = responses.keySet();

Iterator itrRes = resFields.iterator();

while(itrRes.hasNext()){

String field = (String)itrRes.next();

System.out.println(field + ":"  

                                  + googleConnection.getHeaderField(field));

}

InputStream is = googleConnection.getInputStream();

BufferedReader br = new BufferedReader(

                                                            new InputStreamReader(is));

String strLine = null;

while((strLine = br.readLine()) != null){

System.out.println(strLine);

}

br.close();//将自动关闭is

googleConnection.disconnect();

}

}

→F&Q【04_10 10000】

   

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值