一、Properties属性集合类
- Properties 继承自Hashtable<K,V>---->实现Map<K,V>接口
表示了一个持久的属性集
Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
构造方法
public Properties()
举例:
public class PropertiesDemo {
public static void main(String[] args) {
//Properties没有泛型,属于Map的一个子实现类
//使用Map接口的功能操作
//创建一个属性列表
Properties properties = new Properties() ;
//put
properties.put("张三",30) ;
properties.put("李四",40) ;
properties.put("王五",50) ;
properties.put("赵六",25) ;
//遍历:Map集合遍历方式: 推荐:keySet()
Set<Object> keySet = properties.keySet();
for(Object obj :keySet){
//通过键获取值
Object value = properties.get(obj);
System.out.println(obj+"---"+value);
}
}
}
- 关于属性集合类的特有功能:
添加方法
public Object setProperty(String key,String value)
遍历:
public Set stringPropertyNames()
通过键获取值
public String getProperty(String key)
举例:
public class PropertiesDemo2 {
public static void main(String[] args) {
//创建一个属性集合类
Properties prop = new Properties() ;
//添加
prop.setProperty("1","文章") ;
prop.setProperty("2","高圆圆") ;
prop.setProperty("3","马伊琍") ;
prop.setProperty("4","赵又廷") ;
prop.setProperty("4","王宝强") ;
//遍历
Set<String> keySet = prop.stringPropertyNames();
for(String key:keySet){
//通过键获取值
String value = prop.getProperty(key);
System.out.println(key+"---"+value);
}
}
}
-
关于属性集合类的应用;
1)因为键和值都是String,所以可能将键和值的保存在文本文件或者配置文件中 :加载过程
public void load(Reader reader)throws IOException
public void load(InputStream in)throws IOException2)将属性集合类中的内容写出到某个文件中:保存过程
public void store(OutputStream out,String comments) throws IOException
参数1:当前字节输出流
参数2:给当前属性列表中写入完毕之后,注释的内容
public void store(Writer writer,String comments) throws IOException
将当前项目下的name.txt内容加载到属性集合类中
举例:
public class PropertiesDemo3 {
public static void main(String[] args) throws IOException {
// myLoad() ;
// mySotre() ;
}
//保存:将当前属性集合类中的内容,输出在某个文件中
private static void mySotre() throws IOException {
//创建一个属性列表
Properties prop = new Properties() ;
prop.setProperty("马伊琍","35") ;
prop.setProperty("文章","26") ;
prop.setProperty("姚笛","22") ;
prop.setProperty("王宝强","35") ;
prop.setProperty("马蓉","30") ;
//保存
prop.store(new FileWriter("userList.txt"),"name's list");
}
//加载:将name.txt内容加载到属性集合类中
private static void myLoad() throws IOException {
//创建一个属性集合类
Properties prop = new Properties() ;
System.out.println(prop);
//加载
//字符流
Reader r = new FileReader("name.txt") ;
prop.load(r);
//遍历
Set<String> keySet = prop.stringPropertyNames();
for (String key: keySet) {
String value = prop.getProperty(key) ;
System.out.println(key+"---"+value);
}
//System.out.println(prop);
}
}
- 如果我们的配置文件后缀名xx.properties
操作步骤:
src目录下---->类路径
将properties配置文件放置在src目录下
举例:
public class PropertiesDemo4 {
public static void main(String[] args) throws IOException {
//读取user.properties配置文件: src目录下
//1)需要获取当前类的字节码文件对象( PropertiesDemo4类中要使用配置文件)
/* Class clazz = PropertiesDemo4.class ;
//2)获取当前类的类加载器
//Class类的方法:getClassLoader()--->ClassLoader
ClassLoader classLoader = clazz.getClassLoader();
//public InputStream getResourceAsStream(String name) :传入当前配置文件-->获取当前配置资源的输入流对象(推荐)
//public URL getResource(String name):传入配置文件名称-->获取当前配置文件的url地址
//通过类加载将配置文件的内容读取到了流中
InputStream inputStream = classLoader.getResourceAsStream("user.properties");
*/
//一步走
InputStream inputStream = PropertiesDemo4.class.getClassLoader().getResourceAsStream("user.properties");
//创建属性集合类中
Properties prop = new Properties() ;
prop.load(inputStream);
//System.out.println(prop);
Set<String> keySet = prop.stringPropertyNames();
for(String key:keySet){
System.out.println(key+"---"+prop.getProperty(key));
}
}
}
二、网络编程Socket
- UDP协议发送端的实现步骤: (不需要建立连接通道,以"数据报包"的方式发送数据)
DatagramSocket表示用来发送和接收"数据报包"的套接字
1)创建发送端的Socket: DatagramSocket
public DatagramSocket() throws SocketException{}
2) 创建 "数据报包"对象
public DatagramPacket(byte[] buf,int length,InetAddress address,int port)
3)发送数据报包
public void send(DatagramPacket p) throws IOException
4)释放资源
close()关闭socket对象
举例:
public class SendDemo {
public static void main(String[] args) throws IOException {
//创建发送端的Socket: DatagramSocket
DatagramSocket ds = new DatagramSocket() ;
//创建 "数据报包"对象
// public DatagramPacket(byte[] buf,int length,InetAddress address,int port)
//参数1:包的数据--字节数组
//参数2:包的长度
//参数3:ip地址
//参数4:端口号
String messageStr = "hello,UDP,我来了" ;
byte[] bytes = messageStr.getBytes();
int length = bytes.length ;
InetAddress inetAddress = InetAddress.getByName("10" +
".12.152.129");
int port = 10086 ;
DatagramPacket dp = new DatagramPacket(bytes, length, inetAddress, port);
//3)发送数据
ds.send(dp);
System.out.println("当前数据已经发送...");
//4)释放资源
ds.close();
}
}
- UDP协议接收端实现
1)创建接收端的Socket
public DatagramSocket(int port) throws SocketException:绑定端口号
2)数据一个数据报包对象:DatagramPacket
接收容器
public DatagramPacket(byte[] buf, int length) :获取的是缓冲区的数据(不是真实数据)
一般情况:byte[] bytes = new byte[1024] ; 自定义字节缓冲区
3)接收
public void receive(DatagramPacket p):阻塞式方法:在接收数据之前,一直处于阻塞状态,直到
当前接收端监听客户端口号了
4) 获取缓冲区的传递的真实数据
public byte[] getData():获取真实的字节数组
public int getLength():获取实际长度
将获取的字节数据---->String(byte[] bytes,int offset,int length)
获取哪个发送端传递的数据:ip 文本形式:
public InetAddress getAddress()
IntegerAddss—>public String getHostAddress()
5)使用完毕,关闭接收端
接收端不能运行多次,否则出现异常了,端口号被占用!
举例:
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
System.out.println("接收端等待发送数据...");
//创建接收端的Socket
DatagramSocket ds = new DatagramSocket(10086) ;
// 接收容器:数据报包
//定义一个字节缓冲区
byte[] bytes = new byte[1024] ;
int length = bytes.length ;
DatagramPacket dp = new DatagramPacket(bytes,length) ;
//接收
ds.receive(dp);
System.out.println("已经获取发送数据准备解析...");
//解析真实数据
/*
* public byte[] getData():获取真实的字节数组
* public int getLength():获取实际长度*/
byte[] bytes2 = dp.getData();
int len = dp.getLength();
//获取ip地址
String ip = dp.getAddress().getHostAddress();
String receiveMsgStr = new String(bytes2,0,len) ;
System.out.println("data from " + ip +"and content is: "+receiveMsgStr);
//关闭资源
ds.close();
}
}
- 想通过程序的方式:获取本地计算机的这个ip字符串形式以及主机名称?
java.net.InetAddress:互联协议的ip地址!
一个具体类中,没有字段,没有构造方法,
那么这个类只有成员方法,成员方法里面存在静态功能,返回值是它本身!
单例模式:
Runtime
private static Runtime currentRuntime = new Runtime() ;
private Runtime(){}
public static Runtime getRuntime(){
return currentRuntime
}
public static InetAddress getByName(String host):给定主机名称,可以获取互联网ip地址对象!
参数:可以传递主机名称/ip地址名称
public String getHostAddress():获取ip地址字符串形式
public String getHostName():获取主机名称
举例:
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
// InetAddress inetAddress = InetAddress.getByName("LAPTOP-BHL76J0S");
InetAddress inetAddress = InetAddress.getByName("10.12.152.131");
//获取ip地址字符串文本
String ip = inetAddress.getHostAddress();
System.out.println(ip);//10.12.152.129
//获取主机名称
String hostName = inetAddress.getHostName();
System.out.println(hostName);//LAPTOP-BHL76J0S
//LAPTOP-4IJ0OFL4
}
}
/* udp发送端不断的键盘录入数据,当前录入是 "over/886",结束,接收端不断的接收数据!
* 键盘录入数据采用的是:BufferedReader的readLine()功能来操作
*/
public class SendDemo {
public static void main(String[] args) {
//创建一个字符缓冲输入流
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;
//创建一个送端的Socket对象
DatagramSocket ds = null ;
try {
ds = new DatagramSocket() ;
String line = null ;
while((line=br.readLine())!=null){
//自定义结束条件
if("886".equals(line)){
break ;
}
//创建数据报包
DatagramPacket dp = new DatagramPacket(
line.getBytes(),
line.getBytes().length,
InetAddress.getByName("10.12.152.129"),
10010);
ds.send(dp);
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(ds!=null){
ds.close();
}
}
}
}
/* Udp接收端不断的接收数据,接收端一般不关闭(模拟真实场景)
*/
public class ReceiveDemo {
public static void main(String[] args) throws Exception{
try {
System.out.println("等待接收");
DatagramSocket ds =new DatagramSocket(10010) ;
while(true){
//创建接收端的Socket对象
//创建数据报包:接收容器
DatagramPacket dp = new DatagramPacket(new byte[1024],new byte[1024].length) ;
//接收
ds.receive(dp);
//准备解析真实数据
String str = new String(dp.getData(),0,dp.getLength()) ;
String ip = dp.getAddress().getHostAddress() ;
System.out.println("data from: "+ip+" and content is: "+str );
// ds.close(); //接收端不需要关闭
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 如何使用udp方式在一个窗口下进行聊天
需要两条线程:发送端发消息的线程
接收端接收消息的线程
创建线程的方式:(除过线程池)
1)继承自Thread类
2)实现Runnable接口 —> 能够多个线程占用的 内存空间(共享共用)
代理----静态代理模式
举例:
发送端的资源类
public class SendThread implements Runnable {
private DatagramSocket ds ;
public SendThread(DatagramSocket ds){
this.ds = ds ;
}
@Override
public void run() {
try {
//不断键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;
String line = null ;
while((line=br.readLine())!=null){
if("over".equals(line)){
break ;
}
//创建数据报包
DatagramPacket dp = new DatagramPacket(line.getBytes(),
line.getBytes().length,
InetAddress.getByName("10.12.152.129"),
12306);
//发送数据
ds.send(dp) ;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(ds!=null){
ds.close();
}
}
}
}
/* 接收端的资源类对象
*/
public class ReceiveThread implements Runnable {
private DatagramSocket ds ;
public ReceiveThread(DatagramSocket ds){
this.ds = ds ;
}
@Override
public void run() {
try {
while(true){
//创建接收端的Socket对象
//创建数据报包:接收容器
DatagramPacket dp = new DatagramPacket(new byte[1024],new byte[1024].length) ;
//接收
ds.receive(dp);
//准备解析真实数据
String str = new String(dp.getData(),0,dp.getLength()) ;
String ip = dp.getAddress().getHostAddress() ;
System.out.println("data from: "+ip+" and content is: "+str );
}
} catch (Exception e) {
e.printStackTrace();
}
//接收不需要关闭
}
}
public class ChatRoom {
public static void main(String[] args) throws Exception{
//创建两端的Socket对象
//发送端:
DatagramSocket ds = new DatagramSocket() ;
//接收端
DatagramSocket ds2 = new DatagramSocket(12306) ;
//创建资源类对象
//发送端的资源类以及接收端端的子类
SendThread st = new SendThread(ds) ;
ReceiveThread rt = new ReceiveThread(ds2) ;
//创建线程对象
Thread t1 = new Thread(st) ;
Thread t2 = new Thread(rt) ;
t1.start();
t2.start();
}
}
- TCP/IP协议:客户端发送的过程
1)创建客户端的Socket
public Socket(String host,int port) throws UnknownHostException,IOException
2)public OutputStream getOutputStream()throws IOException
获取当前客户端对象所在的通道内的输出流对象
3)使用当前通道内的字节输出流 写数据过去
4)释放资源
举例:
/*服务器端
* 1)创建服务器端的Socket :此类实现服务器套接字
* public ServerSocket(int port)
* throws IOException
* 2)监听客户端连接
* public Socket accept()
* throws IOException
* 3) 通过监听到的客户端对象 获取通道的输入流
* public InputStream getInputStream()
* 4)关闭资源
* 服务器端关闭
*/
public class ServerSocketDemo {
public static void main(String[] args) throws IOException {
//创建服务器端的Socket
ServerSocket ss = new ServerSocket(6666) ; //一旦能成功,就立即建立通道
System.out.println("服务器正在等待连接...");
//2)监听并获取客户端的socket对象
Socket socket = ss.accept(); //阻塞式方法 如果没有监听到,一直等
//3)获取通道内的输入流
InputStream inputStream = socket.getInputStream();
//一次读取一个字节数组
byte[] bytes = new byte[1024] ;
int len = inputStream.read(bytes);
String str = new String(bytes,0,len) ;
//通过监听到客户端的socket对象获取ip地址
String ip = socket.getInetAddress().getHostAddress();
System.out.println("data from :" +ip +" content is :"+str);
System.out.println("服务器端接收完毕...");
//释放资源
ss.close();
}
}
public class ClientDemo {
public static void main(String[] args) throws IOException {
//1)创建客户端的Socket
Socket socket = new Socket("10.12.152.129",6666) ;
//2)获取当前客户端对象所在的通道内的输出流对象
OutputStream outputStream = socket.getOutputStream();
//3)写数据
outputStream.write("hello,TCP,我来了".getBytes());
//4)释放资源
socket.close();
}
}