内部类和匿名类
内部类是指在一个类的内部定义其他类,称为内部类。
内部类:
-
内部类当中可以调用外部类当中的属性和方法,而外部类却不能调用内部类当中的。
-
内部类的类体中不可以声明类变量和类方法,内部类可以由外部类使用外部类中在函数中创建内部类对象来使用,如果内部类 的权限是非私有,非静态的,就可以在外部其他程序中被访问 到,就可以通过创建外部类对象完成;如果内部类是静态的,非私有的,静态成员可以直接类名调用,非静态成员通过创建外部类对象使用。
-
内部类的字节码文件会不一样。会变成外部类名$内部类名
匿名类:
-
匿名类,就是没有名称的类,其名称由Java编译器给出,一般是形如:外部类名称+$+匿名类顺序,没有名称也就是其他地方就不能引用,不能实例化,只用一次,当然也就不能有构造器。
-
匿名类就是利用父类的构造函数和自身类体构造成一个类。
-
格式 new 父类( ){子类内容};
上面格式中的“父类”是子类需要继承或者实现外部的类或者接口
-
匿名类可以继承父类的方法,也可以重写父类的方法。
-
匿名类可以访问外部类的成员变量和方法,匿名类的类体不可以声明称static成员变量和static方法。
-
匿名类由于是一个new的结果,所以其实可以赋值给一个父类对象。因此可以分为两种匿名类,成员匿名类和局部匿名类(作为函数参数)
匿名内部类:
-
匿名是因为匿名内部类的具体名字不会被我们在程序当众编写出来,因为它已经在主方法当中被实例化了。
-
匿名内部类可以继承两类数据结构:
一:抽象类
二:接口。
异常
异常就是程序在编译时发生的意想不到的情况,一般而言分为两类:错误(Error)和异常(Exception)
Exception异常分为编译时异常和运行时异常,由于我们无法预测程序里可能出现的错误或用户在使用程序时会出现的错误,所以需要异常类来告诉我们程序出现了异常
java 中的异常信息主要是调用 Throwable 的几个方法进行处理的,主要的方法有:
printStackTrace(),getMessage(),getStackTrace()方法。
异常的捕获:
异常的捕获需要用到try-catch语法结构
try…catch…finally 结构
该结构对异常捕获和处理的形式如下:
try{
//此处放可能产生错误的代码
}catch(异常类名 1 异常对象名 1){
//此处放处理异常对象 1 的代码
} catch(异常类名 2 异常对象名 2){
//此处放处理异常对象 2 的代码
}finally{
//必须执行的代码
}
-
如果抛出的异常被捕获了,程序会继续执行,而不会终止运行。
-
try块里的代码如果抛出异常,则try块里的代码不会继续执行,而是转到catch块里执行。
-
一个try可以对应多个catch,catch的规则应该是先catch子类异常,后catch父类异常,且一个异常只会被catch一次
-
所有异常都继承自Exception,所以在最后catch一下Exception是一个好习惯
-
运行时异常也可以被catch
throw 语句
通常情况下,异常是由系统自动抛出的。但程序员也可以自己通过 throw 语句抛出异
常。throw 语句抛出异常的格式如下:
throw new 异常类名(异常描述);
其中异常类名为系统异常类名或用户自定义异常类名。
如果一个方法没有捕获可能触发的异常,调用该方法的其它方法应该捕获并处理该异常。
为了明确某个方法不能捕获某个异常,而让调用该方法的其它方法捕获异常,可以在方法声
明的时候,使用 throws 可选项抛出该类异常。其声明的格式如下
[修饰符] 返回值类型 方法名(参数列表) throws 异常类型名{
方法体
}
即在方法声明的后面添加 throws 异常类型名。
throws,表明可以抛出多个异常,多个异常用逗号隔开 throws抛出的异常不一定会被抛出,throws只是负责向外抛这个方法捕获到的异常,不负责判断这个异常到底有没有被捕获到,所以throws后面可以随便写 但是,throws后面必须包含本方法可能被抛出的异常,除非这个异常在本方法内已经被捕获了或者这个异常是运行时异常
public boolean equals(Object obj)
equals 方法应该实现的功能是将当前对象(this)与传入对象进行比较,返回比较结果。
返回值为 boolean 类型,相等返回 true,否则返回 false。传入的参数代表比较对象,将其
与当前对象(this)的内容进行比较。一般来说应该按照如下规则实现 equals 方法:
1. 首先判断传入对象是否为 null,如果为 null 返回 false。
2. 判断传入对象与当前对象是否为同一类型(通过 instanceof 关键字),如果不是返
回 false。
3. 判断当前对象与传入对象的内容。
StringBuffer和StringBuilder的区别
共同之处:都是final类,不允许被继承,主要是从性能和安全性上考虑的,因为这几个类都是经常被使用着,且考虑到防止其中的参数被参数修改影响到其他的应用
区别主要是在两个方面,即运行速度和线程安全这两方面
运行速度,或者说是执行速度,**在这方面运行速度快慢为:StringBuilder > StringBuffer
在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的。如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。。
集合
Collection
Collection集合的方法: boolean add(E e) 在集合末尾添加元素 boolean remove(Object o) 若本类集中有值与o的值相等的元素,则删除该元素,返回ture void clear()清楚本类集中所有元素,调用晚该方法之后本类集将为空 boolean contains(Object o)判断集合中是否包含某元素 boolean isEmpty()判断集合是否为空 int size()返回集合中的元素个数 boolean addAll(Collection c)将一个类集c中的所有元素添加到另一一个类集 Object[] toArray() 返回一个包含了本类集中的所有元素的数组,数组类型为:Object[] Iterator iterartor() 迭代器,集合的专用遍历方式
List
List集合是一个元素有序(每个元素都有对应的顺序索引,第一个元素索引为零),且可重复的集合。存取顺序一致 List是Collection接口的子接口,拥有Collection所有方法外,还有一些对索引操作的方法。
void add(int index, E element);:将元素element插入到List集合的index处;
boolean addAll(int index, Collection<? extends E> c);:将集合c所有的元素都插入到List集合的index起始处;
E remove(int index);:移除并返回index处的元素;
int indexOf(Object o);:返回对象o在List集合中第一次出现的位置索引;
int lastIndexOf(Object o);:返回对象o在List集合中最后一次出现的位置索引;
E set(int index, E element);:将index索引处的元素替换为新的element对象,并返回被替换的旧元素;
E get(int index);:返回集合index索引处的对象;
List<E> subList(int fromIndex, int toIndex);:返回从索引fromIndex(包含)到索引toIndex(不包含)所有元素组成的子集合;
void sort(Comparator<? super E> c):根据Comparator参数对List集合元素进行排序;
void replaceAll(UnaryOperator<E> operator):根据operator指定的计算规则重新设置集合的所有元素。
ListIterator<E> listIterator();:返回一个ListIterator对象,该接口继承了Iterator接口,在Iterator接口基础上增加了以下方法,具有向前迭代功能且可以增加元素:
Arrylist
ArrayList 类提供了快速的基于索引的成员访问方式,对尾部成员的增加和删除支持较好。使用 ArrayList 创建的集合,允许对集合中的元素进行快速的随机访问
特点:排列有序,可重复;底层使用数组;速度快,增删慢,getter()和setter()方法块;线程不安全;当容量不够时,ArrayList当前容量*1.5+1
常用的ArrayList类成员方法:
-
增加元素到链表中
-
boolean add(Element e)
增加指定元素到链表尾部. -
void add(int index, Element e)
增加指定元素到链表指定位置.
-
-
从链表中删除元素
-
void clear()
从链表中删除所有元素. -
E remove(int index)
删除链表中指定位置的元素. -
protected void removeRange(int start, int end)
删除链表中从某一个位置开始到某一个位置结束的元素。
-
-
获取链表中的元素
-
E get(int index)
获取链表中指定位置处的元素. -
Object[] toArray()
获取一个数组,数组中所有元素是链表中的元素.(即将链表转换为一个数组)
-
-
修改某个元素
-
E set(int index, E element)
将链表中指定位置上的元素替换成新元素。
-
-
搜索元素
-
boolean contains(Object o)
如果链表包含指定元素,返回true. -
int indexOf(Object o)
返回元素在链表中第一次出现的位置,如果返回-1,表示链表中没有这个元素。 -
int lastIndexOf(Object o)
返回元素在链表中最后一次出现的位置,如果返回-1,表示链表中没有这个元素。
-
-
检查链表是否为空
-
boolean isEmpty()
返回true表示链表中没有任何元素.
-
-
-
int size()
返回链表长度(链表包含元素的个数).
-
Vector
特点:排列有序,可重复;底层使用数组;速度快,增删慢;线程安全,效率低;当容量不够时,Vector默认扩展一倍容量
Vector的四种构造方法:
1、Vector(); 构造一个空向量,使其内部数据数组的大小为10,其标准容量增量为零。 Vector vec=new Vector();
2、Vector(Collection c); 构造一个包含指定collection中的元素的向量,这些元素按其collection的迭代器返回元素的顺序排列。 Vector v=new Vector(vec);
3、Vector(int initialCapacity); 使用指定的初始容量和等于零的容量增量构造一个空向量。
4、Vector(int initialCapacity,int capacityIncrement); 使用指定的初始容量和容量增量构造一个空的向量。 Vector类中的方法:
1、boolean add(E e); 将指定的元素添加到此向量的末尾。
2、void addElement(E obj); 将指定的组件添加到此向量的末尾,将其大小增加1。
3、void add(int indext,E e); 在此向量的指定位置插入指定的元素。
4、boolean addAll(Collection c); 将指定Collection中的所有元素添加到此向量的末尾,按照指定collection的迭代器所返回的顺序添加这些元素。
5、boolean addAll(int index,Collection c); 在指定位置将指定Collection中的所有元素插入到此向量中。
6、int capacity(); 返回此向量的当前容量。
7、Object clone(); 返回向量的一个副本。
8、boolean contains(Object o); 如果此向量包含指定的元素,怎返回true。
9、boolean containsAll(Collection c); 如果此向量包含Collection中的所有元素,则返回true。
10、void copyInto(Object[] anArray); 将此向量的组件复制到指定的数组中。
11、E elementAt(int index); 返回指定索引处的组件。
12、Enumeration<E> elements(); 返回此向量的组件的枚举。
13、void ensureCapacity(int minCapacity); 增加此向量的容量(如有必要),以确保其至少能够保证最小容量参数指定的组件数。
14、boolean equals(Object o); 比较指定对象与此向量的相等性。
16、E lastelement(); 返回此向量的最后一个组件。代码略。
17、E get(int index); 返回向量中指定位置 的元素。
18、int hashCode(); 返回此向量的哈希码值。
19、int indexOf(Object o,int index); 返回此向量中第一次出现的指定的元素的索引,从index处正向索引,如果未找到该元素,则返回-1.
20、int indexOf(Object o); 返回此向量中第一次出现的指定元素的索引,如果此向量不包含该元素,则返回-1。
21、int lastIndexOf(Object o,int index); 返回此向量中最后一次出现的指定元素的索引,从index处逆向搜索,如果未找到该元素,则返回-1.
22、int lastIndexOf(Object o); 返回此向量中最后一次出现的指定元素的索引,如果此向量不包含该元素,则返回-1。
23、boolean isEmpty(); 测试此向量是否不包含组件。
24、void clear(); 从此向量中移除所有元素。
25、E remove(int index); 移除此向量中指定位置的元素
26、boolean remove(Object o); 移除此向量中指定元素的第一个匹配项,如果向量不包含该元素,则元素保持不变。
27、boolean removeAll(Collection c); 从此向量中移除包含在指定Collection中的所有元素。
28、void removeAllElements(); 从此向量中移除全部组件,并将其大小设置为零。
29、boolean removeElement(Object obj); 从此向量中移除变量的第一个(索引最小的)匹配项。
30、void removeElementAt(int index); 删除指定索引处的组件。
31、protected void removeRange(int fromIndex,int toIndex); 从此list中移除位于formIndex(包括)与toIndex(不包括)之间的所有元素。
32、boolean retainAll(Collection c); 在此向量中仅保留包含在指定Collection中的元素。
LinkedList
LinkedList 类采用链表结构保存对象,这种结构的优点是便于向集合中插入或者删除元素。需要频繁向集合中插入和删除元素时,使用 LinkedList 类比 ArrayList 类效果高
特点 :排列有序,可重复;底层使用双向链表循环数据结构;查询速度慢,增删快;add()和remove()方法快;线程不安全
构造方法
-
LinkedList<类> list = new LinkedList<类>();
-
LinkedList<类> list = new LinkedList(Collection<? extends E> c); 使用一个集合创建一个新的linkedList。
常用方法
1.增
-
public boolean add(E e),链表末尾添加元素,返回是否成功;
-
public void add(int index, E element),向指定位置插入元素;
-
public boolean addAll(Collection<? extends E> c),将一个集合的所有元素添加到链表后面,返回是否成功;
-
public boolean addAll(int index, Collection<? extends E> c),将一个集合的所有元素添加到链表的指定位置后面,返回是否成功;
-
public void addFirst(E e),添加到第一个元素;
-
public void addLast(E e),添加到最后一个元素;
-
public boolean offer(E e),向链表末尾添加元素,返回是否成功;
-
public boolean offerFirst(E e),头部插入元素,返回是否成功;
-
public boolean offerLast(E e),尾部插入元素,返回是否成功;
2.删
-
public void clear(),清空链表;
-
public E removeFirst(),删除并返回第一个元素;
-
public E removeLast(),删除并返回最后一个元素;
-
public boolean remove(Object o),删除某一元素,返回是否成功;
-
public E remove(int index),删除指定位置的元素;
-
public E poll(),删除并返回第一个元素;
-
public E remove(),删除并返回第一个元素;
3.查
-
public boolean contains(Object o),判断是否含有某一元素;
-
public E get(int index),返回指定位置的元素;
-
public E getFirst(), 返回第一个元素;
-
public E getLast(),返回最后一个元素;
-
public int indexOf(Object o),查找指定元素从前往后第一次出现的索引;
-
public int lastIndexOf(Object o),查找指定元素最后一次出现的索引;
-
public E peek(),返回第一个元素;
-
public E element(),返回第一个元素;
-
public E peekFirst(),返回头部元素;
-
public E peekLast(),返回尾部元素;
4.改
-
public E set(int index, E element),设置指定位置的元素;
5.遍历
for (int size = linkedList.size(), i = 0; i < size; i++) {
System.out.println(linkedList.get(i));
}
for (String str: linkedList) {
System.out.println(str);
}
Iterator iter = linkedList.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
Set
Set中的元素是不能重复的,如果使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象。存储顺序无序
1 | add( ) 向集合中添加元素 |
---|---|
2 | clear( ) 去掉集合中所有的元素 |
3 | contains( ) 判断集合中是否包含某一个元素 |
4 | isEmpty( ) 判断集合是否为空 |
5 | iterator( ) 主要用于递归集合,返回一个Iterator()对象 |
6 | remove( ) 从集合中去掉特定的对象 |
7 | size( ) 返回集合的大 |
Hashset
HashSet 类是按照哈希算法来存储集合中的元素,使用哈希算法可以提高集合元素的存储速度,当向 Set 集合中添加一个元素时,HashSet 会调用该元素的 hashCode() 方法,获取其哈希码,然后根据这个哈希码计算出该元素在集合中的存储位置,
特点:排列无序,不可重复;底层使用Hash表实现;内存速度快,内部是HashMap
HashSet的一些常用方法:
添加元素:
hashset.add(E e):返回boolean型,如果此 set 中尚未包含指定元素,则添加指定元素;如果此 set 已包含该元素,则该调用不更改 set 并返回 false。
删除元素:
hashset.clear():从此 set 中移除所有元素。
hashset.remove(Object o):如果指定元素存在于此 set 中,则将其移除。
hashset.isEmpty():如果此 set 不包含任何元素,则返回 true。
hashset.contains(Object o):如果此 set 包含指定元素,则返回 true。
hashset.size():返回此 set 中的元素的数量(set 的容量)。
TreeSet
TreeSet 类同时实现了 Set 接口和 SortedSet 接口。SortedSet 接口是 Set 接口的子接口,可以实现对集合升序排序。TreeSet 只能对实现了 Comparable 接口的类对象进行排序,因为 Comparable 接口中有一个 compareTo(Object o) 方法用于比较两个对象的大小
特点:排列无序,不可重复;底层使用二叉树实现;排序存储;内部是TreeMap的SortedSet
LinkedHashSet
特点 :采用hash表存储,并用双向链表记录插入数据;内部是LinkedHashMap;
Map
特点:Map集合中的键是唯一的;Map集合中的值是可以重复的
两种遍历方法
第一种方法:使用keySet()
这种方法遍历了2次,一次是转为iterator,另一次是从HashMap中取出key所对应的value。
(1) For-Each
Set <String> keys = map.keySet(); //map.keySet()返回key的集合
for(String key:keys) {
System.out.println(key+":"+map.get(key)); //map.get(key)返回key所对应的value值
}
1234
(2) 迭代器
Set <String> keys = map.keySet();
Iterator<String> it = keys.iterator();
String key;
while (it.hasNext()) {
key = it.next();
System.out.println(key+":"+map.get(key));
}
1234567
第二种方法:使用entrySet()
这种方法只遍历了1次,它把key和value都放到了entry中,因此比keySet()快。
(1) For-Each
Set<Entry<String,String>> entrySet = map.entrySet(); //map.entrySet()返回<key,value>键值对的集合
for (Entry<String,String> entry:entrySet) {
System.out.println(entry.getKey()+":"+entry.getValue()); //entry.getKey()返回key,entry.getValue()返回value
}
1234
(2) 迭代器
Set<Entry<String,String>> entrySet = map.entrySet();
Iterator<Entry<String,String>> it = entrySet.iterator();
Entry<String,String> entry;
while (it.hasNext()) {
entry = it.next();
System.out.println(entry.getKey()+":"+entry.getValue());
}
关于文件的类——File类
public class File implements Serializable, Comparable<File>
File类实现了Serializable(序列化)和Comparable(可比较)接口
File类对象是文件和目录路径名的抽象表示形式。
File类的构造器:
常用方法:
public boolean exists()
测试此抽象路径名表示的文件或目录是否存在。
public boolean createNewFile() throws IOException
当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。检查文件是否存在,若不存在则创建该文件,这是单个操作,对于其他所有可能影响该文件的文件系统活动来说,该操作是不可分的
返回:
如果指定的文件不存在并成功地创建,则返回 true
;如果指定的文件已经存在,则返回 false
//String getName() 获取文件名 //String getAbsolutePath() 获取绝对路径 //boolean isFile() 是否是文件 //boolean isDirectory() 是否是目录(文件夹) //boolean delete() 删除文件 //long length() 获取文件内容的长度(其实就是文件大小)
IO流的体系
抽象基类里的InputStream和以及访问文件的FileInputStream
字节流和字符流的区别:
单位的区别,字节流以字节为单位进行输入输出,字符流以字符为单位进行输入输出。
字节对应的类是Byte(基本数据类型是byte),字符对应的类是Character(基本数据类型是char)
InputStream
public abstract class InputStream implements Closeable
InputStream是一个抽象类,所以 不能直接new对象
然后,InputStream实现了一个接口Closeable,顾名思义就是可关闭的,
Closeable
public interface Closeable extends AutoCloseable { public void close() throws IOException; }
Closeable继承自AutoCloseable接口,并且声明了一个方法close()
public interface AutoCloseable { void close() throws Exception; }
1.流的概念及分类
Java将所有传统的流模型(类或抽象类),都放在了Java.io包中,用来实现输入输出的功能。
这里面我们将流分成两种:输入流和输出流。
输入流:只能从中读取数据,而不能向其写入数据。代表:InputStream(字节输入流),Reader(字符输入流)。
输出流:只能向其写入数据,而不能从中读取数据。代表:OutputStream(字节输出流),Writer(字符输出流)。
流按照操作类型也可以分成两种:
字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的 。它操作的数据单元是8位的字节。
字符流 : 字符流只能操作纯字符数据,比较方便。它操作的数据单元是16位的字符。
从Java程序指向文件,这个过程我们称为输出或者写入文件,从文件指向Java程序,这个过程我们称为输入或者读出文件。
在输入流和输出流中,我们主要掌握4个流文件的操作:InputStream,OutputStream,Reader,Writer。这四个类都是抽象类,前两个代表了字节的输入输出流,后两个代表字符的输入输出流,当我们调用的时候通常使用他们的子类来实现我们的类方法。
2.字节输出流(OutputStream)
字节输出流它有以下几个方法可以提供给它的子类使用(在输入输出流中,子类几乎没什么方法,都是调用父类的方法)
-
void close(): 关闭此输出流并释放与此流有关的所有系统资源。
-
void write(byte[] b): 将 b.length 个字节从指定的 byte 数组写入此输出流
-
void write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
-
abstract void write(int b) : 将指定的字节写入此输出流。
由于OutputStream是抽象类,因此我们在向文件写入(输出)字节的时候,需要用到它的子类FileOutputStream,接下来通过使用上面的方法,来实现字节流的输出操作。
关于FileOutputStream:
(1).写入数据文件,通过使用父类的方法,调用子类的对象
(2).FileOutputStream构造方法:
-
作用:绑定输出的输出目的
-
FileOutputStream(File file)
-
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
-
-
FileOutputStream(File file, boolean append)
-
创建一个向指定 File 对象表示的文件中写入数据的文件输出流,以追加的方式写入。
-
-
FileOutputStream(String name)
-
创建一个向具有指定名称的文件中写入数据的输出文件流。
-
-
FileOutputStream(String name, boolean append)
-
创建一个向具有指定 name 的文件中写入数据的输出文件流,以追加的方式写入。
-
(3).流对象的使用步骤:
1).创建流子类的对象,绑定数据目的。
2).调用流对象的方法write写
3).close释放资源
(4).注意事项:流对象的构造方法,可以用来创建文件,如果文件存在的情况下,直接覆盖原文件。
3.字节输入流(InputStream)
字节输入流它有以下几个方法可以提供给它的子类使用(在输入输出流中,子类几乎没什么方法,都是调用父类的方法)
-
abstract int read() : * 从输入流中读取数据的下一个字节,返回-1表示文件结束
-
int read(byte[] b) * 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1。
-
int read(byte[] b, int off, int len) * 将输入流中最多 len 个数据字节读入 byte 数组。 * void close() * 关闭此输入流并释放与该流关联的所有系统资源。
由于InputStream是抽象类,因此我们在从文件读取(输入)字节的时候,需要用到它的子类FileInputStream,接下来通过使用上面的方法,来实现字节流的输入操作。
关于FileInputStream:
在使用FileInputStream创建对象的时候,我们也需要为这个类绑定数据源(我们要读取的文件名)
FileInputStream的构造方法与上述的构造方法相似,里面的参数有两种类型:File类型对象,String类型对象。
输入流读取文件的操作步骤:
(1).创建字节输入流的子类对象
(2).调用读取方法read读取
(3).关闭资源
注意事项:read()方法每执行一次,就会自动的读取下一个字节。它的返回值是读取到的字节,如果没有字节可以读取了,那么返回-1。
4.字符输出流(Writer)
由于Writer也是一个抽象类,因此我们用它的子类FileWriter来实现字符流的输出操作。
关于FileWriter:
(1).方法介绍:
void write(int c):写入单个字符。
void write(String str):写入字符串。
void write(String str, int off, int len):写入字符串的某一部分。
void write(char[] cbuf):写入字符数组。
abstract void write(char[] cbuf, int off, int len):写入字符数组的某一部分。
5.字符输入流(Reader)
由于Reader也是一个抽象类,因此我们用它的子类FileReader来实现字符流的输出操作。
(1)方法介绍:
int read() * 读取单个字符
int read(char[] cbuf) * 将字符读入数组
abstract int read(char[] cbu f, int off, int len) * 将字符读入数组的某一部分。
字符流的输入输出与字节流的差不多,但是字符流只能操作文本文件,不能操作除了文本文件以外的文件,而字节流可以操作文本文件以及音乐,视频等文件,因此在平时的IO流中,我们使用字节流的操作更多一些。
6.文件的复制操作。(这里面我使用字节流的方式实现)
文件的复制操作简单的说就是将一个文件上的内容读取出来,并且将读取到的内容写入到另一个文件上,因此在文件的复制操作中,需要使用文件的输入和输出流操作。