第十章-----Java泛型 File类 IO流 缓存流 对象流

1.泛型

1.1.什么是泛型?

泛型就是限制我们的数据类型。

为什么使用泛型?

我们原来在定义集合时,是如下的定义方式:

List list = new ArrayList();//该集合没有使用泛型

list.add("java01");

list.add("java02");

String str = (String)list.get(0); //获取元素 需要进行强制类型转换

System.out.println(str);

获取元素,不方便对元素进行相应的其他操作.

1.2.如何使用泛型

List<类型> list = new ArrayList<类型>();只能在该集合中存储指定的类型.

 public static void main(String[] args) {
        List<String> list=new ArrayList<>();//这里就限制了集合中每个元素得类型。 后边的类型可以省略
        list.add("java01");
        list.add("hello"); //因为集合中只能添加String类型
        list.add("world"); //因为集合中只能添加String类型

        String s = list.get(0); //在获取元素时 默认就是相应的数据类型 而无需在进行转换

        //<K,V>:K:表示键的泛型  V:表示值的泛型
        HashMap<String,Integer> map=new HashMap<>();
        map.put("name",15);
        map.put("age",25);

        Set<String> keys = map.keySet();
    }

1.3.如何定义泛型类 

public class 类名<标识,标识,....> {

        标识        变量名;

        public 标识   方法名(){

                

        }

.......

}

定义坐标类:

public class Test03 {
    public static void main(String[] args) {
        //在创建泛型类对象时没有指定相应的泛型类型。则默认为Object类型
        Point p1=new Point();
        p1.setX(15);
        p1.setX("北纬50度");

        //这里的泛型必须都是对象类型
        Point<Integer> p2=new Point<Integer>() ;
        p2.setX(25);
        p2.setY(65);
        Integer x = p2.getX();
        Integer y = p2.getY();
        p2.show();

        Point<String> p3=new Point<>();
    }
}
class Point<T>{
     private T x;
     private T y;

     public void show(){
         System.out.println("x坐标为:"+x+";y坐标为:"+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;
    }
}

2. File对象

2.1.File类简介

File 类 就是当前系统中 文件或者文件夹的抽象表示 
    
通俗的讲  就是 使用File对象 来操作我们电脑系统中的文件或者文件夹

学习File类 其实就是学习 如何通过file对象 对系统中的文件/文件夹进行增删改查

 2.2.创建File对象(指定文件路径)

磁盘准备一个目录AAA。以后对文件得操作都放在该目录下

   public static void main(String[] args) {
         /*  path 路径
          Creates a new <code>File</code> instance by converting the given
          pathname string into an abstract pathname.  If the given string is
          the empty string, then the result is the empty abstract pathname
          File(String) 参数为String类型的目标文件路径名
         */
        //创建一个File对象 并指定文件得路径  \转移字符串
        File file01 = new File("D:\\AAA\\aaa.txt");

        /*
           \\目录层级  在window系统下层级分割符为\  但是在linux和mac系统上分割符为 /
           我们得java代码是一种跨平台得语言。 我们得开发在window  但是我们项目得部署在linux.
           我们使我们得代码能在任意系统下来用。 我们有两种解决办法
           (1)第一种 因为window 兼容 / 和 \
         */
        File file02 = new File("D:/AAA/bbb.txt");


        // 第二种 File.separator根据当前代码所在得系统自动获取相应得分割符 

        System.out.println(File.separator); // \因为我们当前在window下
        File file03 = new File("D:"+File.separator+"AAA"+File.separator+"ccc.txt");


    }

2.2.增

package com.qy151.test5;

import java.io.File;
import java.io.IOException;

/**
 * @author : wzh
 * @date 2022/4/19 20:15:07
 */
public class Test2 {
    public static void main(String[] args) throws IOException {
        //创建File对象
        File file1 = new File("D:/BBB/aaa.txt");
        file1.createNewFile();  //创建相应的文件   抛出异常

        File file2 = new File("D:/BBB/AAA");
        file2.mkdir();  //创建目录  make directory  单层目录

        File file3 = new File("D:/BBB/CCC/ddd");
        file3.mkdirs(); //创建多层目录

        File file4 = new File("D:/BBB/eee");
        file4.createNewFile();

        File file5 = new File("D:/BBB/CCC/ddd/eee.mp4");
        file5.createNewFile();
        
        //根据调用的方法不同,创建不同的类型
    }
}

2.3.删

package com.qy151.test5;

import java.io.File;

/**
 * @author : wzh
 * @date 2022/4/19 20:24:26
 */
public class Test3 {
    public static void main(String[] args) throws InterruptedException {
        File file1 = new File("D:/BBB/eee");
        file1.delete();  //删除文件

        File file2 = new File("D:/BBB/bbbb.txt");
        file2.deleteOnExit();   //当程序退出后  删除

        Thread.sleep(5000); //休眠5秒

        File file3 = new File("D:/BBB/AAA");
        file3.delete(); //删除空目录  有文件不能删除
    }
}

2.4.改

package com.qy151.test5;

import java.io.File;
import java.io.IOException;

/**
 * @author : wzh
 * @date 2022/4/19 20:32:14
 */
public class Test4 {
    public static void main(String[] args) throws IOException {
        //改
        File file = new File("D:/BBB/ccc.txt");
        file.createNewFile();       //创建ccc.txt文件

        file.setReadable(false);    //设置该文件的权限为不能读
        file.setWritable(false);    //设置该文件的权限为不能写
        file.setReadOnly(); //设置只读的权限

        file.renameTo(new File("D:/BBB/dddd.txt")); //重命名
        file.renameTo(new File("D:/AAA/dddd.txt")); //写别的路径 是粘贴
    }
}

2.5.查

package com.qy151.test5;

import java.io.File;
import java.util.Arrays;

/**
 * @author : wzh
 * @date 2022/4/19 20:41:29
 */
public class Test5 {
    public static void main(String[] args) {
        File file1 = new File("D:/BBB/CCC/ddd/eee.mp4");

        String name = file1.getName();//得到文件的名称
        System.out.println("name===========>"+name);

//        File parentFile = file1.getParentFile();
//        System.out.println(parentFile);

        String parent = file1.getParent();  //得到父级路径的名称
        System.out.println("paarnt============>"+parent);

        String path = file1.getPath();  //得到文件的路径
        System.out.println("path==============>"+path);

         //  linux中文件都有三权限  读写可执行
        boolean b = file.canExecute();
        boolean b1 = file.canRead();
        boolean b2 = file.canWrite();

        boolean f1 = file1.isFile();  //判断该文件对象是否为文件类型
        System.out.println("f1=============>"+f1);

        boolean f2 = file1.isDirectory();   //判断该文件对象是否为目录类型
        System.out.println("f2=============>"+f2);

        File file2 = new File("D:/BBB");
        String[] list = file2.list();   //列出BBB目录下所有子文件的名称
        System.out.println(Arrays.toString(list));

        File[] files = file2.listFiles();   //列出BBB目录下所有文件对象
        for(File f : files){
            System.out.println(f.toString());
        }
    }
}

经典题目: 用的方法的递归调用。

package com.qy151.test5;

import java.io.File;

/**
 * @author : wzh
 * @date 2022/4/19 20:59:13
 */
public class Test6 {
    public static void main(String[] args) {
        //经典题目: 用的方法的递归调用
        //显示指定目录下的所有文件。D:/BBB下所有的文件.

        showAlLFiles("D:/BBB");
    }
    public static void showAlLFiles(String path){
        //使用传入的路径构建文件对象
        File file = new File(path);
        //判断文件是否存在  或者  文件是否为目录
        if(!file.exists() || !file.isDirectory()){
            return ;
        }
        //列出该目录下所有的文件对象
        File[] files = file.listFiles();
        //遍历数组
        for(File f : files){
            if(f.isDirectory()){
                System.out.println(f.getPath()+"  <Dir>");
                showAlLFiles(f.getPath());  //继续调用该方法
            }else{
                System.out.println(f.getPath()+" ");
            }
        }
    }
}

3.IO流

3.1.IO流概述

1. IO都是全大写 说明肯定是两个单词的首字母
I  : inputstream 输入流     O : outputstream  输出流

2. IO的作用:就是通过java代码 对文件中的内容进行操作。 
  输入: 读操作(读取文件的内容)   输出: 写操作(往文件中写内容)
  所以有一话:   读进来 写出去 


3. IO流的分类:

 (1)根据流的方向:
    ---输入流: 程序可以从中读取数据的流。
    ---输出流: 程序能向其中写入数据的流。
    
 (2)根据流的单位:
    ---字节流: 以字节为单位传输数据的流
    ---字符流: 以字符为单位传输数据的流
 
 (3)根据功能
    ---节点流: 直接和文件进行交互                      ---四大基流
    ---处理流(过滤流): 不是直接作用在文件上。是对一个已存在流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。               ---包装流 
    
四个基本的流: 其他的流都是在这四个流的基础上进行扩展的
        字节输入流
        字节输出流 
    
        字符输入流
        字符输出流

3.2.字符流 

 3.2.1.Writer字符输出流

它是所有字符输出流的跟类。---FileWriter类

package com.qy151.test5;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

/**
 * @author : wzh
 * @date 2022/4/19 21:25:23
 */
public class Test7 {
    public static void main(String[] args) throws Exception {
        //字符输出流  -----指定对那个文件(路径)进行写操作
        Writer writer = new FileWriter("D:/BBB/aaa.txt");

        String str = "Hello AAA 我要学java";
        writer.write(str);

        writer.flush(); //刷新流
        writer.close(); //关闭流资源
    }
}

上面每次往内容中写内容时,就会把原来的内容覆盖了。如何追加内容
 

package com.qy151.test5;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

/**
 * @author : wzh
 * @date 2022/4/19 21:33:59
 */
public class Test8 {
    public static void main(String[] args) throws Exception {
        //字符输出流 ----指定对那个文件(路径)进行写操作
        //true:表示允许追加内容到文件中
        Writer writer = new FileWriter("D:/BBB/aaa.txt",true);

        String str = "你好  我是新添加的内容  Hello Java";
        writer.write(str);

        writer.flush(); //刷新流
        writer.close(); //关闭流资源
    }
}

3.2.2.Reader字符输入流

它是所有字符输入流的根类  它的实现类有很多,我们使用FileReader实现类

package com.qy151.test5;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;

/**
 * @author : wzh
 * @date 2022/4/19 21:39:59
 */
public class Test9 {
    public static void main(String[] args) throws IOException {
        //创建字符输入流对象,作用:就是读取aaa.txt里的内容
        Reader reader = new FileReader("D:/BBB/aaa.txt");
        int count = 0; //表示读取字符的个数
        char[] chars = new char[10];    //每次读取到元素存入该数组中
        while((count=reader.read(chars))!=-1){
            String str = new String(chars,0,count);
            System.out.print(str);
        }

        //但是这种效率会很慢,因为每次只读取一个字符串.
        //那么我们可以一次读取多个字符 并存入一个字符数组中
//        char[] chars = new char[2]; //每次读取2个字符放入该数组中
//        int c = reader.read(chars); //每次读取2个字符放入chars数组中,返回读取的个数
//        System.out.println(c);
//        System.out.println(chars);
//        String s = new String(chars,0,c);   //把字符数组转换为字符串
//        System.out.println(s);
//
//        c = reader.read(chars);
//        System.out.println(c);
//        System.out.println(chars);  //[H,e]--->[l,l]
//        String s1 = new String(chars,0,c);
//        System.out.println(s1);
    }
}

3.2.3.使用字符输入和输出流完成文件内容的复制

要求:D:/BBB/d.txt  复制到 C:/AAA/d.txt.

//junit 单元测试 @Test 相当于每个方法都可以独立的运行等价于main函数。
//完成文件内容的复制功能
//junit 单元测试 @Test 相当于每个方法都可以独立的运行等价于main函数。
@Test
public void test1() throws Exception{
    //1.创建一个字符输入流
    FileReader  fr = new FileReader("D:/BBB/d.txt");

    //2.创建一个字符输出流
    FileWriter fw = new FileWriter("C:/AAA/e.txt");

    int c = 0;//读取到字符的个数
    char[] chars = new char[5];    //每次读取的内容放入到该数组中

    while((c=fr.read(chars))!=-1){
        fw.write(chars,0,c);    //写入chars 从0的位置开始,写c个
        fw.flush();    //刷新流
    }

    fw.close();    //关闭流资源
    fr.close();
}

大家思考:

咱们能不能复制一个电影,图片,压缩文件等,上面的字符流没法对图片和电影或压缩文件等进行操作.因为它只能对文本进行操作.因为视频图片等这些都属于二进制.

字节流与字符流的区别:
 *         字节流操作的基本单元为字节;字符流操作的基本单元为Unicode码元;
 *         字节流默认不使用缓冲区;字符流使用缓冲区 
 *      字节流通常用于处理二进制数据,实际上它可以处理任意类型的数据,但它不支持直接写入或读取        Unicode码元;
 *      字符流通常处理文本数据,它支持写入及读取Unicode码元。
————————————————
版权声明:本文为CSDN博主「农村小白」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44538107/article/details/89923745

3.3.字节流

3.3.1.字节输出流-----OutputStream

它可以对任意文件进行操作,对文件进行输出操作。以字节为单位。 它是所有字节输出流的父类. 

 FileOutputStream

//测试字节输出流
@Test
public void testOutputStream() throws Exception{
    OutputStream os = new FileOutputStream("D:/BBB/d.txt");
   
    String str = "Hello World!!!";
    //把字符串转换为字节数组
    byte[] bytes = str.getBytes();    
    os.write(bytes);

    os.flush();    //刷新流
    os.close();    //关闭流资源
}

3.3.2.字节输入流-----InputStream

它可以对任意文件进行读操作,以字节为单位,它是所有字节输入流的父类,子类有FileInputStream.

//一次一次的读取
@Test
public void testInputStream() throws Exception{
    InputStream is = new FileInputStream("D:/BBB/d.txt");
    
    byte[] bytes = new byte[5];    
    int c = is.read(bytes);    //一次读取五个字节 并把读取的内容放入字节数组bytes中  返回读取到的字节的个数
    System.out.println(bytes+"-------------->个数:"+c);

    c = is.read(bytes);
    System.out.println(bytes+"-------------->个数:"+c);

    c = is.read(bytes);
    System.out.println(bytes+"-------------->个数:"+c);
}


//如果文件中内容非常大   使用循环来读取
@Test
public void testInputStream1() throws Exception{
    InputStream is = new FileInputStream("D:/BBB/d.txt");

    byte[] bytes = new byte[5];
    int c = 0;    //读取到的个数
    while((c=is.read(bytes))!=-1){
        String str = new String(bytes,0,c);
        System.out.print(str);
    }

    is.close();
    
}

3.3.3.使用字节输入和输出完成文件的复制功能

@Test
public void testCopy() throws Exception{
    //1.创建字节输入流  图片
    InputStream is = new FileInputStream("D:/BBB/1.jpg");
    //2.创建字节输出流
    OutputStream os = new FileOutputStream("C:/AAA/1.jpg");

    byte[] bytes = new byte[10];
    int c = 0;

    while((c=is.read(bytes))!=-1){
        os.write(bytes,0,c);
    }

    is.close();
    os.close();
}

3.4.缓存流

缓存流是在四大基础流[ InputStream  OutputStream  Writer  Reader]之上  添加了一个缓存池功能.

BufferedInputStream  BufferedOutputStream  BufferedWriter  BufferedReader  提高IO的效率,降低IO的次数.

3.4.1.字节缓存输出流        ---BufferedOutputStream

@Test
public void TestBuffer() throws Exception{
    OutputStream os = new FileOutputStream("D:/BBB/d.txt");
    BufferedOutputStream bos = new BufferedOutputStream(os);   //缓存流要作用在基础流上
    
    String str = "Hello World!!! 我要睡觉啊";
    byte[] bytes = str.getBytes();    //把字符串转为字节
    bos.write(bytes);   //因为写的内容暂时放入缓存池中  并没有直接放入文件中,所有文件中没有内容

    //bos.flush();    //刷新缓存池 ---- 把缓存池的内容输入到文件上
    bos.close();    //关闭流    -----先刷新缓冲池  再关闭流资源
}

3.4.2. 字节缓存输入流        ----BufferedInputStream

public void testBufferedInputStream() throws IOException {
        InputStream is = new FileInputStream("D:/BBB/a.txt");
        BufferedInputStream bis = new BufferedInputStream(is);//缓存流要作用在基流上
        int c = 0;
        byte[] bytes = new byte[5];
        while((c=bis.read(bytes))!=-1){
            String str = new String(bytes,0,c);
            System.out.print(str+" ");
        }
 }

3.4.3.使用字节缓存输出流和字节缓存输入流完成复制功能 

//字节缓存输入流和字节缓存输出流完成复制
    //Junit @Test单元测试 每个方法都可以独立运行 相当于main函数
    @Test
    public void testCopy2() throws IOException {
        //创建字节缓存输入流
        InputStream is = new FileInputStream("D:/BBB/a.txt");
        BufferedInputStream bis = new BufferedInputStream(is);
        //创建字节缓存输出流
        OutputStream os = new FileOutputStream("D:/BBB/d.txt");
        BufferedOutputStream bos = new BufferedOutputStream(os);
        int c = 0;
        byte[] bytes = new byte[10];
        while((c=bis.read(bytes))!=-1){
            bos.write(bytes,0,c);
            bos.flush();
        }
        bos.close();
        bis.close();
    }

3.5.对象流        ----对Java对象进行IO操作

为什么需要对象流?

我们现在操作IO流的时候  都是将字符串读写操作  可不可以将Java对象在文件中进行读写呢?

可以的        Student student = new Student();对象

//因为运行的时候,所有的数据都是在运行内存中的   持久化  将运行内存的数据 保存到硬盘上   存档(写)  读档(读)

 3.5.1.对象输出流          ------ObjectOutputStream

//public ObjectOutputStream(OutputStream out)throws IOException
@Test    //存档 -----序列化:
public void testObjectStream() throws Exception{
    OutputStream os = new FileOutputStream("D:/BBB/a.txt");
    //对象输出流    ObjectOutputStream
    ObjectOutputStream oos = new ObjectOutputStream(oos);    //对象流在基流上使用
    
    //使用对象输出流调用输出方法  输出的类的对象  该类必须实现Serializable 序列化接口
    Role r = new Role("吕布","10级",1,"战四娘");
    oos.writeObject(r);
    oos.close();  
}

3.5.2.对象输入流         ------ObjectInputSteam

@Test    //读档:    -----反序列化
public void testObjectStream() throws Exception{
    InputStream is = new FileInputStream("D:/BBB/a.txt");
    //对象输入流    -----ObjectInputStream
    ObjectInputStream ois = new ObjectInputStream(is);
    Object o = ois.readObject();

    System.out.println(o);
    ois.close();
}


//读取多个对象
@Test
    public void testObjectInputStream() throws IOException, ClassNotFoundException {
        InputStream is = new FileInputStream("D:/BBB/a.txt");
        ObjectInputStream ois = new ObjectInputStream(is);
        //readObject()读取到文件最后会有java.io.EOFException异常(读取不到对象),
        // 进行try{}catch(){}捕捉即可
        while(true) {
            try {
                Teacher o = (Teacher) ois.readObject();
                System.out.println(o);
            }catch(EOFException e){
                System.out.println("读取完毕");
                break;
            }
        }
        ois.close();
    }

1.序列化:把内存中的java对象存储到磁盘(网盘)的过程

               -------java对象所属的类必须实现序列化接口:implements Serializable

2.反序列化:把磁盘中的内容读取到java对象内存中的过程

序列化:是对象转换成一个字节序列的过程,是一个写操作。

反序列化:一个字节序列转换成对象的过程,是一个读操作。

Serializable:序列化接口
如果想将对象序列化,那么对象的类型必须实现此接口。此接口内什么都没有,只是一个序列化标识。

3.5.3.总结

1.  通过字符流完成文件的复制---->它只能复制文本文件
2.  字节流:---字节输入流和字节输出流。
3.  字节流 我们也可以完成文件的复制功能---它可以复制任意类型的文件.
4.  缓存流--->它基本流的基础上 添加了一个缓存池 
5.  对象流: ObjectInputStream  ObjectOutputStream
     序列化:把内存中的java对象存储到磁盘(网盘)的过程

               -------java对象所属的类必须实现序列化接口:implements Serializable

     反序列化:把磁盘中的内容读取到java对象内存中的过程

因为文件里的文本内容无法确定,所以如果是文本内容,建议还是用字符流

完结!!!!! 

感谢观看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值