From:https://blog.csdn.net/w252064/article/details/79923999
[Java高级特性详解]:https://blog.csdn.net/qq_37977176/article/details/78941649
菜鸟教程 之 Java 教程:https://www.runoob.com/java/java-tutorial.html
本部分内容主要有集合框架及泛型,实用类,输入和输出处理,注解与多线程,网络编程与XML技术。初次学习这部分会感觉很难,主要是概念难于理解,最好是多看看例子,多练习。下面是个人的总结
一、集合框架及泛型
1、集合框架
是一套性能优良、使用方便的接口和类(位于 java.util 包中)解决数组在存储上不能很好适应元素数量动态变化,查找效率低的缺陷
集合接口: Map、Collection(子接口List、Set) 、 Iterator接口实现类:HashMap TreeMap 、ArrayList LinkedList、 HashSet TreeSet 实现map、list、set接口集合工具类:Arrays 、Collections 提供对集合元素进行操作的算法
2、接口的区别
Collection 接口存储一组可重复,无序的对象(包括 List Set 接口)通用方法:
clear() 清除元素
isEmpty() 判断集合是否为空
iterator() 获得集合的迭代器
toArray() 集合转换为数组
List 接口存储一组可重复,有序的对象
Set 接口存储一组唯一,无序的对象
Map接口存储一组键值对象,键是唯一的,Map和Set很像
4、接口实现类
ArrayList:
在内存中分配连续的空间。根据下标遍历元素和随机访问元素的效率比较高,而增加和删除由于位置移动操作很慢
常用方法:
add(Objiect o) 在列表末尾顺序添加元素
get(int index) 返回指定索引位置处的元素
size() 返回列表中的元素个数
contains(Objiect o) 判断列表中是否存在指定元素
remove(Objiect o) 删除列表中的元素
LinkedList:
采用链表存储方式。所有顺序查找的时候很慢,而插入、删除元素时无需移动位置,效率比较高常用方法:
addFirst(Objiect 0) 在列表首部添加元素
addLast(Objiect 0) 在列表尾部添加元素
getFirst() 获得当前集合的第一个元素
getLast() 获得当前集合的最后一个元素
removeFirst() 删除并返回列表中的第一个元素
removeFirst() 删除并返回列表中的最后一个元素
TreeSet | TreeMap 比较:
底层是二叉树结构;
TreeMap、TreeSet都保存了对象的排列次序;
TreeSet只存储一个对象,而TreeMap存储两个对象Key和Value;
存储速度比Hash集合慢。
HashSet | HashMap比较:
底层数据结构为哈希表;
HashMap存储键值对,键唯一,而HashSet仅仅存储对象,对象唯一;
HashMap使用唯一的键来获取对象,速度相对较快。
HashSet 集合方法:
add(Objiect o) 添加对象
size() 返回元素个数
contains(Objiect o) 判断是否存在
remove(Objiect o) 移除有关对象
HashMap 集合方法:
put(key,value) 添加键值对
get(key) 获取与key有关的值
remove(key) 移除与key有关的映射,并返回旧值
containsKey( ) containsValue( ) 判断是否存在key value
size() 返回元素个数
keySet() 获取所有key的集合
values() 获取所有values的集合
5、集合遍历
三种方法:普通for循环 增强for循环 Iterator迭代器遍历
- 1. for (Object object : list) { System.out.println(object); }
- 2. for (int i = 0 ;i<list.size();i++) { int j= (Integer) list.get(i); System.out.println(j); }
- 3. Iterator iterator = list.iterator();while(iterator.hasNext()){ int i = (Integer) iterator.next(); System.out.println(i); }
Iterator方法:
- HasNext() 判断是否存在下一个可访问的元素,如果可以,返回true
- Next() 返回要访问的下一个元素
6、Collections工具类
作用:实现对元素的排序、查找和替换操作
如果要比较一个类的对象之间的大小,必须要实现Comparable接口。
Comparable接口:对实现它的每个类的对象进行自然排序。
comparableTo(Object obj)方法:用于比较此对象与指定对象的顺序
返回值:0等于、1大于、-1小于指定对象obj
方法:
fill( ) 替换集合中所有元素为相同元素的方法
sort( ) 对集合进行排序的方法
binarySearch( ) 对集合进行查找的方法
max( )\min( ) 查找最大值、最小值
7、泛型集合
泛型即参数化类型,通过指定集合中的元素类型来实现约束
作用:将对象的类型作为参数,指定到其他类或者方法上,从而保证类型转换的安全性和稳定性
举例:List<Integer> list=new ArrayList<Integer>( );
ArrayList<Student> students = new ArrayList<Student>();
典型的泛型集合:ArrayList<E>、HashMap<K,V>
泛型类: public class User<T>{}
泛型接口:public interface Pair<T>{}
泛型方法: public <T> void getMiddle(T[] b) {} 注意<T>的位置
在泛型中,基本类型是不可以做泛型参数,只能使用包装类、引用数据类型。
二、实用类
1、基本概念
Java API:Java应用程序的编程接口、Java帮助文档
实用类: 由Java API提供的常用类
学习这部分一定要多看 Java API 。Java 帮助文档提供的常用包如下:
lang包 :包含基础类和接口 如 Comparable接口 、包装类、 String、Math类
Util包 :包含系统辅助类 如 Collection、Map接口、 Date、Arrays类
Io包 :与输入输出有关类 如 Serializable接口、File、Reader、Writer类
Net包 :与网络有关类 如CookieStore接口 、Socket、URL、ServerSocket类
Sql包 :与数据库有关类 如 Statement接口、DriverManager、DriverPropertyInfo类
2、枚举
指由一组固定的常量组成的类型。使用enum关键字定义
举例:定义:public enum Genders{男,女} 调用:Genders.男
作用:类型安全、易于输入、代码清新
3、包装类
概念:把基本数据类型包装为对象,方便对象的操作,体现了java面向对象的特点。 ag:int→Integer char→Character byte→Byte
包装类作用:
- 方便在各种类型之间的转化 如:int类型和String类型互相转换
- 提供了基本数据类型的相关属性与方法 如:最小值、toString() 、valueOf()、equals()方法
常用方法:
toString() :将基本数据类型转换为字符串类型
valueOf() :静态的重载方法 将基本数据类型、字符串转换为包装类
parseInt()、parseBoolean() :把字符串转换为相应基本数据类型
4、类型转换
- 基本类型转包装类:Integer i=5;或 Integer i=new Integer(5);或Integer i=new Integer(“5”);或Integer i=Integer.valueOf(“5”);
注意:除Character包装类外,都可以将字符串作为参数来构造实例
- 包装类转基本类型:int intId=id.intvalue();或int intId=id;
- 自动转换: Integer i=5;//装箱 基本→包装 int j=i;//拆箱 包装→基本
jdk 1.5以后,基本类型和包装类的转换,编译器会自动完成
5、String类
- 在Java中,字符串常被作为String类型的对象来处理。
- 创建 String 对象方法:String a = "hello" 或 String a = new String("hello");
注意:第2个方法 ,创建了两个对象:一个 "hello" 字符串对象,在堆内存中;一个s对象,在栈内存中。 - 常用方法:
判断: equals() :判断两个字符串的内容是否相同 equalsIgnoreCase() :判断两个字符串的内容是否相同,不区分大小写 contains(String s) :判断一个字符串中是否包含另一个字符串 endsWith(String s) :测试此字符串是否以指定的后缀结束 startsWith(String s) :测试此字符串是否以指定的前缀开始 isEmpty() :测试字符串是否为空获取: int length() :返回此字符串的长度 char charAt(int index) :返回指定索引处的char值(字符) int indexOf() :返回指定字符(串)在此字符串中第一次出现处的索引 int lastIndexOf(int c) :返回指定字符在此字符串中最后一次出现的索引// 返回一个新字符串,它是此字符串的一个子字符串,包含头不包含尾。 String substring(int beginIndex, int endIndex)转换: byte[] getBytes() :从字符串到字节数组的方法 char[] toCharArray() :从字符串到字符数组的方法 String valueOf(数据类型) :把该数据类型的数据转换成字符串 String toLowerCase() :把字符串转换成小写 String toUpperCase() :把字符串转换成大写 String concat(String str) :将指定字符串连接到此字符串的结尾替换分割: String replace(char oldChar, char newChar) :用新字符替换旧字符 String[] split(String regex) :根据指定的字符串把一个字符串分割成一个字符串数组 String trim() :去除字符串的前后空格 int compareTo(String anotherString) :按字典顺序比较两个字符串 int compareToIgnoreCase(String str) :按字典顺序比较两个字符串,不考虑大小写
6、StringBuffer
- 相当于给字符串一个缓冲区,是String的增强类。对字符串频繁修改(如字符串连接)时,使用StringBuffer类可以大大提高程序执行效率。
- StringBuffer 声明
StringBuffer strb = new StringBuffer(); StringBuffer strb = new StringBuffer("aaa");
-
常用方法:
增加: append("**”) :追加各种类型的数据到字符串之后 insert (1, "**”) : 在容器指定位置插入各种类型的数据删除: deleteCharAt() :删除指定位置的字符 delete() :清空StringBuffer的缓冲区替换: replace() :用新字符替换旧字符 toString() :将StringBuffer类型的字符串转换为String类型的对象获取: charAt() :返回指定索引处的char值(字符串) length() :返回此字符串的长度
- JDK5.0 后提供了 StringBuilder,等价 StringBuffer。但是是单线程的,效率相对较高,但是不保证线程安全。
7、Math类
提供了常用的数学运算方法和两个静态常量E(自然对数的底数)和PI(圆周率)
常用方法:
abs() :返回绝对值;
max() :返回最大值;
random() :返回随机数
ag:生成[0,10)区间的整数 int random = (int)(Math.random()*10);
8、Random类
是产生随机数的一个类
常用方法:
- 构造方法
Random() 创建一个新的随机数生成器。 Random(long seed) 使用单个种子创建一个新的随机数生成器。 注意:种子数只是随机算法的起源数字,和生成的随机数字的区间无关 ag:Random rand = new Random(10);
- 成员方法
int nextInt() 返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。 int nextInt(int n) 返回一个伪随机数,该值介于[0,n)的区间。 ag:生成[0,10)区间的整数 int num = rand.nextInt(10);
11、Scanner类
位于java.util包,是获取从键盘的输入数据的一个类
- 构造方法
Scanner(InputStream source) 创建一个用来解析基本类型和字符串的文本扫描器 ag:Scanner sc = new Scanner(System.in);
- 成员方法
hasNext() 判断扫描器中当前扫描位置后是否还存在下一段。 hasNextLine() 如果在此扫描器的输入中存在另一行,则返回 true。 nextInt() 将输入信息的下一个标记扫描为一个int,接受整型变量。 next() 以换行或空格符为分界线接收下一个String类型变量。如:输入hello world!,接收到的只是hello nextLine() 以换行为分界线接收下一个String类型变量。如:输入hello world!,接收到的是hello word!
12、Date类
位于java.util包,表示日期和时间的类
- 构造方法
Date() 分配Date对象并初始化此对象,以表示分配它的时间(精确到毫秒)。 Date(long date) 分配Date对象并初始化此对象,以表示从标准基准时间(即1970年1月1日00:00:00GMT)以来的指定毫秒数。
- 成员方法
int compareTo(Date anotherDate) 比较两个日期的顺序 boolean equals(Object obj) 比较两个日期的相等性。
13、SimpleDateFormat类
位于java.text包,格式化和解析日期的具体类
固定写法:
//创建日期对象 Date date = new Date();
//定制日期格式 SimpleDateFormat f= new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
String now = f.format(date); System.out.println(now);
14、Calendar类
位于java.util包,用于设置和获取日期/时间数据的特定部分
int get(int field) 返回给定日历字段的值
YEAR 指示年 MONTH 指示月
DAY_OF_MONTH 指示一个月中的某天
DAY_OF_WEEK 指示一个星期中的某天
三、输入/输出和反射
1、File类
位于java.io包,用来操作文件目录和属性
- 构造方法:
File(String pathname) 指定文件路径 File(String dir,String subpath) dir参数指定目录路径,subpath参数指定文件名 File(File parent,String subpath) parent参数指定目录文件,subpath参数指定文件名
- 常用方法:
创建: boolean createNewFile( ) 创建名称的空文件,不创建文件夹 boolean mkdir() 创建由该File对象表示的目录(一级文件夹) boolean mkdirs() 创建包括父目录的目录(二级文件夹)判断: boolean exists( ) 判断文件或目录是否存在 boolean isFile( ) 判断是否是文件 boolean isDirectory( ) 判断是否是目录获取: String getPath( ) 返回此对象表示的文件的相对路径名 String getAbsolutePath( ) 返回此对象表示的文件的绝对路径名 String getName( ) 返回此对象表示的文件或目录的名称 String getParent() 返回此对象父目录的路径名; long length() 返回文件的长度,单位为字节, 如果文件不存在,则返回0L删除: boolean delete( ) 删除此对象指定的文件或目录
2、相对路径与绝对路径
相对路径:从中间目录出发,到目前位置路径。
绝对路径:从根目录出发,到目前位置的路径。
3、Java IO流
指二进制的字节序列,是一连串流动的字符,是以先进先出方式发送信息的通道
分类:
- (1) 按照流操作的数据类型分为:字节流和字符流。字节流是8 位通用字节流,字符流是16位Unicode字符流
- (2) 按照流的流向分为:输入流,输出流(相对计算机程序而言,先入后出、先读后写)。源数据源(键盘、硬盘)→输入流(读)→程序→输出流(写)→目标数据源(控制台)
4、IO流常用基类
注意:( )里面是子类 如File**类,Buffered**类
Buffered**类带有缓冲区,有按行读取内容的readLine()方法
- 字节流
字节输入流:InputStream (FileInputStream、BufferedInputStream) 字节输出流:OutputStream (FileOutputStream、BufferedOutStream)
- 字符流
字符输入流:Reader (FileReader、BufferedReader) 字符输出流:Writer (FileWriter、BufferedWriter)
5、常用基类的方法
- 字节输入流InputStream类方法
void close() 关闭此输入流并释放与该流关联的所有系统资源 int read() 读取一个字节数据 int read(byte[] b) 读取一定数量的字节,并将其存储数组中 int read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节,保存到字节数组b中
- 字节输出流OutputStream类方法
void close() 关闭此输出流并释放与此流有关的所有系统资源 write(int b) 写入一个字节数据 void write(byte[] b) 写入数组b的所有字节 void write(byte[] b, int off, int len) 将字节数组中从偏移量 off 开始的 len 个字节写入到输出流
- 字符输入流Reader类方法
void close() 关闭输入流 int read() 读取单个字符 int read(char[] c) 将c.length长度的字符读入数组c中 int read(char[] c, int off, int len) 将最多len长度的字符读入数组c,保存位置从off位置开始
- 字符输出流Writer类方法
void close() 关闭输出流 void flush() 刷新输出流 int read() 读取单个字符。 int read(char[] cbuf) 将字符读入数组 int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分
6、节点流与包装流
节点流:创建对象时,参数是字符串或File类对象
包装流:创建对象时,参数是流对象。
包装的作用:1.提高效率 2.方便书写代码
7、使用字节流读写文本文件
- 使用 FileInputStream 读文本文件
//构造字节输入流对象 FileInputStream fis= new FileInputStream(“c:\\test.txt”); //循环读取文件数据 最后关闭流对象fis.close(); System.out.println(“可读取的字节数”+fis.available()); byte []buf = new byte[1024]; int len=0; while((len=fis.read(buf))>0){ System.out.write(buf, 0, len); }
- 使用FileOutputStream 写文本文件
//构造字节输入流对象 FileOutputStream fos=new FileOutputStream(“f:/java.txt”); //把数据写入文本文件 最后关闭流对象fos.close(); int num=12345;String s=String.valueOf(num); fos.write(s.getBytes(), 0, s.getBytes().length);
8、使用字符流读写文本文件
- 使用FileReader/BufferedReader读取文件
//创建FileReader/BufferedReader对象 Reader fr= new FileReader(“D:\\myDoc\\简介.txt”);//节点流 BufferedReader br=new BufferedReader(fr); //包装流 //调用readLine()方法读取文本文件的数据 最后关闭流对象 String s=null; while((s=br.readLine())!=null){…}
- 使用FileWriter/BufferedWriter写文件
//创建FileWriter/BufferedWriter对象 FileWriter fw= new FileWriter(“D:\\myDoc\\简介.txt”); BufferedWriter bw=new BufferedWriter(fw); //调用write()方法写文本文件的数据 最后关闭流对象 fw.write(); fw.close();
9、解决读取时中文乱码
//使用InputStreamReader并设置编码格式
InputStreamReader fr=new InputStreamReader(fis,"UTF-8");//以字节数组的形式读取
byte []buf = new byte[1024]; fis.read(buf)
10、读写二进制文件
- 使用FileInputStream/DataInputStream读取二进制文件
//构造数据输入对象 FileInputStream fis=new FileInputStream(“C:\\HelloWorld.class”); DataInputStream dis=new DataInputStream(fis); //调用read()方法读取 dis.readInt(); dis.close();
- 使用FileOutputStream/DataOutputStream写二进制文件
//构造数据输出对象 FileOutputStream outFile=newFileOutputStream(“C:\\temp.txt”); DataOutputStream out=new DataOutputStream(outFile);//调用write()方法写入 out.write(); out.close();
11、序列化与反序列化
序列化:将对象的状态写入到特定的流中的过程。对象 —> 流
反序列化:从特定的流中获取数据重新构建对象的过程。流 —> 对象
作用:Java对象序列化后,得到的二进制字节序列可以方便的保存到磁盘或者云上。二进制序列可以方便地跨平台传输,不用担心因平台问题而显示异常。
实现步骤:
- 1、实现Serializable接口
- 2、创建对象输出流ObjectOutputStream(序列化)/输入流ObjectInputStrean(反序列化)
- 3、调用writeObject()/readObject ()方法将对象写入文件(序列化)/读取对象(反序列化)
- 4、关闭对象输入流
注意:使用transient关键字修饰对象的某些属性时,这些属性将不再被序列化
12、java反射
反射:指java程序能自描述和自控制,它允许程序在运行时才加载、探知、使用编译期间完全未知的类
反射机制:指在运行状态中,动态获取类信息以及动态调用对象方法的功能
反射常用API:
- Class类 — 可获取类和类的成员信息
- Field类 — 可访问类的属性
- Method类 — 可调用类的方法
- Constructor类 — 可调用类的构造方法
使用反射的步骤:
- 1、导入java.lang.reflect.*;
- 2、获取需要操作类的Class对象
- 3、调用Class的方法获取Field、Method等对象
- 4、使用反射API进行操作
反射的应用:
- 获取Class对象:getClass()方法 Class.forName()方法 .class 方法
- 创建Class对象:newInstance()方法
- 访问类的属性:getXxx()方法 setXxx()方法
- 访问类的方法:getMethod()方法 invoke()方法
四、注解和多线程
1、注解
Java代码里的特殊标记。它为在代码中添加用Java程序无法表达的额外信息提供了一种形式化的方法。注解可以看成修饰符,修饰程序元素。
注解可以在编译、类加载、运行时被读取。而注释不会被程序所读取。
2、注解分类
(1) 内建注解:标准注解类型;
@Overrid 限定重写父类方法
@Deprecated 标示已过时
@SuppressWarnings 抑制编译器警告
(2) 元注解: 修饰其他的注解定义
@Target 指定被其修饰的注解能用于修饰哪些程序元素
@Retention 指定该注解可使用反射读取
@Documented 指定该注解将被JavaDoc工具提取成文档
@Inherited 指定被其修饰的注解将具有继承性
(3)自定义注解: 注解类型是一种接口
使用关键字@interface定义新注解,如:public @interface AnnotationTest{}
3、读取注解信息
AnnotatedElement接口是所有程序元素的父接口,指定了程序中可以接受注解的程序元素。通过反射获取对象信息。
getAnnotation()方法:返回该程序元素上存在的、指定类型的注解
getAnnotations()方法:返回该程序元素上存在的所有注解
4、进程与线程
- 程序:是对数据描述与操作的代码的集合。
- 进程:指程序的一次动态执行过程。是系统运行程序的基本单位,有独立的内存空间和系统资源
- 线程:指进程中的一个执行流程。是进程中执行运算的最小单位,真正在处理机上运行的是线程,一个进程中至少要有一个线程。
- 线程创建与启动:
(1)继承 java.lang.Thread类 如:class MyThread extends Thread{}
(2)实现 java.lang.Runnable接口 如:class MyThread implements Runnable{}
都需要重写 run()方法,调用 start() 方法
MyThread myThread = new MyThread(); new Thread(myThread).start();
5、线程状态
↙阻塞|睡眠状态↘
新生状态—>可运行状态<—>运行状态—>死亡状态
新生状态:线程对象已经创建,还没有在其上调用start()方法。
可运行状态:当线程有资格运行,但调度程序还没有把它选定为运行线程时线程所处的状态。
运行状态:线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态
等待/阻塞/睡眠状态:是线程有资格运行、只是没有条件使线程苏醒所处的状态。
死亡状态:当线程的run()方法完成时就认为线程死去
6、线程调度
多个线程处于可运行状态,线程调度会根据优先级来决定线程进入可运行状态的次序。
线程的优先级用1~10 表示,10的优先级最高,默认值是5
设置优先级:setPriority(int grade) 如:myThread.setPriority(3);
调度方法:
join() :将指定的线程加入到当前线程。先执行完调用该方法的线程再继续执行本线程
sleep() :当前线程在指定毫秒内停止执行而转入不可运行状态
yield() :当前线程转入暂时停止运行的状态
7、线程同步
当两个或多个线程需要访问同一资源时,需要以某种顺序来确保该资源某一时刻只能被一个线程使用。同步就相当于上锁,上了锁的线程首先访问资源,其他线程等待。
实现线程同步:
同步方法: 用 synchronized关键字修饰的方法
public synchronized void save(){}
同步代码块: 用synchronized关键字修饰的代码块
synchronized(object){}
注意:多线程使用同步存在”死锁”的潜在危险。
死锁:如果多个线程都处于等待状态而无法被唤醒,就构成了死锁。比如同步方法里面有sleep()方法,那么这个锁就成了死锁。
8、线程通信
线程同步可以阻止并发访问同一资源,但不能实现不同线程之间的消息传递。所以需要用到线程通信。
注意下面方法只能在同步方法或同步代码块中使用
wait()方法 :挂起当前线程,并释放共享资源的锁
notify()方法:唤醒线程。在因调用该对象的wait()方法而阻塞的线程中随机选择一个解除阻塞,但要等到获得锁后才可执行
notifyAll()方法:将因调用该对象的wait()方法而阻塞的所有线程一次性全部解除阻塞
五、网络编程技术
1、基本概念
网络:是信息传输、接收、共享的虚拟平台,把各个点、面、体的信息联系到一起,从而实现资源共享
网络编程:通过使用套接字来达到进程间通信目的的编程
2、IP地址(Internet Protocol)
概念:唯一标识网络上的每一台计算机
IP组成:32位,由4个8位二进制数组成(ipv4)
11000000.10101000.00000001.11001000–>192.168.1.200
IP地址=网络地址+主机地址
3、IP检测
查看IP地址:cmd—ipconfig
检测网络是否通畅:ping IP地址
4、DNS
域名解析器,把IP地址映射到域名。实现网站通过域名访问
5、网络服务器
指在网络环境下,具有较高计算能力,能够提供用户服务功能的计算机(邮件服务器;web服务器 如Apache Tomcat 阿里云)
客户机→服务器 (Client/Server) ( c/s)
浏览器→服务器 (Browser/Server)( b/s)
6、网络通信协议
为了在网络中不同的计算机之间进行通信而建立的规则、标准或约定的集合
应用层 HTTP FTP TFTP SMTP SNMP DNS协议
传输层 TCP UDP 协议
网络层 ICMP IGMP IP ARP RARP 协议
数据链路层和物理层 由底层网络定义的协议
7、Socket编程
- Socket(套接字):是通信链路的端点。也是Java提供的接口。因为Socket的底层机制复杂,所以Java提供了API方便我们使用Socket编程
- Socket通信模型:进行网络通信时,Socket需要借助数据流来完成数据的传递工作
- 流式套接字:基于TCP协议的Socket网络编程
1、客户端Socket 类
//创建一个客户端Socket
Socket socket = new Socket("localhost",端口参数)//通过输出流,发送请求 getOutputStream( ) write()
OutputStream os=Socket.get OutputStream( );
byte[] infos=info.getBytes();
os.write(infos);//关闭输出流
socket.shutdownOutput();// 通过输入流,接收服务端响应
Inputstream is = socket.getInputStream();//释放资源
2、服务器端ServerSocket类
//创建一个服务器Socket
ServerSocket serverSocket=new ServerSocket(5000)//使用accept()方法等待客户的通信
Socket socket=serverSocket.accpet();//获得输入流,获得客户端请求
InputStream is=socket.getInputStream();//把获得的字节流包装成字符流
BufferedReader br=new BufferedReader(new IputStreamReader(is));//通过输出流,发送响应
OutputStream os = socket.getOutputStream(); Os.write(replys);//释放相应资源
- 数据包式套接字:基于UDP协议的Socket网络编程
① 利用DatagramPacket对象封装数据包
② 利用DatagramSocket发送数据包(send())
③ 利用DatagramSocket接收数据包(receive())
④ 利用DatagramPacket处理数据包
- TCP 与 UDP 的区别
TCP | UDP | |
是否连接 | 面向连接 | 面向非连接 |
传输可靠性 | 安全可靠 | 不可靠 |
速度 | 慢 | 快 |
六、XML技术
1、XML简介
XML(Extensibel Markup Language):即可扩展标记语言,是一种简单的数据存储语言,使用一些列简单的标记描述数据。
特点:与操作系统、开发平台无关;规范统一
作用:数据交互;配置应用程序和网站;Ajax基石
2、XML基本结构
(1)XML声明。如:<?xml version=”1.0” encoding=”UTF-8”?>
(2)唯一的根元素。如: <books> </books>
(3)元素描述信息。 如<book id=”1”><title>java编程思想</title></book>
3、XML标签
<元素名 属性名 = “属性值”>元素内容</元素名>
如:<id name=”id” column=”id”> <generator class=”sequence”/> </id>
注意:属性值用双引号包裹。有多个属性用空格隔开
4、XML转义符
< 对应转移符< > 对应转移符 >
”对应转移符" ’对应转移符'
& 对应转移符&
当元素中出现很多特殊字符时,可以使用CDATA节 :<![CDATA[from Student where sid=?]]>
5、XML解析器
非验证解析器:检查文档格式是否良好 (eclipse自带)
验证解析器: 使用DTD(文档类型定义)或Schema检查文档的有效性
6、XML命名空间
写法:< xmlns:name=”url”>
举例:xmlns:canon=”http://www.canon” –XML命名空间
xmlns=”http://www.Aptech_edu.ac” —属性命名空间
7、解析XML技术
DOM(文档对象模型):把XML文档映射成一个倒挂的树
- DOM:基于XML文档树结构的解析。适用于多次访问的XML文档。特点:比较消耗资源
步骤:
1.创建解析器工厂对象
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance( );2.解析器工厂对象创建解析器对象
DocumentBuilder db = dbf.newDocumentBuilder( );3.解析器对象指定XML文件创建Document对象
Document document = db.parse(“要解析的路径”)4.以Document对象为起点操作DOM树
NodeList dogList= document.getElmentsByTagName(“节点”)
DOM接口方法
Document接口:
getElementById()getElementsByTagName() getElementsByName()等方法
Node接口:
getparentNode() getchildNodes() getfirstChild() getlastChild()
getnextSibling () getpreviousSibling() createTextNode( ) removeChild()等方法
Element接口:
getTagName() createElement( )等方法
- SAX:基于事件的解析。适用于大数据量的XML文档。特点:占用资源少,内存消耗小
- DOM4J:非常优秀的Java XML API。性能优异、功能强大。特点:开放源代码
DOM4J解析XML方法
//创建SAXReader对象 SAXReader reader = new SAXReader();//获取XML文档对象 Document document = reader.read("xml/users.xml");//获取root(根)节点 Element root = document.getRootElement();//获取节点下的所有子节点集合 List<Element> users=root.elements();//遍历输出 for(Element user:users){…}DOM4J创建XML方法//创建了一个xml文档
Document document=DocumentHelper.createDocument();//创建一个根节点 和一个子节点 并添加属性
Element root=document.addElement("users");
Element user = root.addElement("user").addAttribute("id", "1");//设置子节点的文本
user.addElement("username").addText("zs");
user.addElement("password").addText("111");//创建输出流对象
File file = new File("src/xml/users.xml");
FileOutputStream out = new FileOutputStream(file);//创建一个XMLWriter的对象 调用write方法写入
writer = new XMLWriter(out, OutputFormat.createPrettyPrint());
writer.write(document);
七、相关代码
package com.hfxt.demo02;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*** 1.输入:***InputStream(***Reader)/输出:***OutputStream(***Writer)* * 2.字节流:***Stream/字符流:***Reader(***Writer)** 3.节点流:创建对象时,参数是字符串或File类对象* 包装流(装饰流):创建对象时,参数是流对象,包装的作用:1.提高效率 2.方便书写代码*/
public class Demo01 {public static void main(String[] args) {File file = new File("f:/java/User.java");FileInputStream fis=null;try {fis=new FileInputStream(file);
/* int data;while((data=fis.read())!=-1){System.out.print((char)data);}*/byte []buf = new byte[1024];int len=0;while((len=fis.read(buf))>0){//System.out.write(buf);System.out.write(buf, 0, len);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}
package com.hfxt.demo02;
import java.io.*;
//二进制文件的读写
public class ReadAndWriteBinaryFile {public static void main(String[] args){DataInputStream dis=null;DataOutputStream dos=null;FileInputStream fis=null;FileOutputStream fos=null;try {//创建输入流对象fis=new FileInputStream("c:\\myDoc\\star.jpg");dis=new DataInputStream(fis);//创建输出流对象fos=new FileOutputStream("c:\\myDoc\\new.jpg");dos=new DataOutputStream(fos);//读取文件并写入文件int temp;while((temp=dis.read())!=-1){dos.write(temp);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally{try {if(dis!=null){dis.close();}if(dos!=null){dos.close();}if(fis!=null){fis.close();}if(fos!=null){fos.close();}} catch (IOException e) {e.printStackTrace();}}}
}
package com.hfxt.demo;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Demo08 {public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {User user = new User(1, "zs", "111", "zs");//序列化ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(new File("f:/wkjava/user.txt"))));oos.writeObject(user);if(oos!=null) oos.close();//反序列化ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(new File("f:/wkjava/user.txt"))));User user2=(User) ois.readObject();System.out.println(user2);}
}
package com.hfxt.demo;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo05 {/** 用字符流复制文本文件*/public static void main(String[] args) {//创建文本文件对象和流对象File file1 = new File("f:/wkjava/a.jpg");File file2 = new File("f:/wkjava/3.jpg");FileOutputStream fos = null;FileInputStream fis = null;BufferedInputStream bis = null;BufferedOutputStream bos = null;try {//将文件对象放入流对象中fis = new FileInputStream(file1);fos = new FileOutputStream(file2);bis=new BufferedInputStream(fis);bos=new BufferedOutputStream(fos);//创建数组byte []buf=new byte[1024];int len=0;//复制操作:先读后写while((len=bis.read(buf))>0){bos.write(buf, 0, len);}//清缓冲区//bos.flush();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally { //关闭流if(bis!=null)try {bis.close();} catch (IOException e) {e.printStackTrace();}if(bos!=null)try {bos.close();} catch (IOException e) {e.printStackTrace();}}
}
}
package com.hfxt.demo;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class ReadXml {public static void main(String[] args) {//创建SAXReader对象 SAXReader reader = new SAXReader();try {//读取文件 Document document = reader.read("xml/users.xml");//获取root(根)节点 Element root = document.getRootElement();//获得根元素/*System.out.println(root.getName());System.out.println("*******************");System.out.println(root.getText());System.out.println("*******************");*///获取节点下的所有子节点集合 List<Element> users=root.elements();//遍历 for(Element user:users){System.out.println(user.attributeValue("id"));System.out.println(user.elementText("username"));System.out.println(user.elementText("password"));System.out.println(user.elementText("nickname"));}} catch (DocumentException e) {e.printStackTrace();}}
}
package com.hfxt.demo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
public class WriteXml {public static void main(String[] args) throws Exception {XMLWriter writer=null;//创建文档:使用了一个Helper类Document document=DocumentHelper.createDocument();//添加属性 添加子节点Element root=document.addElement("users");Element user = root.addElement("user").addAttribute("id", "1");user.addElement("username").addText("zs");user.addElement("password").addText("111");user = root.addElement("user").addAttribute("id", "2");user.addElement("username").addText("ls");user.addElement("password").addText("222");String path="src/xml/users.xml";File file = new File(path);if(!file.getParentFile().exists()){file.getParentFile().mkdirs();}FileOutputStream out = new FileOutputStream(file);//writer=new XMLWriter(out);writer=new XMLWriter(out, OutputFormat.createPrettyPrint());writer.write(document);}
}