char c='\u4e00' //汉字开始
char c='\u9fa5'//汉字结束
java 正则 正则表达式: java.util.regex.Pattern
[] 匹配的一个字符
[^a] 一个非a的字符
[^abcd]一个非a,b,c,d的字符
[A-Z] 一个 A-Z 的字符
[a-z] 一个a-z的字符
[0-9] 一个0-9 的字符
[a-z&&[^bc]]一个a-z的字符 而且不能是bc
. 任意一个字符
\d 任意一个数字
\w[a-zA-Z0-9_]
\s空白字符 [\y\n\xOB\f\r]
\D非 \d
\W非 \w
\S非 \s
量词
[0-9]? 0 或者1
[0-9]* 0 到无限
[0-9]+ 最少一个
[0-9]{6} 必须6个
[0-9]{6,}最少6个
[0-9]{0,6}最多6个
[0-9]{6,9}6-18位
(\+86) +86 这个整体
位置限定符
^ 第一个字符
$ 最后一个字符
分组
()
特殊字符转义
\
^[\w]+@[\w]+(\.[a-zA-Z0-9]+)+$
但是 java中的String 中的matches 中的匹配时全匹配 也就是^ $ 你加不加 java 都帮你加上了
| 或的意思
(0086|\+86) 0086 或者 +86
Object 是所有类的父类
Object 东西
toString()方法
1)返回对象文本描述
2)被很多API默认调用
3)建议重写toString方法,对象的文本描述
4)建议自定义的每一类增加toString()方法
equals 方法: 比较两个对象的内容是否一样
instanceof
instance of 的实例
== 比较变量的值,引用变量的值是地址值 比的是对象的地址(引用类型变量 指向的地址)
也就是比较的是否是同一个对象
package se.day001;
/**
* 斗地主
* @author 煊
*
*/
public class Card {
/** 花色*/
private int suit;
/** 点数*/
private int rank;
public static final int THREE=0;
public static final int FOUR=1;
public static final int FIVE=2;
public static final int SIX=3;
public static final int SEVEN=4;
public static final int EIGHT=5;
public static final int NINE=6;
public static final int TEN=7;
public static final int JACK=8;
public static final int QUEEN=9;
public static final int KING=10;
/**
* A
*/
public static final int ACE=11;
/**
* 2
*/
public static final int DEUCE=12;
/**
* 小王
*/
public static final int BLACK=13;
/**
* 大王
*/
public static final int COLOR=14;
/**
* 方块
*/
public static final int DIAMOND = 0;
/**
* 梅花
*/
public static final int CLUB = 1;
/**
* 红桃
*/
public static final int HRART = 2;
/**
* 黑桃
*/
public static final int SPADE = 3;
/**
* 王
*/
public static final int JOKER = 4;
public Card(int suit,int rank){
this.suit = suit;
this.rank = rank;
}
public int getSuit(){
return suit;
}
public int getRank(){
return rank;
}
public void setSuit(int suit){
this.suit = suit;
}
public void setRank(int rank){
this.rank = rank;
}
private static String[] suitName = {"方块","梅花","红桃","黑桃",""};
private static String[] rankName = {"3","4","5","6","7","8","9","10","J","Q","K","A","2","小王","大王"};
@Override
public String toString(){
return "点数:"+rankName[rank]+";花色:"+suitName[suit];
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + rank;
result = prime * result + suit;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if(obj instanceof Card){
Card other = (Card)obj;
return this.rank ==other.rank && this.suit == other.suit;
}
return false;
}
}
package se.day001;
/**
* 建议重写toString方法,对象的文本描述
* @author 煊
*
*/
public class Dmeo01 {
public static void main(String[] args){
Card ace = new Card(Card.SPADE,Card.ACE);
String whatIsIt = ace.toString();
System.out.println(whatIsIt);
Card c1 = new Card(Card.DEUCE,Card.TEN);
Card c2 = new Card(Card.DEUCE,Card.TEN);
Card c3 = c1;
System.out.println(c1==c2);
System.out.println(c1==c3);
System.out.println(c1.equals(c2));
System.out.println(c1.equals(c3));
}
}
package se.day001;
public class Demo02 {
public static void main(String[] args){
Object o1 = new Card(Card.DIAMOND,Card.THREE);
Object o2 = "方块3";
System.out.println(IsCard(o1));
System.out.println(IsCard(o2));
}
public static boolean IsCard(Object o){
if(o ==null){
return false;
}else{
return (o instanceof Card);
}
}
}
String 类的特点
字符串是字符数组组成的
字符串 对象 是不可改变的,字符串引用可以重新赋值
为了提高性能,静态字符串(字面量/常量/常量连接的结果)在静态池中创建,尽量使用同一个对象,重用静态字符串
package se.day001;
import java.util.Arrays;
/**
* 实现 字符数组内容转为小写
* 实现 字符数组内容转为大写
* @author 煊
*
*/
public class Demo03 {
public static void main(String[] args){
char[] chs = {'I','l','o','v','e','u'};
char[] chs2 = Arrays.copyOf(chs, chs.length);
for(int i = 0;i<chs.length;i++){
if(chs2[i]>'A' && chs2[i]<'Z'){
chs2[i]=(char)(chs2[i]-('A'-'a'));
}
}
System.out.println(chs);
System.out.println(chs2);
String str = "I love u";
System.out.println(str);
System.out.println(str.toLowerCase());
System.out.println(str.toUpperCase());
}
}
package se.day02;
/**
* 正则
* @author zongx
*
*/
public class StringDemo {
public static void main(String[] args){
if(Test.email("81240805@qq.com")){
System.out.println("yes");
}else{
System.out.println("no");
}
if(Test.ID("321321199909191099")){
System.out.println("yes");
}else{
System.out.println("no");
}
}
}
class Test{
public static boolean email(String email){
String regex = "[\\w]+@[\\da-zA-Z0]+(\\.[\\da-zA-Z]+)+";
//String mail = "81240805@qq.com";
return email.matches(regex);//全匹配
}
public static boolean ID(String ID){
String regex ="[1-9]\\d{14}(\\d{2}[\\dxX])?";
return ID.matches(regex);
}
}
package se.day02;
/**
* 将字符串 中满足正则表达式的部分替换为给定内容
* @author 煊
*
*/
public class StringDemo3 {
public static void main(String[] args){
String str ="asdfhaj lh8349 38 512 jlkg0erg 03u0 24 ";
str = str.replaceAll("\\d+", "AA");
System.out.println(str);
String regex ="(sb|wqnmlgb|cnm|djb)";
String msg = "sb,你个djb";
String message = msg.replaceAll(regex, "****");
System.out.println(message);
}
}
Java 的字符串连接的过程是利用StringBuilder 实现的
建议在大量字符串计算的时候利用StringBuilder
String
StringBuilder
api方法是对其那内部char[] 内容进行 增删改查方法
package se.day001;
public class Demo05 {
public static void main(String[] args){
StringBuilder buf = new StringBuilder();
System.out.println(buf.append("123"));//增
System.out.println(buf.delete(0, 1));//删
System.out.println(buf.insert(0,"4"));//插入
System.out.println(buf.indexOf("4"));//查
System.out.println(buf.append("123"));
System.out.println(buf.replace(1,2, "22"));//替换
System.out.println(buf.reverse());//反转
}
}
StringBuffer
package se.day001;
public class Demo06 {
public static void main(String[] args){
StringBuffer buf = new StringBuffer();
System.out.println(buf.append("123"));//增
System.out.println(buf.delete(0, 1));//删
System.out.println(buf.insert(0,"4"));//插入
System.out.println(buf.indexOf("4"));//查
System.out.println(buf.append("123"));
System.out.println(buf.replace(1,2, "22"));//替换
System.out.println(buf.reverse());//反转
}
}
StringBuffer 和 StringBuilder
比较:StringBuffer 早于StringBuilder(快)
线程安全 StringBuffer 同步处理,性能稍慢
多线程使用
非线程安全 StringBuilder 并发处理,性能稍快
单线程使用
Java 中代表字符串的有 char[] String StringBuilder
char[] 只是字符数据,没有算法 用它就要自己实现方法 可能性能高 开发效率低
String 是不可变字符串 是最常用的字符串 java数据大多就是使用String 输出的
StringBuilder 是可变字符串,字符串的内容计算,建议采用StringBuilder实现,性能好
8个基本类型不是Object 的子类 也就是说 他们不是东西。
包装类 就是可以使8个基本类型可以参与到面向对象
都是final的
Byte byte
Short short
Integer int
Long long
Float float
Double double
还继承了java.lang.Object
-------------------------------------------
Character char
Boolean boolean
继承了java.lang.Object
---------------------------------------
创建的时候建议使用 常量池的方式 节省内存
Integer i = Intger.valueOf(1);
Integer i2 = new Integer(1);
java1.5 之后的变革
自动拆装箱:拆箱 自动将包装类对象转换为基本类型
:装箱 自动将基本类型数据转换为包装类对象
使用更加方便
System.out.println("-----------------");
int i3 = i;
System.out.println(i3);
Integer i4 = 1;
System.out.println(i4);
//提供两个常量 最大 和最小值
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
//将字符串转换为基本类型
String str = "1231234";
int i5 = Integer.parseInt(str);
System.out.println(i5);
String str2 = "123.123";
double d3 = Double.parseDouble(str2);
System.out.println(d3);
//将整数转换为2进制形式的字符串
int num = 100;
String bStr = Integer.toBinaryString(num);
System.out.println(bStr);
//转换16进制
String hStr = Integer.toHexString(num);
System.out.println(hStr);
double d4 = 100.101;
String dStr = Double.toString(d4);
System.out.println(d4);
BigDecimal类
BigDecimal 大小数
对小数做精确计算时,double不能描述的时候,就要使用这个类BigDecimal对小数做精确计算
BigInteger类
BigInteger 大整数
保存更长的整数,取值范围受内存限制,在long 不能满足的时候使用BigInteger
Java 中的时间
是一个long类型的整数,是GMT 1970年元旦到显示累计的毫秒数
时间的计算就是 毫秒数的 + -
UTC 时间:1970/01/01/00:00:00;
java.util.Date类
getYear(); 有2000年问题 需要+1900
getMonth();返回月份 从0开始 也就是要 +1
getDay();返回星期几
getTime();返回long毫秒值
setTime(long);修改时间毫秒值
SimpleDateFormat
format方法:将Date 对象转换为特定格式的字符串
parse方法:将字符串按照特定格式转换为Date对象
package se.day001;
// yyyy 2016
// yy 16
// MM 01
// M 1
// dd 13
// d 6
// E 星期三
// a a- 下午
// H 24小时制
// h 12小时制
// m 份
// s 秒
import java.text.SimpleDateFormat;
import java.util.Date;
public class Demo07 {
public static void main(String[] args){
Date t = new Date();
System.out.println(t.getYear());
System.out.println(t.getYear()+1900);
System.out.println(t.getMonth()+1);
System.out.println(t.getDate());
System.out.println(t.getDay());
t.setTime(0);
System.out.println(t.getYear());
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = fmt.format(t);
System.out.println(str);
System.out.println(fmt.format(0));//可以使用long值
}
}
DateFormat类
是SimpleDateFormat的父类创建实例时只需要条用其提供的一个静态方法getInstance()
package se.day001;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
public class Demo09 {
public static void main(String[] args){
Date date = new Date();
/**
* style 对应的常量 LONG SHORT MEDIUM
* 通常使用MEDIUM
* Locale 类
* 对应的地区
*/
DateFormat df = DateFormat.getDateInstance(DateFormat.LONG,Locale.CHINA);
System.out.println(df.format(date));
}
}
Calendar 类
可以方便的尽心日期的计算
获取日期中的信息考虑了时区等问题
抽象类 操作时间 判断时间
创建实例通常可以使用提供的工厂方法
getInstance()
该方法自动根据当前系统所处地区创建对应时区的实现类
package se.day001;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class Demo10 {
public static void main(String[] args){
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
System.out.println(calendar);
Date date = calendar.getTime();
System.out.println(sdf.format(date));
//设置一个时间点
calendar.set(Calendar.YEAR, 1111);
calendar.set(Calendar.MONTH,Calendar.NOVEMBER);
calendar.set(Calendar.DAY_OF_MONTH,11);
System.out.println(calendar.getTime());
calendar.set(Calendar.DAY_OF_MONTH,1111);
System.out.println(calendar.getTime());
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 11);
calendar.set(Calendar.SECOND, 11);
System.out.println(calendar.getTime());
int week = calendar.get(Calendar.DAY_OF_WEEK);
System.out.println(week);//国外星期天是第一天
int day = calendar.get(Calendar.DAY_OF_YEAR);
System.out.println(day);
int sumOfYear = calendar.getActualMaximum(Calendar.DAY_OF_YEAR);//传入的年的最大值
int sumOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);//传入的月的最大值
System.out.println(sumOfYear);
System.out.println(sumOfMonth);
}
}
java 中的集合框架
Collection接口
接口定义集合的相关特征
集合:
Collection
两个子接口
List集合 Set集合
可重复 equals 不可重复
有序的 无序的
ArrayList HashSet
内部使用数组 散列算法
LinkedList TreeeSet
内部使用链表 二叉树
ArrayList 使用数组方法实现,这种集合更适合查询数据,但是对频繁的增删元素 效率低
LinkedList 使用链表方法实现,这种集合更适合增删元素,但是对频繁的查询元素 效率低
基本类型有自动装箱
迭代器:
用于遍历集合元素
调用集合定义的方法iterator()
Iterator 接口
定义了遍历集合时的相关方法
不同的集合有着不同的迭代器实现
该接口有三个常用的方法:
boolean hasNext(): 是否还有元素可以获取
Object next():获取元素
void remove():删除当前迭代出的元素
遍历集合的顺序: 问取删(删可以不做)
删除只能通过迭代器remove 删除
泛型 1.5以后有的
泛型的本质就是参数化类型,再使用某个类时为方法属性等指定类型
新循环 1.5之后
新循环是使用迭代器的形式实现的 so 不能通过集合删除元素
int[] arr = {1,2,3,4,5};
for(int i:arr){
System.out.println(i);
}
数据结构:
队列 Queue
先进先出(FIFO)First Input First Output
Queue 重用的子类实现LinkedList
LinkedList 实现了集合 也实现了队列
也支持泛型
Deque 双端队列==》栈
是Queue的子接口
双进双出
使用双端队列时,若只允许元素都一个方向进出,就实现了栈
栈有良好的实力追溯性
先进后出FILO(First Input Last Output)
就像子弹夹
浏览器上的前进和后退
Comparable 接口
在对数组或集合元素进行排序时,首先要确定比较大小,有了结论才可以进行排序,而如何比较大小则需要实现该接口 并实现compareto方法
需要实现 compareTo方法
返回值不在乎集体的值 只关心取值的范围
>0 当前对象比给定的对象大
<0 当前对象比给定对象小
=0 当前对象和给定对象相等
compareTo方法的返回值应该与equals 方法的返回值具有一致性
当两个对象的equals 方法返回true时 compareTo方法应该返回0
Collections 集合的工具类
sort方法 用于排序集合 会调用compareTo方法
java 中的很多类都实现了Comparable 接口
想要自定义比较规则:
sort(Collections c,Comparator com)
比较器
用来定义比较规则
不适用集合中元素自身的比较规则,而是使用自己提供的比较器中的比较规则静静比较后再进行排序
Map 接口
Map 接口定义idea集合包含两个部分
key-value 以键值对的形式保存元素,可以把map看作是一个多行两列的表格
HashMap TreeMap
在Map中,key 是不重复的
异常
ERROR
jvm 级别的错误
栈内存溢出
Exception
程序级别的错误
通过捕获机制来解决
catch语句是用来捕获try语句中出现 并针对该异常解决,catch语句块可以出现多次
捕获异常:应该在最后一个catch 中加入Exception 可以保证程序不会因为没有捕获到一个未知的异常而中断, 而且这个Exception 应该放在所有catch 的最后一个..
try{
}catch(){
}finally{
}
finally出现在try语句的最后
finally块中的语句是必然执行的无论try中是否出现异常
用于收尾工作
throws 抛出异常
thorws 声明
在当前方法中出现异常,但是处理这个异常的责任不是当前方法管,这时候就把异常抛出去
谁调用 谁来解决
当程序遇到满足语法要求,但是不符合业务逻辑的 也可以使用thorws 一个异常
通常情况下方法中 throw一个异常实例我必须处理这个异常 处理的方式有两种
1,为throw 添加try{}catch(){}
2,在当前方法是声明该类异常的抛出,通知调用者处理该异常
我们定义的方法中可能会出现错误,无论是否为我们主动抛出的,但只要是方法中出现的异常不在方法中处理的,我们通常在声明方法是同事申明可能会抛出的异常,通知调用者必须捕获
java 文件操作
File类
用于描述操作系统中的一个文件或者目录通过File 可以得知文件的名字,大小,修改时间等信息但是不能读物文件的内容
描述文件路径时,尽量使用相对路径,便于跨平台的使用
. 表示当前目录,这个目录就时当前项目的根目录
File file = new File("."+File.separator+"1.txt");
创建目录需要两部
使用File 对象描述要创建的目录
通过File 对象的方法创建目录
File file = new File("."+File.separator+"asdf");
file.mkdir();
File sub = new File(dir,"sub");
sub.mkdir();
File file2 = new File("."+File.separator+"asdf"+File.separator+"asdf"+File.separator+"asdf"+File.separator+"asdf"+File.separator+"asdf"+File.separator+"asdf");
file.mkdirs();
File file3 = new File("."+File.separator+"lmdtx.txt");
try{
file3.createNewFile();
}catech(Exception e){
}
package se.day001;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class Demo18 {
public static void main(String[] args){
File file = new File("."+File.separator+"zxzx");
Scanner con = new Scanner(System.in);
if(file.exists()){
System.out.println("file is exists,will delete this file(Y/N):");
if("Y".equals(con.nextLine())){
file.delete();
System.out.println("fils delete");
file.mkdir();
System.out.println("file mk");
}else{
System.out.println("no del");
}
}else{
file.mkdir();
}
File file2 = new File("."+File.separator+"file.txt");
try {
file2.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package se.day001;
import java.io.File;
import java.io.IOException;
public class Demo17 {
public static void main(String[] args){
File file = new File("."+File.separator+"zxzcv.txt");
if(file.exists()){
System.out.println("have");
}else{
System.out.println("cretae file ");
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package se.day001;
import java.io.File;
import java.io.IOException;
public class Demo16 {
public static void main(String[] args){
File dir = new File("."+File.separator+"asdf");
if(dir.exists()){
System.out.println("have this dir,can not make");
try {
System.out.println(dir.getCanonicalPath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
dir.mkdir();
}
File sub = new File(dir,"sub");
if(sub.exists()){
System.out.println("have");
}else{
sub.mkdir();
}
}
}
package se.day001;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Demo15 {
public static void main(String[] args){
File file = new File("."+File.separator+"ttt.txt");
if(file.exists()){
System.out.println("yes");
}else{
System.out.println("no");
}
if(file.isFile()){
System.out.println("File");
}else{
System.out.println("noFile");
}
if(file.isDirectory()){
System.out.println("dir");
}else{
System.out.println("noDir");
}
System.out.println(file.getName());
System.out.println(file.length());
System.out.println(file.getPath());
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(file.lastModified())));
System.out.println(file.getAbsolutePath());
try{
System.out.println(file.getCanonicalPath());
}catch(Exception e){
System.out.println("no this ");
}
if(file.canRead()){
System.out.println("can read");
}else{
System.out.println("can not read");
}
if(file.canWrite()){
System.out.println("can write");
}else{
System.out.println("can not write");
}
if(file.canExecute()){
System.out.println("can exe");
}else{
System.out.println("can not exe");
}
}
}
package se.day001;
import java.io.File;
public class Demo19 {
public static void main(String[] args){
File src = new File(".");
String[] subFileName = src.list();
for(String sub:subFileName){
System.out.println(sub);
}
File[] subs = src.listFiles();
for(File sub:subs){
System.out.println(sub.getName()+":"+sub.length());
}
}
}
若给定的File对象是一个目录要先将子项全部删除后才能删除它
递归调用,删除给定的子项File
package se.day001;
import java.io.File;
public class Demo20 {
public static void main(String[] args){
File dir = new File("."+File.separator+"aa");
if(dir.exists()){
delFile(dir);
System.out.println("del all ");
}else{
System.out.println("no this dir");
}
}
public static void delFile(File file){
if(file.isDirectory()){
File[] subFiles = file.listFiles();
for(File subFile:subFiles){
delFile(subFile);
}
}
file.delete();
}
}
文件过滤器
接口
RandomAccessFile
用于读写文件内容的类
java 中文件模型
数据在硬盘中保存的形式是byte by byte
读写文件实际上就是读写字节
创建RandomAccessFile
RandomAccessFile(File file,String mode)
mode :
rw 读写
r 只读
一次写一个字节
8位
File file = new File('.'+File.separator+"xxxxxxxx.log")
RandomAccessFile raf = new RandomAccessFile(file,"rw");
raf.write('a');
int max = Integer.MAX_VALUE;
raf.write(max>>>24);
raf.write(max>>>16); ==> raf.writeInt(Integer.MAX_VALUE);
raf.write(max>>>8); ==>
raf.write(max);
8个基本类型都有
写字符串
给write 一个byte 数组也是可以得
按照utf-8;
String str = "my name is lmdtx";
byte[] data = str.getBytes("utf-8");
raf.write(data);
raf.close();
通常在写字符串的时候,不是直接把字符串转换的字节先写出去,而是要先写一个整数,这个整数表示后面将要写的字符串的总字节量,这样便于读取,否则在读取的时候无法确定读取多少个字节才能完整的读取所有字符串
读取
读取一个字节 以 int 形式返回
当返回值为-1的时候 读取到文件的末尾
该int值 只有低8位有效
File file = new File('.'+File.separator+"xxxxxxxx.log");
RandomAccessFile raf = new RandomAccessFile(file,"r");
char a = (char)raf.read();
int num = 0;
int i = raf.read();
num = (i<<24)|num;
i = raf.read();
num = (i<<16)|num;
i = raf.read();
num = (i<<8)|num;
i = raf.read();
num = i|num;
System.out.println(num == Imteger.MAX_VALUE);
int max = raf.readInt();
System.out.println(num == max);
raf.close();
读取字符串
int read(byte[] data)
一次性读取data数组长度的字节量,并存入该数组中,
返回值为实际读取到的字节量
若返回值为-1 读取到了文件末尾
byte[] data = new byte[raf.readint()];
raf.read(data);
String str = new String(data,"utf-8");
System.out.println(str);
raf.close();
读取写入utf-8
File file =new File("123.txt");
RandomAccessFile raf = RandomAccessFile(file,"rw");
raf.writeUTF("asdjasdfkl aihf oh asd ");
raf.seek(0);
String str = raf.readUTF();
System.out.println(str);
读取文件是游标
RandomAccessFile raf =new RandoAccessFile(file,"rw");
raf.seek(0);
输出游标位置
raf.getFilePointer()
从一个文件中读一个字节并写入到第二个文件中 ==》复制文件
创建一个File 对象用于描述要复制的文件
并用一个RandomAccessFile 读取
在创建一个新的File对象描述复制后的文件
并再用一个RandomAccessFile 写入数据
int data = -1;
while((data = src.read())!=-1){
desRaf.write(data);
}
使用缓冲的方式复制
创建应给File对象用于描述要复制的文件
并用一个RandomAccessFile 读取
在创建应给新的File对象描述复制后的文件
并再用一个RandomAccessFile写入数据。不过这里使用数组的方式写入
byte[] buf = new byte[1024 * 10];
ine len =0;
while((len = srcRaf.read(buf))>0){
desRaf.write(buf,0,len);
}
流
Java中的IO
输入流与输出流
InputStream
输入流
用于从外界读取数据到程序中
OutputStream
输出流
用于将程序中的数据发送到外界
对于程序
进入程序的是Input 读入
从程序出去的Output 写出
java中的流分为
低级流:节点流
数据的来源和去向是明确的
高级流:处理流,过滤流
高级流不能独立存在,通常基于一个流进行工作,使用高级流可以简化我们的读写操作
根据读写数据的单位通常划分为
字节流
以字节为单位读写数据
字符流
以字符为单位读写数据
java.io中输入流和输出流的父类
java.io.InputStream
这是一个抽象类,不能实例化,是所有输入流的父类
其中定义了读取数据的相关方法
java.io.OutputStream
这是一个抽象类,不能实例化,是所有输出流的父类
其中定义饿了写出数据的相关方法
FIS 与FOS
文件字节输入输出流
FileInputStream
用于读取文件的字节流
File file = new File("xxxx");
FileInputStream fis = new FileInputStream(file);
fis.read();
FileOutpputStream
用于向文件写数据的字节流
FileOutputStream fos = new FileOutputStream("xxxxx");
fos.write();
向文件中追加内容
File file = new File("xxxxx");
RandomAccessFile raf = new RandomAccessFile(file,"rw");
raf.seek(file.length());
raf.writeUTF("hihihihihihihihihihihiihihihi");
raf.close();
使用流的时候 就是后面添加一个true 就是在文件中追加内容,只要使用这个流就是追加
FileOutputStream fos = new FileOutputStream("20160722-2",true);
String str = "123123123123";
byte[] data = str.getBytes("UTF-8");
fos.write(data);
fos.close();
具有缓冲功能的输出流 是高级流
加快了读写效率
BIS 和BOS
BufferedInputStream
缓冲字节输入流
File file = new File("xxxxxx");
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read();
BuffedOutputStream
缓冲字节输出流
FileOutputStream fos = new FileOutputStream("xxxx");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write();
强制刷新
bos.flush();
将一个数据转化为对应的字节
这个过程 =》 序列化
将数据写入硬盘做长久保存的过程 =》 数据持久化
将字节转换为数据的过程 反序列化
用于读写基本类型数据的流 8个基本
DataInputStream
File file = new File("xxxx");
FileInputStream fis = new FileInputStream(file);
DataInputStream dis = new DataInputStream(fis);
DataOutputStream
FileOutputStream fos = new FileOutputStream("xxxxx");
DataOutputStream dos = new DataOutputStream(fos);
dos.writeInt(123);
dos.writeChar('a');
dos.writeUTF("123123");
dos.writeDouble(123.123);
字符流
读写以字符为单位
字符流的父类
java.io.Reader
java.io.Writer
读写数据都是基于字节的,所已字符流都是高级流
文本信息
子类实现
InputStreamReader
File file = new File("xxx");
FileInputStream fis = new FileInputStream(file);
InputStreamReader reader = new InputStreamReader(fis);
int c = -1;
while((c=reader.read()) != -1){
System.out.println((char)c);
}
reader.close();
连续读取2个字节(1个字符),并以int 形式返回
所以该int值低16位有数据
若返回值为-1 表示EOF
OutputStreamWriter
FileOutputStream fos = new FileOutputStream("xxxx");
OutputStreamWriter writer = new OutputStreamWriter(fos);
writer.writer('A');
char[] chs = {'1','2','3','4','5'};
writer.writer(chs,2,3);
writer.close();
package se.day001;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Demo42 {
public static void main(String[] args) throws Exception{
File srcFile = new File("."
+File.separator+"src"
+File.separator+"se"
+File.separator+"day001"
+File.separator+"Demo40.java");
FileInputStream fis = new FileInputStream(srcFile);
InputStreamReader reader = new InputStreamReader(fis);
File desFile = new File("20160725-5");
FileOutputStream fos = new FileOutputStream(desFile);
OutputStreamWriter writer = new OutputStreamWriter(fos);
char[] chs = new char[1024*5];
int len = -1;
while((len = reader.read(chs)) > 0){
writer.write(chs,0,len);
}
reader.close();
writer.close();
}
}
缓冲字符输入输出流
以行为单位读写字符
BufferedReader
缓冲字符输入流
br.readLine() 一次读一行字符
连续读取字符,知道去读到换行符为止,然后将换行符之前的字符组成字符串返回
返回值中是不包含换行符的
当返回值为null时表示EOF
BufferedWriter
缓冲字符输出流
bw.write(str);
bw.newLine(); 换行 就用这个 跨平台
穿重字符输入流质处理字符输入流
所以要先将细节输入流包装为字符输入流
package se.day001;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Demo43 {
public static void main(String[] args) throws Exception{
File srcFile = new File("."
+File.separator+"src"
+File.separator+"se"
+File.separator+"day001"
+File.separator+"Demo40.java");
FileInputStream fis = new FileInputStream(srcFile);
InputStreamReader reader = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(reader);
FileOutputStream fos = new FileOutputStream("20160725-7");
OutputStreamWriter writer = new OutputStreamWriter(fos);
BufferedWriter bw = new BufferedWriter(writer);
String str = null;
while((str= br.readLine())!=null){
bw.write(str);
bw.newLine();
}
br.close();
bw.close();
}
}
用于读取文本文件的字符流
读取文本的时候使用系统默认的编码集,不能设置编码集,解决方法,不使用这个
使用InputStreamReader读取
FileReader
文件字符输入流
FileWriter
文件字符输出流
InputStreamReader 有一个重载的构造方法支持指定特殊的编码集读取文本文件
InputStreamReader(FileInputStream file,String charset)
package se.day001;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
public class Demo45 {
public static void main(String[] args) throws Exception{
String str = "哈哈哈哈哈哈哈哈哈 ?";
FileOutputStream fos = new FileOutputStream("20160725-9");
byte[] data = str.getBytes("UTF-8");
fos.write(data);
fos.close();
}
}
package se.day001;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class Demo47 {
public static void main(String[] args) throws IOException{
FileInputStream fis = new FileInputStream("20160725-9");
InputStreamReader inReader = new InputStreamReader(fis,"UTF-8");
int chr = -1;
while((chr = inReader.read())!=-1){
System.out.print((char)chr);
}
inReader.close();
}
}
PrintWriter
带自动刷新的缓冲字符输出流
常用的构造方法
PrintWriter(File file)
创建一个像给定文件写数据的PrintWriter
创建一个不自动行刷新的流
PrintWriter(OutputStream out)
创建一个不具备自动行刷新的基于给定字节输出流尽心写操作的PrintWriter
PrintWriter(OutputStream out,boolean autoFlush)
创建一个具备自动行刷新的基于给定字节输出流进行写操作的PrintWriter
字符
PrintWriter(Writer w)
PrintWriter(Writer w,boolean autoFlush)
PrintWriter(String FilePath)
根据给定的文件路径,创建基于该文件进行写操作的PrintWriter
package se.day001;
import java.io.PrintWriter;
public class Demo48 {
public static void main(String[] args)throws Exception{
PrintWriter pw = new PrintWriter("pw20160725");
pw.println("随便写点什么东西,给你看看吧");
pw.println("再来一点东西,快看");
pw.close();
}
}
package se.day001;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
public class Demo49 {
public static void main(String[] args) throws FileNotFoundException{
File file = new File("file20150725");
PrintWriter pw = new PrintWriter(file);
pw.println("哈哈哈哈哈哈哈");
pw.println("在来一发");
pw.close();
}
}
package se.day001;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
public class Demo49 {
public static void main(String[] args) throws FileNotFoundException{
FileOutputStream out = new FileOutputStream("pw201607252.txt");
PrintWriter pw = new PrintWriter(out);
pw.println("和吱吱吱吱吱吱");
pw.println("快了快了快了快了");
pw.close();
}
}
package se.day001;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
public class Demo49 {
public static void main(String[] args) throws FileNotFoundException{
FileOutputStream out = new FileOutputStream("pw201607253.txt");
PrintWriter pw = new PrintWriter(out,true);
pw.println("和吱吱吱吱吱吱");
pw.println("快了快了快了快了");
}
}
写LOG的简单方法:
package se.day001;
import java.io.File;
import java.io.PrintStream;
public class Demo50 {
public static void main(String[] args) throws Exception{
System.out.println("HelloWorld");
File file = new File("20160726.log");
PrintStream ps = new PrintStream(file);
ps.println(" write in file");
//保存针对控制台的输出流
PrintStream out = System.out;
//将创建的输出流设置给System
System.setOut(ps);
System.out.println(" i come ");
//还原原来的输出流
System.setOut(out);
ps.close();
}
}
简单的控制台输入
package se.day001;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Demo51 {
public static void main(String[] args)throws Exception{
InputStream in = System.in;
//想读取字符串,就先将其转为字符输入流
InputStreamReader reader = new InputStreamReader(in);
//转换为可以按行读取的缓冲字符输入流
BufferedReader br = new BufferedReader(reader);
String str = null;
//readLine() 方法会卡住,直到输入回车,才会将之前输入的内容
//作为一个字符串返回
//键盘数据是源源不断的,不像文件有尽头,所以
//while循环是永远不会停的
while((str = br.readLine()) != null){
if("exit".equals(str)){
System.out.println("bye");
break;
}
System.out.println("输入的是:"+str);
}
}
}
命令行 记事本
package se.day001;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class Demo51 {
public static void main(String[] args)throws Exception{
InputStream in = System.in;
//想读取字符串,就先将其转为字符输入流
InputStreamReader reader = new InputStreamReader(in);
//转换为可以按行读取的缓冲字符输入流
BufferedReader br = new BufferedReader(reader);
FileOutputStream fos = new FileOutputStream("20160726-1.log");
PrintWriter pw = new PrintWriter(fos,true);
String str = null;
//readLine() 方法会卡住,直到输入回车,才会将之前输入的内容
//作为一个字符串返回
//键盘数据是源源不断的,不像文件有尽头,所以
//while循环是永远不会停的
while((str = br.readLine()) != null){
if("exit".equals(str)){
System.out.println("bye");
break;
}
pw.println(str);
}
pw.close();
br.close();
}
}
可以对 对象 进行序列化与反序列化的流
ObjectInputStream
读取字节并转换为对象输入流(反序列化)
ObjectOutputStream
将对象转换为字节后并写出的流(序列化)
需要序列化的类需要实现这个接口,这个接口就是一个标记
implements Serializable
当摸个属性被transient 修饰,那么该属性在序列化过程中被忽略
在反序列化时得不到原来的值
private transient int sex;
package se.day001;
import java.io.Serializable;
public class Person implements Serializable{
private String name;
private int age;
private transient int sex;
public Person(String name,int age,int sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public void setSex(int sex){
this.sex = sex;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public int getSex(){
return sex;
}
}
package se.day001;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class Dem052 {
public static void main(String[] args) throws Exception {
Person p = new Person("lmdtx", 18, 1);
//创建写文件的字节输出流
FileOutputStream fos = new FileOutputStream("person20160726");
//创建可以序列化对象输出流
ObjectOutputStream oos = new ObjectOutputStream(fos);
//将给定的Person对象序列化后写入文件中
oos.writeObject(p);
oos.close();
}
}
package se.day001;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class Demo53 {
public static void main(String[] args)throws Exception{
//创建用于读取保存着对象字节的文件的输入流
FileInputStream fis = new FileInputStream("person20160726");
ObjectInputStream ois = new ObjectInputStream(fis);
Person p = (Person)ois.readObject();
System.out.println(p.getName());
System.out.println(p.getAge());
System.out.println(p.getSex());
ois.close();
}
}
java语言的一个优势就是处理多线程比较简单
每一个程序都是 I C O
输入 I
计算 C
输出 O
一般操作系统都支持同时执行多个程序,那么每个同事运行的程序对操作系统而言称为一个进程
而对于一个程序而言,内部也可能同时运行多个任务,那么每个同时运行的任务称为一个线程
无论是进程还是线程,任务都是并发运行的,而不是纯粹的同时运行 具体的看操作系统原理
创建线程的步骤
定义一个类,并继承Thread类
Thread类是线程类,七种定义这操作线程的相关方法
重写run方法,该方法中应该定义的内容就是要并发运行的代码
实例化线程并启动
(有一个弊端,就是定义线程的时候就决定该线程要运行的任务,尽可能避免线程与执行的任务关联性太强)
并发的执行过程
当一个线程条用了start() 方法,该线程纳入线程调度机制,得以并发运行
package se.day001;
public class Demo55 {
public static void main(String[] args){
Thread t1 = new Person1();
Thread t2 = new Person2();
//启动线程不能去调用run方法,而是要调用start()方法
//否则两个线程不是并发运行的
t1.start();
t2.start();
}
}
class Person1 extends Thread{
public void run(){
for(int i = 0;i<1000;i++){
System.out.println("who are you? count:"+i);
}
}
}
class Person2 extends Thread{
public void run(){
for(int i = 0;i<1000;i++){
System.out.println("I am xxx count:"+i);
}
}
}
任务是任务,线程是线程,线程只关心可并发运行即可,给什么任务就并发运行什么任务
package se.day001;
public class Demo56 {
public static void main(String[] args){
Runnable p3 = new Person3();
Runnable p4 = new Person4();
Thread t3 = new Thread(p3);
Thread t4 = new Thread(p4);
t3.start();
t4.start();
}
}
/**
* 定义一个类并实现Runnable接口并重写run方法
* run方法中定义线程中药执行的代码
*/
class Person3 implements Runnable{
public void run(){
for(int i = 0;i<1000;i++){
System.out.println("who are you? count:"+i);
}
}
}
class Person4 implements Runnable{
public void run(){
for(int i = 0 ;i<1000;i++){
System.out.println("I am xxx count:"+i);
}
}
}
package se.day001;
/**
* 匿名的方式创建线程
*
*/
public class Demo57 {
public static void main(String[] args){
Thread t5 = new Thread(){
public void run(){
System.out.println("one");
}
};
Thread t6 = new Thread(new Runnable(){
public void run(){
System.out.println("two");
}
});
t5.start();
t6.start();
}
}
线程中常用的方法
static void sleep(long time)
让当前线程进入睡眠阻塞time 毫秒,当时间消耗完毕后,线程重写回到runnable
Thread.sleep(1000);
void interrupt()
中断线程
返回当前运行的线程 谁调用它,它返回谁
Thread.currentThread();
用于获取当前线程的名字,这个名字是系统分配的
也可以自己定义
getName()
一个方法的局部内部类中要引用该方法的 其他局部变量那么这个变量必须是final的
package se.day001;
public class Demo59 {
public static void main(String[] args){
final Thread l = new Thread(new Runnable(){
public void run(){
System.out.println("zzzzzzz");
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
System.out.println("狗蛋,别闹");
//e.printStackTrace();
}
}
});
Thread h = new Thread(new Runnable(){
public void run(){
System.out.println("老大,别睡了");
for(int i = 0;i<5;i++){
System.out.println("有妹子");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("妹子都要走了");
l.interrupt();
}
});
l.start();
h.start();
}
}
设置优先级
final void setPriority(int p)
1-10
有对应的常量
MAX_PRIORITY 10
NORM_PRIORITY 5
MIN_PRIORITY 1
每一个线程都会分配一个优先级NORM_PRIORITY
守护线程(后台线程)
当一个进程中所有前台线程运行完毕后,所有后台线程均要强制结束
进程的结束
当一个进程中的所有线程结束后,该进程结束
设置后台线程的方法要在该线程启动前调用
t1.setDaemon(true);
线程安全问题:
当多想成访问同一段数据时,机会引发现场安全问题
需要在访问数据的地方保证同步操作,就是要由先后顺序,不能同时访问
synchronized 同步锁
当synchronized 关键字修饰方法时,该方法变成同步方法,多个线程不能同时执行该方法
当修饰方法时,那么锁对象就当前对象,就是给this 上了个锁
当一个类中声明的多个方法均被synchronized 修饰,那么这些方法是互斥关系,同一个时间不可能被同事调用
如果所有的操作均都对方法进行同步,显然效率底下,在方法中,有时只有部分代码需要同步,这时候我们只需要同步这部分就好了,这样可以提高同步效率
synchronized(同步监视器){
}
同步监视器就是要上锁的对象
通常使用的同步监视器(上锁的对象)是this
要保证需要同步的代码库上锁的对象多个线程都能够看到,才可以保证同步
package se.day001;
public class Demo63 {
public static void main(String[] args){
final Shop shop = new Shop();
Runnable runnable =new Runnable(){
public void run(){
shop.bygGoods();
}
};
//创建 三个线程,同时调用bygGoods()方法
Thread t1 =new Thread(runnable);
Thread t2 =new Thread(runnable);
Thread t3 =new Thread(runnable);
t1.start();
t2.start();
t3.start();
}
}
class Shop{
public void bygGoods(){
System.out.println("tiao yifu");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {
System.out.println("tiao hao le ,shishi yifu");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("jie zhang zou ren ");
}
}
线程安全 与 不安全的类
StringBuffer(安全)
StringBuilder(不安全)
Vector(安全)
ArrayList(不安全)
Hashtable(安全)
HashMap(不安全)
所有的集合都支持一个以参数为Collection的构造方法
这个构造方法的作用可以在创建当前集合的基础上,将给定的集合元素放入其中,这个构造方法通常习惯叫他为:集合的复制构造器
List list = new ArrayList();
list.append("1");
list.append("2");
list.append("3");
List vector = new Vector(list);
使用Collections 的方法,可以方便的将一个集合变成线程安全的
List syncList = Collections.synchronizedList(list);
set
set syncSet = Collections.synchronizedSet(hashset);
map
Map<String,Integer> syncMap = Collections.synchronizedMap(map);
很多应用中都需要使用多线程,
当一个线程要完成的工作需要基于另一个线程的工作情况时,我们则需要两个线程协调工作
在Object 中 定义的:
wait() 在当前线程上等待
通过调用一个对象的wait()方法后,那么这个线程就在当前线程上等待,进入了等待阻塞
他和sleep 的区别在于
sleep() 阻塞会在指定时间消耗完毕后自动回到runnable状态
wait() 阻塞则不会自动回到runnable 直到调用了这个对象的notify方法,当前线程才回到runnable状态
wait() 在谁身上等,就要锁谁 synchronized(){}
notify() 通知一个在当前线程上等待的线程运行
this.notify() 通知在他身上等待的的解除等待阻塞
也是要加锁的 synchrized(this){}
notifyAll() 一个对象身上可以有多个对象在等待 notify() 只能随机的唤醒一个
如果要所有的都唤醒 就使用notifyAll()
package se.day001;
public class Demo64 {
public static boolean finish = false;
public static void main(String[] args){
final Thread downThread = new Thread(new Runnable(){
public void run(){
for(int i = 0;i<100;i++){
System.out.println(i+"%");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("下载完成");
finish = true;
synchronized (this) {
this.notify();
}
}
});
Thread displayThread = new Thread(new Runnable(){
public void run(){
System.out.println("等待下载图片的线程通知");
try {
synchronized (downThread) {
downThread.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
if(!finish){
throw new RuntimeException("图片没有下载完毕,无法显示图片");
}
System.out.println("显示");
}
});
downThread.start();
displayThread.start();
}
}
线程池
使用 线程池
ExecutorService 实现线程池
是java 提供的用于管理线程池的类
作用
控制线程数量
重用线程
当一个程序中若创建大量线程,病在任务结束后销毁 会给系统带来过度的消耗资源,以及过度切换线程德危险 从而可能导致系统崩溃为此我们应该使用线程池来解决这个问题
Executors.newCachedThreadPool()
创建一个可根据需要穿创建新线程的线程池,但是在以前构造的线程可用时将重用他们
弹性比较好,可以 满足 瞬间 激增的 有宕机的风险
Executors.newFixedThreadPool(int nThreads)
创建一个可重用固定线程集合的线程池,以共享的***队列方式来运行这些线程
Executors.newScheduledThreadPool(int corePoolSize)
创建一个线程池,他可安排在给定延迟够运行命令或者定期的执行
Executors.newSingleThreadExecutor()
创建一个使用单个worker 线程德Executor 以***队列方法来运行该线程
单线程模式 等于 Executors.newFixedThreadPool(1)
public class Demo65 {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(2);
for(int i = 0;i<10;i++){
Runnable runn = new Runnable(){
public void run(){
for(int i = 0;i<10;i++){
System.out.println(i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
};
threadPool.execute(runn);
}
}
}
网络基础
java网络开发
Socket套接字
网络应用的模式
C/S 客户端对服务器端
客户端都是根据需要制定的有特定的传输协议
可以为用户提供更准确的需要,更好的效果,
但是对于更新和维护来讲,需要影响用户所以维护和更新是弊端
B/S 浏览器对服务器端
通信协议一致的特殊C/S结构应用
服务端创建一个
ServerSocket 服务器端套接字
调用accept()方法来等待客户端来连接
客户端 创建一个Socket 请求与服务端建立连接
Socket
服务端接收客户端的连接请求,同时创建一个新的Socket与客户端建立连接,服务端继续等待新的请求