目录
一. 泛型
(1) 什么是泛型
1. 泛型就是限制我们得数据类型。
2.为什么使用泛型?
我们原来在定义集合时,是如下得定义方式:
List list = new ArrayList(); //该集合没有使用泛型list.add("南京");
list.add("北京");
Object s = list.get(0);
System.out.println(s);
String b = (String) list.get(1); //使用类型输出时需要进行强制转换
获取元素时,不方便对元素进行相应得其他操作。
(2) 如何使用泛型
package com.xx.test2;
import java.util.*;
public class TextFx02 {
public static void main(String[] args) {
List<String> ls = new ArrayList<>(); //限制了集合中元素的类型(这就是泛型)
ls.add("孙悟空");
//ls.add(15); 因为集合中只能添加String类型
//限制集合的key值只能为String类型,value值只能为Integer类型
HashMap<String,Integer> hm = new HashMap();
hm.put("name",90);
hm.put("name2",99);
//hm.put("name","孙悟空");//因为value值设置了限定条件,所有value只能存储Interger类型的数据
Set<String> keys = hm.keySet(); //获取所有的key值
for (String xx:keys){ //遍历获取到的每一个key值
Integer s = hm.get(xx); //根据key获取value
System.out.println(s);
}
}
}
(3) 我们自己定义泛型类
package com.xx.test2;
public class TextFx03 {
public static void main(String[] args) {
Point pi = new Point();
pi.setX("15");
pi.setY("东京");
pi.test();
//指定泛型,添加的输入必须是指定类型
Point<String> pi2 = new Point<>();
pi2.setX("高渐离");
pi2.setY("钟子期");
//pi2.setX(90); //添加的元素不是指定类型
pi2.test();
Point<Integer> pi3 = new Point<>();
pi3.setX(99);
pi3.setY(96);
pi3.test();
}
}
class Point<T>{
private T x;
private T y;
public void test(){
System.out.println(this.x+" "+this.y);
}
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
}
二. File 对象
(1) File的介绍
File 类 就是当前系统中 文件或者文件夹的抽象表示
通俗的讲 就是 使用File对象 来操作我们电脑系统中的文件或者文件夹
学习File类 其实就是学习 如果通过file对象 对系统中的文件/文件夹进行增删改查
(2) 创建Flie对象(创建文件或目录)
//创建一个File对象 并指定文件得路径
//三种路径引入方式
File fl = new File("D:\\xwj\\test1.txt");
File fl2 = new File("D:/xwj/test2.txt");
File fl3 = new File("D:"+File.separator+"xwj"+File.separator+"test3.txt");
//System.out.println(File.separator); //输出的是“\”
fl.createNewFile(); //创建指定的test1.txt文件
File fl4 = new File("D:/qy151/qy151/xwj/file01");
fl4.mkdir(); //创建指定的文件夹
File fl5= new File("D:/qy151/qy151/xwj/file02/zml01");
fl5.mkdirs(); //创建指定的多级文件夹
//若在指定路径下已经存在同名文件或文件夹,命令都不会被执行
(3) 删除操作
File fl = new File("D:\\xwj\\test1.txt"); //创建一个File对象 并指定文件得路径
fl.delete(); //删除指定路径下的文件
fl.deleteOnExit(); //在程序结束时删除指定文件
Thread.sleep(1000); //设置休眠时间,休眠结束,执行deleteOnExit()命令
File fl4 = new File("D:/xwj/file01");
fl4.delete(); //删除空目录(该命令只能删除空目录)
(4) 修改操作
File fl = new File("D:\\xwj\\test1.txt");
fl.setReadable(false); //设置文件不能读
fl.setWritable(false); //设置文件不能写
fl.setReadOnly(); //设置文件只读
fl.renameTo(new File("D:\\xwj\\xyz.txt")); //将文件重命名
(5) 查询操作
File fl = new File("D:\\xwj\\test1.txt");
String name = fl.getName(); //得到文件名称
System.out.println(name);
String parent = fl.getParent(); //得到父级路径的名称
System.out.println(parent);
String path = fl.getPath(); //得到文件路径的名称
System.out.println(path);
System.out.println("==============");
boolean s = fl.isFile(); //判断当前路径下的是不是文件
boolean s2 = fl.isDirectory(); //判断当前路径下的是不是文件夹
System.out.println(s);
System.out.println(s2);
System.out.println("==============");
File f = new File("D:\\xwj"); //创建file对象并获取指定路径
//列出指定目录下的所有子文件的名称(文件夹,图片,文本等所有在该文件夹下的文件的名称)
String[] list = f.list();
System.out.println(list);
System.out.println(Arrays.toString(list));
File[] f2 = f.listFiles(); //列出指定目录下的所有子文件的路径及名称
System.out.println(f2);
System.out.println(Arrays.toString(f2));
System.out.println("---------------");
//循环输出指定目录下的所有子文件的路径及名称
for (File xx:f2){
System.out.println(xx);
}
(6) 经典面试题
求指定路径下的所有文件及目录(包含子目录下的子目录及内容)
package com.xx.test4;
import java.io.File;
public class TextMst {
public static void main(String[] args) {
showAllFiles("D:\\xwj");
}
public static void showAllFiles(String path){
//使用传入的路径构建文件对象
File file = new File(path);
if (!file.exists()||!file.isDirectory()){ //判断传入的文件对象是否是存在或是否为文件夹
return;
}
File[] f2 = file.listFiles(); //列出指定目录下的所有子文件的路径及名称
for (File f:f2){
if (f.isDirectory()){
System.out.println(f.getPath()); //输出获取到的所有文件夹路径及名称
showAllFiles(f.getPath()); //继续调用本方法(通过新获取到的路径,查询下面是否有文件或目录)
}
//判断该路径下是否有文件
if (f.isFile()){
System.out.println(f.getPath()); //输出查询到的路径及名称
}
}
}
}
三. IO流
(1) 什么是IO流
1. IO 表示有两个单词的缩写。
I: Input 输入 O: Output 输出2. IO的作用:就是对文件中的内容进行操作。
输入: 读操作(读取文件的内容) 输出: 写操作(往文件中写内容)
3. IO流的分类:(1)根据流的方向:
>>>输入流: 程序可以从中读取数据的流。
>>>输出流: 程序能向其中写入数据的流。
(2)根据流的单位:
>>>字节流: 以字节为单位传输数据的流
>>>字符流: 以字符为单位传输数据的流
(3)根据功能
>>>节点流: 直接和文件进行交互
>>>处理流: 不是直接作用在文件上。
四个基本的流: 其他的流都是在这四个流的基础上进行扩展的
字节输入流
字节输出流
字符输入流
字符输出流
(2) 字符
2.1 write字符输出流
它是所有字符输出流的根类。---FileWriter类
public static void main(String[] args) throws IOException {
File fl = new File("D:\\xwj\\xx.txt"); //创建File对象并指定路径
fl.createNewFile(); //在指定路径下创建指定文件
Writer wt = new FileWriter("D:\xwj\\xx.txt",true);
String str = "hello world";
wt.write(str); //向txt文件中添加内容
//wt.flush(); //属性流
//wt.close(); //关闭流资源
//当此行代码运行一遍后,若将内容更改,重新运行,则会覆盖前面由这行代码写入的内容
// 方法一:不覆盖的解决方法,在原先new FileWriter("路径")上添加true变为new FileWriter("路径",true)
//方法二:再新创建String,添加新数据
String str2 = "我和你心连心";
wt.write(str2);
wt.flush();
wt.close();
}
2.2 Reader 字符输入流
它是所有字符输入流的根类 它的实现类有很多,我们使用FileReader实现类
a. 单个字符读取
public static void main(String[] args) throws Exception {
Reader rd = new FileReader("D:\\xwj\\xx.txt");
//read();每次只读取一个字符
Object c = rd.read(); //通过read()读取的是经系统转译后的ASCII码
System.out.println(c);
int c2 = rd.read();
//每次读取一个字符,因为上面已经读取过一次,这次输出的是文件的中的第二个字符
Object d = (char)rd.read();
System.out.println(d);
}
b. 数组方式读取
public static void main(String[] args) throws Exception {
Reader rd2 = new FileReader("D:\\xwj\\xx.txt");
char[] cs = new char[10]; //创建一个容量为20的字符数组
rd2.read(cs); //将读取到的元素放置到cs中,直到填满为止
System.out.println(Arrays.toString(cs)); //将cs数组中存储的数据转为toString形式输出
int c = rd2.read(cs); //计算读取的个数,将个数赋值给c(上面已经读取过一次,这次相当于第二次读取)
System.out.println(c);
System.out.println(cs);
System.out.println(Arrays.toString(cs));
String tr = new String(cs); //将cs数组转换为字符串形式
System.out.println(cs);
System.out.println("===============");
//再次读取文件中的元素,但是接着上次读取结束的位置开始读取,而不是从头读取,若剩余内容小于数组长度,则会重头开始读取
//再次读取的内容会覆盖原先填入数组的内容(从数组第一个元素开始覆盖,若剩余内容小于数组长度,则后面内容不改变,只有前面被覆盖的改变)
c= rd2.read(cs);
System.out.println(c);
System.out.println(cs); //前面读取已经把内容读取完毕,因为读取不到元素,输出的是最后读取的数组
System.out.println(Arrays.toString(cs)); //前面读取已经把内容读取完毕,因为读取不到元素,是将最后读取的数组内容转为toSring形式
String str = new String(cs);
System.out.println(str);
//解决方法:重新创建一个数组,会接着上个数组读取结束的位置开始读取,但值会存入新的数组,但是若内容读取结束不会重头开始读,数组剩余空间显示为空
//若在内容读取完后又重新创建一个数组,开始读取文件内容,输出内容返回-1;(若文件已经全部读取过或文件为空,返回-1)
}
c. 循环方式读取
public static void main(String[] args) throws Exception{
Reader rd3 = new FileReader("D:\\xwj\\xx.txt");//创建字符输入流对象
int count = 0;
char[] cs = new char[10];
//rd3.read(cs)返回的值是ASCII码,而不是字符形式(若要输出字符形式则要强转,(char)rd3.read(cs))
//每次循环获取的ASCII码都赋值给count,若count不等于-1,则循环继续
//当rd3.read(cs)读取内容完毕时,数组未填满读取结果则为空,此时rd3.read(cs)读取结果为-1,则count=-1,循环结束
while ((count = rd3.read(cs)) !=-1){ //count = rd3.read(cs)返回每次读取的放入cs的元素个数
//String str = new String(cs); 默认情况是将cs数组中的所有元素组成字符串,添加条件后指将数组cs中指定初始位置到指定结束位置的字符拼接为字符串
String str = new String(cs,0,count); //将cs数组转换为字符串形式,从0开始,到读取长度最大值结束
System.out.println(str); //若文件内容大于数组长度,则每次获取的内容换行输出
}
rd3.close();
}
2.3. 完成文件内容的复制
public static void main(String[] args) throws Exception {
//创建字符输入流
FileReader fr = new FileReader("D:\\xwj\\test1.txt");
File fl = new File("C:/Test/bbb");
fl.mkdir();
File fl2 = new File("C:/Test/bbb/sy1.txt");
fl2.createNewFile();
//创建字符输入流(向指定文件写入东西,完成复制要求)
FileWriter fw = new FileWriter("C:/Test/bbb/sy1.txt");
int a = 0; //读取到的字符个数
char[] ary = new char[10]; //每次读取的内容放入该数组
while ((a = fr.read(ary))!=-1){
String str = new String(ary,0,a); //把数组中(0,a)的数据转换为字符串形式
fw.write(str);
fw.flush();
}
fr.close();
fw.close();
}
(3) 字节
3.1 字节输入流(向指定文件写入内容)
public static void main(String[] args) throws Exception{
//如果目录中没有该文件,则系统会默认建立新文件,但不能建立文件夹
OutputStream ot = new FileOutputStream("D:\xwj\\test2.txt");
String str = "hello world";
byte[] bytes =str.getBytes(); //将字符串转换为字节数组
ot.write(bytes);
ot.flush();
ot.close();
}
3.2 字节输出流(将指定文件的内容提取出来)
a.提取内容占用空间小时的方式
public static void main(String[] args) throws Exception{
InputStream is = new FileInputStream("D:\\xwj\\test2.txt");
//当读取的内容是中文时,中文默认占用三个字节,若将字节数组空间设置为5,因为系统无法读取一个半字符,所以会出现乱码
//解决方法(1.设置足够大的空间2.数组长度设置为3的倍数)
byte[] bytes = new byte[3];
//byte[] bytes1 = is.read();
int a = is.read(bytes); //读取指定文件的内容并将内容放置到bytes数组中
System.out.println(a);
System.out.println(bytes);
}
b.提取内容占用空间大时的方式
public static void main(String[] args) throws Exception{
InputStream is = new FileInputStream("D:\\xwj\\test2.txt");
int a = 0;
byte[] bytes = new byte[3]; //定义一个空间为3的字节数组
while ((a=is.read(bytes))!=-1){
String str = new String(bytes,0,a);
System.out.println(str);
}
is.close();
}
3.3 使用字节流完成指定文件的复制
复制的不单单是文件内容,而是包括图片,视频等文件
public static void main(String[] args) throws Exception{
//通过输出流读取指定的文件
InputStream is = new FileInputStream("D:/xwj/1.webp");
//通过输入流向指定路径中存入指定文件(可以将复制过来的文件直接更改文件名)
OutputStream os = new FileOutputStream("C:/Test/bbb/2.webp");
byte[] bytes = new byte[10];
int s = 0;
while ((s = is.read(bytes))!=-1){ //读取指定文件并存储到字节数组中
os.write(bytes,0,s); //将读取到的文件写入指定路径中(复制到指定路径中)
}
is.close();
os.close();
}
3.4 缓存流和对象流
缓存流和对象流都是在基础流的基础上进行操作
a. 缓存流
public void TestBuffer() throws Exception{
OutputStream os = new FileOutputStream("D:/xwj/test03.txt"); //引入基础流
//当读取的内容超过缓存池的容量大小,内容则直接写入指定文件中
BufferedOutputStream bos = new BufferedOutputStream(os); //缓存流要作用在基础流上(缓存池默认大小为8192)
//BufferedOutputStream bos2 = new BufferedOutputStream(os,1); //缓存流要作用在基础流上(自行设置缓存池容量大小)
String a = "abcdefghijklmn";
byte[] ary = a.getBytes(); //将字符串内容转为字节数组
bos.write(ary); //将字节数组里的内容暂时存入缓存池(在刷新后或关闭后将暂存的内容放入指定文件中)
bos.flush(); //刷新缓存池(刷新后就会将缓存池中的内容写入到指定文件中)
bos.close(); //(先刷新缓存池),再关闭流资源
}
b. 对象流
package coms.zjl.test1;
import org.testng.annotations.Test;
import java.io.*;
public class TextRole {
//存档----序列化,输入对象流(将对象中的内容存储到本地)
public static void main(String[] args) throws Exception{
OutputStream ot = new FileOutputStream("D:\\xwj\\test4.txt"); //引入基础输入流
//对象输入流
ObjectOutputStream oop = new ObjectOutputStream(ot); //引入对象输入流
Role role = new Role("吕布","7级",123,"貂蝉"); //引入对象
//写入对象流时,必须在对象上添加Serializable接口
oop.writeObject(role); //将对象存入指定路径指定文件中
oop.close();
}
//读档------反序列化,输出对象流
@Test
public void test() throws Exception{
InputStream is = new FileInputStream("D:\xwj\\test4.txt"); //引入基础流
ObjectInputStream ot = new ObjectInputStream(is); //引入对象流
Object t = ot.readObject();
System.out.println(t);
ot.close();
}
}
//创建角色对象
class Role implements Serializable {
private String name;
private String level;
private int id;
private String other;
public Role() {
}
public Role(String name, String level, int id, String other) {
this.name = name;
this.level = level;
this.id = id;
this.other = other;
}
@Override
public String toString() {
return "Role{" +
"name='" + name + '\'' +
", level='" + level + '\'' +
", id=" + id +
", other='" + other + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getOther() {
return other;
}
public void setOther(String other) {
this.other = other;
}
}
(4) 总结
1. 通过字符流完成文件的复制---->它只能复制文本文件
2. 字节流:---字节输入流和字节输出流。
3. 字节流 我们也可以完成文件的复制功能---它可以复制任意类型的文件.
4. 缓存流--->它在基本流的基础上 添加了一个缓存池
5. 对象流: ObjectInputStream ObjectOutputStream
序列化 反序列化