1.String
1.新建对象
常量池(方法区)
1
String str="x";
新创建
1
Stirng str=new String("x");
区别
常量池
创建是在现有堆中查找是否有相同的内容,如果有指向同一数据;新创建
中则忽略先在常量池中创建再在新堆中创建,指向的内容不相等;先在新堆中创建,再在常量池中查找(此时的常量池就是刚创建的新堆)指向的内容相同;
1
2
3String str1="x";
String str2=new String("x");
syso(str1==str2);//输出flase;1
2
3String str1=new String("x");
String str2="x";
syso(str1==str2);//输出true;常量池中创建是在一个堆中,而新堆创建是在两个堆中
1
2
3String str1="x";
String str2="x";
syso(str1==str2);//输出true;1
2
3String str1=new String("x");
String str2=new String("x");
syso(str1==str2);//输出flase
2.相关方法
检索str的位置
没有检索到返回
-1
;检索第一次出现str的位置:
1
int x = indexOf(str);
检索从n开始出现str的位置:
1
int x = indexOf(str,n);
检索最后一次出现str的位置;
1
int x = LastIndexOf(str);
获取指定位置字符串
获取从n1到n2的字符串
1
String str = str.substring(n1,n2);
获取从n开始到结尾的字符串
1
String str = str.substring(n);
获取位置n上的字符串
1
String str = str.charAt();
去除字符串前后的空字符串
1
String str = str.trim();
查询是否存在
以str2开头的字符串
1
boolean b = str.startsWith(str2);
以str2结尾的字符串
1
boolean b = str.endsWidth(str2);
正则表达式方法
是否存在正则表达式相配数据
1
boolean b = str.matches(“正则表达式”);//true:相同
将一个字符串拆分成字符串数组
1
String[] b = str.split(正则表达式);
将字符串的一部分用于替换
1
String b = str.replaceAll(正则表达式,被替换);
3.StringBuffer/Builder
String是不可变的(被final修饰);
1
2String str="1";
str=str+"2";流程:JVM创建第一个str对象并赋值”1”,创建第二个str并赋值”12”,GC垃圾回收机制处理掉第一个str
StirngBuffer是可变的
StringBuffer是线程安全的,StringBuilder是线程不安全的;StringBuilder是性能最好的;
2.集合
1.基础知识
数组和集合的区别
- 数组长度不可变,集合的长度可变;
- 数组无法保存具有映射关系的数据;
- 数组可以保存基本数据和对象,集合只能保存对象(对象的引用变量);
所属包:
java.util(工具类,java5以后再java.util.concurrent包下提供线程安全集合类)
包含类:
- Collection:接口类,集合框架的根接口
- Map:接口类,集合框架的根接口
2.Collection集合
1.基础知识
1.Collection
基础知识:
- collectoion是顶级父类接口;Set/List是子接口
- Collection接口派生的集合默认长度为0
关系图:
2.List和Set的区别
- List集合是序列(有序)的,允许元素重复;
- java.util.ArrayList:
- 内部由数组实现,查询效率好;
- 修改必须新建重新赋值;
- java.util.LinkedList:
- 内部由链表实现,增删效率好,尤其是首尾增删;
- 查询慢必须一个一个查询,修改快,只需要插入即可
- java.util.ArrayList:
- Set集合是散列(无序)的,不允许元素重复(若重复则只显示一个):
- 相同元素的标准:2个对象的equals()对比结果为true且hashCode()返回值相同
- 如果使用的实现类是
TreeSet
,还要求集合中的元素实现Comparable
接口。
3.Collection共有方法
新建对象:
set/array亦可
1
Collection<Integer> collection = new Collection<Integer>();
添加:
添加元素:
1
collection.add(1);
将集合2的数据复制到集合1中:
如果collection是list集合重复的数据只显示一份,set集合可以重复
1
collection.addAll(collection2);
删除:
删除元素:
1
collection.remove(1);
删除两个集合中相同的元素
1
collection.removeAll(collection2);
集合的大小
1
int size = collection.size();
空集
清空为空集
1
collection.clear();
检测是否为空集
1
boolean is = collection.isEmpty();
更改元素:将位置1的数值更改为2;仅适用于List
1
collection.set(1,2);
包含
判断集合中是否有1;
1
boolean contain = collection.contain(1):
判断C1中是否包含C2中的所有元素
1
boolean contains = collection.containAll(c2);
2.遍历集合
1.Iterator
1.Iterator
属性:
位于顶级父类Collection中的方法;
遍历数组时里面不能使用集合的方法(多数情况下会报错)
执行读写删读写删操作;
步骤
创建集合
1
Collection c = new ArrayList();
返回一个迭代器,返回Iterator类型的对象
1
Iterator it = c.iterator();
遍历
遍历时别修改集合的值会报错
1
2
3
4while(it.hasNext()){ //判断是否还有下一个元素可以遍历
String o =(String)it.next();//将接收到的内容强制转换为String类型
it.remove(); //删除调用的集合 (此处不能使用集合的方法)
}
2.匿名内部类
原理
Iterable接口新增一个forEach()默认方法,Iterable接口是Collection接口的父接口
遍历
1
it.forEachRamaining(obj -> System.out.println("迭代集合元素:"+obj));
2.增强for
1.增强for
新循环是编译器认可的,编译器编译或将新循环遍历数组为普通for;
数组:
1
2
3
4
5
6
7
8for(int i = 0; i<arr.length;i++) {
String str = arr[i];
System.out.println(str);
}
for(String str : arr) {
System.out.println(str);
}
Arrys.toString(arr);集合:
新循环遍历集合会被编译器改为迭代器遍历(不需要返回一个迭代器了)
1
2
3
4
5
6
7
8for(Object o : c) {
String str = (String)o;
System.out.println(str);
}
Collection<String> c = new ArrayList<String>();//指定类型
for(String str : c) {
System.out.println(str);
}
2.匿名内部类
表达式
1 | books.forEach(obj -> System.out.println("迭代集合元素:"+obj)); |
3.Set
1.HashSet
当向HashSet集合中添加可变对象时,如果修改集合中对象,有可能导致对象与集合中的其他对象相同,从而导致HashSet无法准确访问该对象
添加规则
判定元素是否重复标准
- 比较两个元素的hashCode()方法返回的hashCode值,如果不相等则为合格;
- 两个元素进行equals()比较是否为同一对象,如果结果为flase则为合格;
- 以上两个只有有一个合格就可以添加成功,;
单个合格的缺点
- eualas合格,hashcode不合格:就会导致两个元素被分配到不同的hash值地址上,但是元素是相同的,与set规则不相符(元素不可以重复);
- hashcode合格,equals不合格:就会导致两个元素被分配到相同的hash值地址上,用链表的形式保存,因为查找元素是靠hash值,这样会导致查询速度变慢;
重写hashCode和equals规则
如果重写euals方法时就要重写hashCode;hashCode和equals都为合格或都为不合格
重写HashSet
HashSet计算公式:
通常只使用引用类型
计算Haash值
方法1:
1
2
3public int code(){
return f1.hashCode()*17+f2.hashCode()*31+...;
}方法2:
1
2
3
4
5
6
7public int code(){
int result = 17;
result = result * 31 + ((Book == null) ? 0 : Book.hashCode());
result = result * 31 + ((Name == null) ? 0 : Name.hashCode());
...
return result;
}方法3:
eclipse自动生成
2.linkedHashSet
- HashSet的子类,拥有HashSet的功能;
- 存储:
- 排序方式:按照集合元素的添加顺序;
- 存储位置:按照hash值存储
- 通过链表维护集合元素的顺序,是一个有序的set,不可重复
- add时性能略低与HashSet,遍历时性能略高于HashSet
3.TreeSet
基础知识:
- TreeSet是SortSet接口的实现类;SortSet是Set的子接口;
- 存储:
- 排序方式:按照集合内元素的大小排序;
- 存储位置:按照红黑树数据结构;
相关方法
返回第一个元素
1
treeSet.firset();
返回最后一个元素
1
treeSet.last();
元素的前一个元素
1
treeSet.last();
元素的后一个元素
1
treeSet.last();
返回t1和t2之间元素(以集合的形式)
1
treeSet set = subSet(t1,t2);
返回小于t的所有元素(以集合的形式)
1
treeSet set = headSet(t);
返回大于t的所有元素(以集合的形式)
1
treeSet set = tailSet(t);
排序方式:
基础知识:
- 要添加的元素最好是同一类型,否则会报错;
- 要添加的元素的实体类一定要有排序规则;
- 如果修改添加完的数据会导致大小顺序发生改变不会刷新,并且重复和修改的数据不能被删除
自然排序:
排序原理:调用元素的compareTo(Object obj)方法比较元素之间的大小,然后将元素升序排序;实现方法:
实体类实现
Comparable
接口,重写compareTo(Object obj)方法,定义排序规则;排序规则:
A1.compareTo(A2)返回值>0代表A1>A2;
A1.compareTo(A2)返回值<0代表A1<A2;
A1.compareTo(A2)返回值=0代表A1=A2;
排序公式:
1
2
3
4
5
6
7
8class student() implements Comparable{
private String name;
private Integer id;
public int compareTo(Studnet student){
return id-student.id;
return id-student.id>0?1:id-student.id<0?-1:0;
}
}
定制排序:
排序原理:ThreSet的自然排序是根据集合元素的大小,TreeSet将他们以升序排列;在新建TreeSet对象时,传入一个实现Comparator接口并重写compare(T1,T2)方法的对象,在compare中重新定义排序规则
排序公式
1
2
3new TreeSet((School s1,School s2)->{
return s1.getId()-s2.getId();
});
4.EnumSet
枚举类
4.List
1.基础知识
属性:
有序列表HashSet不继承List;
实现类:
- 一般使用ArrayList
方法(不包括collection)
List list = new ArrayList();//括号内可以传入一整个集合
将位置2添加新元素12
1
list.add(2,”2”);
将位置2删除
1
list.remove(2);
将位置2更新为3
1
list.set(2,”3”);
获取位置2
1
list.get(2);
生成list的[3,8)的子集subList
1
List.subList=list.subList(3,8);
将生成的子集删除(子集修改父集也会被删除)
1
list.subList(3,8)clear();
2.转换
集合转换数组
toArray是Collection的方法,他的子类也可以使用;
1
2Collection c = new ArrayList();
String[] array = c.toArray(new String[c.size()]);c.size的长度没有达到数组该有的长度会补齐
数组转换集合
Arrays提供了一个静态方法asList,将数组转换为List集合
1
2
3String[] arr = {"one","two","three","four"};
List list = Arrays.asList(arr);
Arrays.toString(arr);
4.栈结构
队列:先进先出;//后进前出
所属类:
java.util.queue
父类:
Collection
实现类:
LinkedList
方法
1
2
3
4
5Queue<String> queue = new LinkedList<String>();
tring str = queue.poll();//将第一个输出(输出后在集合中消失)
依次输出:用i--;因为只有定义为初始值才不会改变;
str = queue.peek();//将第一个输出
queue.offer("a");//在后面添加一个数
双端队列:两端都可以输入输出;
所属类:
java.util.Deque
父类:
queue
实现类:
LinkedList
方法:
1
2
3
4deque.offerFirst();
deque.offerLast();
deque.pollFirst();
deque.polLast();
栈结构:再同 一端进入输出可用于前进后退功能
1
2queue.push();
queue.poll();
3.Map集合
新建map
1
Map map<String,String> = new Map<String,String>();
返回所有key
1
Set<String> keys = map.keySet();
返回所有value
1
Set<String> values = map.keyValue();
4.Collections
所属类:
java.util.Collections (Collection的集合工具类);
1.封装线程安全集合
Collection
1
2Conllection collection = new ArrayList();
collection = Collections.synchronizedList(list);List
1
2List list = new ArrayList();
list = Collections.synchronizedList(list);Set
1
2Set set = new HashSet(list);
set = Collections.synchronizedSet(set);SortedMap/Tree
SortedSet/Tree
2.List集合排序
自然排序
升序操作
1
Collections.sort(list);
自定义排序
Comparator:自然排序重写
1
Collections.sort(list,Comparator);
乱序
1
collections.shuffle(list);
翻转排序
1
collecions.reverse(list);
3.创建不可变集合
3.线程
1.注意事项
main方法也是一个线程
2.创建线程
建议使用Runnable或Callable
- 由于java里一个类只能继承一个父类,所以Thread只能继承一个父类,而runnable和callable可以继承多个父类
- runable和callable可以实现代码的分离,面向对象
- runable和callable代码复杂,获取线程对象要用Thread.currentThread()方法,而thread可以直接对象点;
1.继承Thread
新建线程:新建类继承Throw,重写run方法
1
2
3
4
5public class Test() extends Throw(){
public void run(){
线程需要执行的内容;
}
}创建线程:
1
Test test = new Test();
启动线程:创建一个新的栈,而不是创建栈帧
1
test.start();
2.实现Runnable
新建线程:新建线程类,实现Runnable接口,重写run方法
1
2
3
4
5public class Test implements Runnable{
public void run(){
线程内容;
}
}创建线程对象1
Test test = new Test();
新建线程
1
Thread thread = new Thread(thread[,"线程名"]);
执行线程
1
thread.start();
3.使用Callable和Future
新建线程:新建范方法线程类,实现Callable类,重写call方法
可以抛出异常而不需要必须在县城里处理1
2
3
4
5public class Test implements Callable<call方法返回值>{
public Integer call() throws Exception{
线程内容;
}
}新建线程对象
1
2Test test = new Test();
FutureTask<Integer> result = new FutureTask<>(test);执行线程
1
Thread thread = new Thread(result);
执行线程
1
therad.start();
返回值:get()会阻塞到结束时执行
1
2
3try{
Integer sum = result.get();
}catch(){}
4.其他方法创建
1.匿名内部类
Thread
1
2
3
4
5Thread thread = new Thread(){
public void run(){
}
}
thread.start();Runnable
1
2
3
4
5Thread thread = new Runnable(){
public void run(){
}
}
new Thread(thread.start());
2.Lambda表达式
当新建的线程类中只有一个方法时就可以使用Lambda表达式
5.Threa对象
获取线程对象(静态)
run方法内
只适用于实现Runnable或Callable的接口的run方法内执行
不能使用this,this指的是线程类这一个对象,而静态方法获取的是不同的三个对象
1
Thread thread = Thread.currentThread();
线程外获取对象
1
2Test test = new Test();
Thread thread = new Thread(test);
获取线程名
1
String name = thread.getName();
获取线程id
1
Int id = thread.getId()
获取线程优先级[见下文]
1
thread.getPriority();
检查是否处于活动状态[见下文]
线程处于:就绪/运行/阻塞返回
true
,处于新建/结束返回flase
;1
thread.isAlive();
检查是否为守护线程[见下文]
1
thread.isDaemon();
检查是否被中断
1
thread.isInterrupted();
3.生命周期
图表
状态 线程 新建 使用new关键字创建线程后 就绪 线程对象调用start()方法后 运行 获得cpu资源,执行run方法体后 死亡 run()结束/错误/执行stop() 图示
线程从阻塞状态只能进入就绪状态
注意事项
主线程和子线程:
主线程和子线程有相同的地位,子线程不收主线程的影响,主线程结束后子线程可以继续执行;
start()
对新线程两次调用start()或者对死亡的线程调用start()都会抛出异常
illegalThreadStateException
调用run()方法以后不能再次调用start()方法会抛出异常
4.控制线程
新建线程:
Thread/Runnable/Callable
1
2Test test = new Test();
Thread thread = new Thread(test);
1.join
因为阻塞后会处于就绪,因此.start()可以解除join
在therad2线程中调用thread.join()方法,therad2会被一直阻塞,直到therad执行完毕
1
thread.join();
在therad2线程中调用thread.join(n毫秒)方法,therad2会被一直阻塞n毫秒
1
thread.join(n);
2.后台线程(守护线程)
- 注意事项:
- 当前台线程全部执行完毕,守护线程也随之结束,jvm的gc就是守护线程,
- 线程处于:就绪/运行/阻塞返回
true
,处于:新建/结束返回flase
; - 前台线程创建的默认是前台线程,后台线程创建的线程默认是后台线程;
设置为后台线程
必须在thread.start()之前执行,否则返回
illegalThreadStateException
1
thread.setDaemon(true);
获取当前线程状态
1
boolean flag= thread.getDaemon();
3.sleep(线程休眠)
可能发生死锁,尽量少使用,run方法内执行
让thread线程休眠
1
Thread.sleep();
让thread休眠n毫秒(收系统精度影响)
1
Thread.sleep(n);
4.yield(线程让步)
移植性低,不建议使用,建议使用sleep
会将线程强制转换到就绪状态,而不是阻塞,在执行后会暂停并给大于等于自身优先级的线程(包括)执行机会,
1 | Thread.yield(); |
5.设置优先级
每个线程默认的优先级都与创建它的父线程优先级相同;
优先级级别
范围从1-10,但是由于要受操作系统的影响,所以应该尽量使用常量优先级
常量优先级
常量 级别 Thread.MAX_PRIORITY 10 Thread.MIN_PRIORITY 1 Thread.NORM_PRIORITY 5(main)
获取优先级
1
int x = thread.getPriority();
设置优先级
1
thread.setPriority(优先级);
5.线程同步
1.并发产生的原因
1 | int total2=2000 |
如果线程1在经过1时正好堵塞,线程2在此期间执行完毕,这时线程1再执行完毕则出现错误;也就是说有同时执行1的可能
2.同步代码块
参数是同步监视器:当一个线程使用obj
时阻止其他线程使用,直到代码块执行完毕
- 同步监视器:obj,需要竞争的对象资源
- 同步代码块:需要执行的操作
1 | synchronized(obj){ //加锁 |
3.同步方法
在自定义类中加同步方法:被synchronized修饰的方法,默认同步监视器是this就是当前对象;
1 | public synchronized void XXX(){ |
4.同步锁
在实现方法中书写同步锁:java8新功能,ReentrantLook可以被多次加锁
步骤
新建ReentrantLook(可重入锁)
1
private final Look look = new ReentranLook();
代码开头加锁
1
look.look();
finally中解锁
1
look.ulook();
案例
1
2
3
4
5
6private final ReentrantLock lock = new ReentrantLook();
public void x(){
look.look();
try{代码}
finally{look.unlook()};
}
5.死锁
在系统中出现多个同步监视器的情况下容易死锁;
6.同步监视器何时释放和锁定
- 释放同步监视器的锁定
- 同步方法或代码块执行结束
- 遇到break/return提前结束同步方法或代码块
- 出现未处理的error或Exption导致同步放那个发或代码块结束
- 执行了同步监视器对象的wait()方法,使当前线程暂停会释放监视器
- 不释放同步监视器的锁定(容易死锁)
- Thread.sleep()/Thread.yield()
- suspend()将线程挂起
6.线程通信
1.传统通信
相关方法:
Object的三种方法,仅适用于同步块和同步方法
当前线程等待,知道调用notify()或notifyAll();
1
wait();
唤醒在此同步监视器上等待的单个线程
1
notify();
唤醒在此同步监视器上等待的所有线程
1
notifyAll();
案例:
当程序进入draw2()存钱方法后,如果flag为true,表示账户中有人正在取钱,程序调用wait()方法阻塞存钱方法;反之如果flag为flase表示账户中没有人正在存钱此时执行存钱操作,最后将flag设置为true,并唤醒存钱期间被阻塞的取钱操作,被唤醒的取钱线程会执行取钱操作最后将flag设置为false,并唤醒取钱期间被阻塞的存钱操作;
注意事项:在类中设置flag默认为flase,所以直接执行取钱操作就会有问题;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30public class A{
private String ANo;//账户编号
private double price;//账户余额
private boolean flag = false;//true:有人正在取钱|false:有人正在存钱
get/set/toString(price只写get处于安全考虑)
public synchronized void draw(double price2){
try{
if(!=flag){
wait();
}else{
price = price - price2;
flag = false;
notifyAll();//唤醒其他线程;
}
}
}
public synchronized void draw2(double price2){
try{
if(flag){
wait();
}else{
price = price + price2;
flag = true;
notifyAll();//唤醒其他线程;
}
}
}
}
2.Condition通信
步骤
仅适用于同步锁
新建look对象
1
private final Look look = new ReentrantLook();
获得Condition对象
1
private final Condition conditon = Conlook.newCCondition();
await();
signal();
signalAll();
案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32public class A{
private String ANo;//账户编号
private double price;//账户余额
private boolean flag = false;//true:有人正在取钱|false:有人正在存钱
get/set/toString(price只写get处于安全考虑)
public void draw(double price2){
look.look();
try{
if(!=flag){
wait();
}else{
price = price - price2;
flag = false;
notifyAll();//唤醒其他线程;
}
}catch(){
}finally{
look.ulook;
}
}
public void draw2(double price2){
try{
if(flag){
wait();
}else{
price = price + price2;
flag = true;
notifyAll();//唤醒其他线程;
}
}
}
}
3.阻塞队列[待学]
7.线程组和未处理的异常
8.线程池
1.相关线程池
线程池 | 作用 | 注意事项 |
---|---|---|
newFixedThreadPool() | 固定数量线程池 | |
newCachedThreadPool() | 缓存线程池 | |
newScheduledThreadPool() | 周期性线程池 | |
newSingleThreadExecutor() | 单线程线程池 |
2.创建线程池
创建线程池
1
ExcutorService pool = Executors.线程池();
创建线程池
1
向线程池中提交线程(可提交多个)
1
pool.submit(target);
关闭线程池
1
pool.shutdown();
9.线程相关类
1.ThreadLocal
2.包装线程
3.线程安全
- 集合:详情请见Collections中
- Random—–ThreadLocalRandom
4.IO操作
1.File类
1.相关方法
新建对象,而不是文件(file为地址);
自定义地址创建
1
File file = new File("/demo");
在指定目录下创建[只在大量创建子目录时使用]
1
File file = new File(mkdir,"demo");
显示File信息
地址
1
2file;//方法1:直接输出file对象,不是String类型
String path = file.getPath();//方法2文件/目录名
1
String name = file.getName();
绝对地址=绝对名字
1
2File AbsoluteFile = file.getAbsoluteFile();//方法1
String absolutePath = file.getAbsolutePath();//方法2:absolluteFile().tostring();
检测
是否是目录或文件
1
boolean exists = file.exists();
是否是目录
1
boolean directory = file.isDirectory();
是否是目录
1
boolean file = file.isFile();
创建/删除
创建目录
1
mkdir.mkdir();//(父级目录必须存在,例如"A//b//,则A必须存在")
创建多级目录
1
mkdirs.mkdirs();//(腹肌目录不存在会一起创建)
创建文件(需要处理IOException)
文件可能被占用
1
file.createNewMkdir();
删除文件/目录
不能删除非空目录,见案例详述
1
file/mkdir.delete();
其他
文件/目录大小
1
long length = file/mkdie.length();
返回目录下的所有文件和目录地址
1
File[] list = mkdir.listFiles();
返回目录下的所有文件和目录名
1
String[] list = mkdir.list();
转换为nio的path对象
1
Path path = file.toPath();
临时目录
前缀最少3位数,并且是生成以前缀为开头的随机文件名
新建临时文件夹
1
File.createTempFile("前缀","后缀");
在指定目录下创建临时文件夹
1
File.createTempFile("前缀","后缀","指定目录");
案例(删除非空目录)
方法1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public static void delete1(File file) {
if (file.exists()) {
if (file.isFile()) {
file.delete();
} else {
File[] list = file.listFiles();
for (File file2 : list) {
file2.delete();
}
file.delete();
syso("删除完毕");
}
}else {
System.out.println("要删除的文件或目录不存在");
}
}方法2(return)迭代方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public static void delete2(File file) {
if(!file.exists()) {
return;
}else if(file.isFile()) {
file.delete();
return;
}else {
File[] files = file.listFiles();
for(File file2 :files) {
delete2(file2);
}
file.delete();
}
System.out.println("删除完毕");
}
2.FileNameFilter
函数式接口
实现方法:
- 新建类实现FileNamefilte,重写accept(File dir,String name)方法 dir:父目录,name:字文件目录名称
- 1中类返回满足的要求
案例
1
2
3
4
5
6public boolean accept(File dir, String name) {
boolean endsWith = name.endsWith(".f");
//name只有new File才能使用File的方法
//boolean directory = new File(name).isDirectory();
return endsWith;
}FileNameFilter与FileFilter的区别
- 传入参数不同,FileFilter也实现accept但是传入(File file)方法
- FileFilter不适用于
file.list()
方法
2.byte
字节换算
1KB=1024B=1byte(字节)=8bit(比特)
1B(字节)=8b(比特)
UTF-8
字符集 中文 英文 UTF8 3个字节 1个字节 GBK 2个字节 1个字节 byte[]转换
String转换为byte[]
1
byte[] bates = str.getBytes("字符集");
byte[]转换为String
1
String str = new String(bates,"字符集");
3.RandomAccessFile
1.基础知识
所属类
java.io.RandomAccessFile
作用:
进行文件的byte单字节读写
原理:
指针读取:
每写入1byte(字节),指针移动1个位置.
同一个raf对象指针的位置不重置为0的,如果要读取,要先raf.seek(0);
不同的raf默认指针位置为0再次写操作会覆盖写入的部分;
由于第一次写入1个String类型占3个字节,第二次写入一个int类型占2个字节,还剩余一个字节就会抛出
EOFException
异常1
2
3
4dyte[] dates = new dates[];
String str = new String ("x","字符集");
raf.seek();
raf.writeInt(1);
2.相关方法
创建对象
如何file为r,而选择rw访问模式则直接报错
r:读:如果写操作会抛出io异常
rw:读写:如果没有文件会尝试创建文件
1
RamdomAccessFile raf = new RamdomAccessFile(file,"rw");
写入
char/ASCII写入
1
read.write();
写入数组大小数据并导入数组中
1
read.write(dates);
写入数组n1-n2位置数据并导入数组中
1
read.write(dates,n1,n2);
int/double/其他类型
当读取到末尾时会抛出
EOFException
1
raf.writeInt();/raf.writeUTF();
UTF
虽然传入的是String类型内容,但是写入的是不同类型(“1”–int/“你好”–String)
1
raf.UTF("1");/raf.UTF("你好");
读取
char/ASCII读取(文档不乱码)
1
raf.read();
读取数组大小数据并导入到数组中
1
raf.read(dates);
int/UTF(不乱码)读取
1
raf.readInt();/raf.readUTF();
指针
单位是byte(字节)
当前指针位置
1
raf.getFilePoint();
指定指针位置
1
raf.seek(0);
当前总指针数/文件大小
1
raf.length();
关闭流
1
raf.close();
3.案例
1.String写入或读写
写入
1
2
3String str = "x";
byte[] bytes = str.getBytes(str,"字符集");
raf.write(bytes);读取
1
2
3
4raf.seek(0);
byte[] bytes = new byte[raf.length()];
raf.read(bytes);
String str = new String(bytes,"字符集");
2.ASCII和char写入或读写
写入
1
raf.write('a');/raf.write(49);
读取
1
2
3
4int code = -1;
while((code=raf.read()) != -1){
syso(code);
}Other写入或读写(readInt/readUTF)
写入
1
raf.writeInt(123);/raf.UTF("123");
读取
1
2
3while(raf.getFilePoint != raf.length()){
raf.read();
}
3.文件复制
1 | RandomAccessFile raf1 = null; |
5.Other
最后更新: 2019年11月06日 11:36