@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】