泛型和IO流详解

目录

一. 泛型

(1) 什么是泛型

(2) 如何使用泛型

(3) 我们自己定义泛型类

二. File 对象

(1) File的介绍

(2) 创建Flie对象(创建文件或目录)

 (3) 删除操作

(4) 修改操作

(5) 查询操作

(6) 经典面试题

 三. IO流

(1) 什么是IO流

(2) 字符 

2.1 write字符输出流

2.2 Reader 字符输入流

2.3. 完成文件内容的复制

(3) 字节

3.1 字节输入流(向指定文件写入内容)

3.2 字节输出流(将指定文件的内容提取出来)

3.3  使用字节流完成指定文件的复制

 3.4 缓存流和对象流

(4) 总结


一. 泛型

(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
     序列化   反序列化

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值