Java之IO流

异常机制Exception

异常

指程序中出现的不期而至的各种情况:文件找不到、网络连接失败、非法参数等。

在这里插入图片描述

异常处理

try…catch…
try{
    //尝试执行的代码
}catch(Exception e//想要捕获的异常类型){
       //出现异常之后的处理代码
       //可以有多个catch(){}最大的异常要放在后面
       }finally{
           //一定会执行的代码,例如关闭资源
           //即是try...catch...中有return,finally也会执行
           //可以不要finally
       }
       
//特点:处理完异常后,程序继续执行
throws(抛出,调用者处理)
  1. 调用者处理方案(两种)
    • 接着抛出
    • 采用try…catch…
  2. 特点:执行结束后,程序不再继续执行

自定义异常

步骤
  1. 创建自定义异常类(继承Exception类);
  2. 在方法中通过throw关键字抛出异常对象;
  3. 如果在当前抛出异常的方法中处理异常,可以使用try…catch…语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作;
  4. 在出现异常方法的调用者中捕获并处理异常。

IO流

IO流能干什么

在本地磁盘和网络上操作数据

流:内存与存储设备之间传输数据的通道

IO流分类

  1. 按数据流向分为
    • 输入流
    • 输出流
  2. 按操作方式分
    • 字节流:以字节为单位可以读写所有数据
    • 字符流:以字符为单位只能读写文本数据
  3. 按功能分
    • 节点流:具有实际传输数据的读写功能
    • 过滤流:在字节流的基础之上增强功能

IO流体系

在这里插入图片描述

在这里插入图片描述

InputStream、OutputStream、Reader、Writer均为抽象类

字节流读写文件

字节流拷贝文件——按单个字节读写

  1. 创建字节流读文件对象
InputStream is = new FileInputStream("1.jpg");
  1. 创建字节流写文件对象
OutputStream os = new FileOutputStream("2.jpg");
  1. 异常处理

  2. 使用while循环读写数据

int b;
while((b = is.read())!=-1){
    os.write(b);
}
  1. 关闭资源
is.close();
os.close();

字节流拷贝文件——按字节数组读写

  1. 创建字节流读文件对象
InputStream is = new FileInputStream("1.jpg");
  1. 创建字节流写文件对象
OutputStream os = new FileOutputStream("2.jpg");
  1. 异常处理

  2. 使用字节数组读写数据

byte[] b = new byte[2048];

int len;

while((len = is.read(b))!=-1){
    os.write(b,0,len);
}
  1. 关闭资源
is.close();os.close();

字节缓冲流拷贝文件

  1. 创建字节缓冲流读文件对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.jpg"));//节点流/底层流
  1. 创建字节流写文件对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2.jpg"));
  1. 异常处理

  2. 读写数据

int len;while((len = bis.read())!=-1){//bis本身其实有缓冲区了,也可以自己创建一个缓冲区byte[] buf = new byte[2048];    bos.write(len);//先写入缓冲区    bos.flush();//刷新操作}
  1. 关闭资源
bis.close();bos.close();//内部会调用flush()方法,所有上面那里可以不用刷新

缓冲流

  1. 提高IO效率,减少访问磁盘的次数;
  2. 数据存储在缓冲区中,flush()是将缓冲区的内容写入文件中,也可以之间close()

实例一:FileInputStream的使用

package com.io.first;import java.io.FileInputStream;/** * FileInputStream的使用 * 文件输入字节流 */public class Demo01 {    public static void main(String[] args) throws Exception {        //1.创建FileInputStream,并指定文件路径        FileInputStream fis = new FileInputStream("d:\\aaa.txt");//需要异常处理        //2.读取文件read()        //2.1单个字节读取//        int b;//        while ((b=fis.read())!=-1) {//            System.out.print((char) b);//        }//        System.out.println();//        System.out.println("执行完毕");        //2.2一次读取多个字节        byte[] buf = new byte[1024];        int len = 0;        while ((len = fis.read(buf))!=-1) {            //String(byte[] byte,int start,int length)将字节数组转换成字符串的带三个参数的构造函数            System.out.println(new String(buf,0,len));        }        System.out.println("执行完毕");        //关闭资源        fis.close();    }}

实例二:FileOutputStream的使用

package com.io.first;import java.io.FileOutputStream;import java.nio.charset.StandardCharsets;public class Demo02 {    public static void main(String[] args) throws Exception {        //第二个参数可以不用写,表示每次执行都是将上次写入的覆盖掉        //true表示再次执行是继续写入没有覆盖        FileOutputStream fos = new FileOutputStream("d:\\bbb.txt",true);        //单字节写入//        fos.write(97);//        fos.write('b');//        fos.write('c');//        System.out.println("执行完毕");        //多字节写入        String s = "hello world";        fos.write(s.getBytes(StandardCharsets.UTF_8));        System.out.println("执行完毕");        //关闭资源        fos.close();    }}

实例三:通过字节流拷贝文件

package com.io.first;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;/** * 通过文件字节流拷贝文件 */public class Demo03 {    public static void main(String[] args) throws IOException {        //创建文件输入字节流对象        FileInputStream fis = new FileInputStream("d:\\h1.jpg");        //创建文件输出字节流对象        FileOutputStream fos = new FileOutputStream("d:\\h2.jpg");        //多字节读入        int len;        byte[] buf = new byte[1024];        while ((len = fis.read(buf))!=-1) {            fos.write(buf,0,len);        }        //关闭资源        fis.close();        fos.close();        System.out.println("拷贝完毕");    }}

实例四:BufferedInputStream的使用

package com.io.second;import java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.IOException;/** * BufferedInputStream的使用 */public class Demo1 {    public static void main(String[] args) throws IOException {        FileInputStream fis = new FileInputStream("d:\\aaa.txt");        BufferedInputStream bis = new BufferedInputStream(fis);        int data;        while ((data = bis.read())!=-1) {            System.out.print((char) data);        }        //关闭资源        bis.close();    }}

实例五:BufferedOutputStream的使用

package com.io.second;import java.io.BufferedOutputStream;import java.io.FileOutputStream;import java.io.IOException;import java.nio.charset.StandardCharsets;/** * BufferedOutputStream的使用 */public class Demo2 {    public static void main(String[] args) throws IOException {        FileOutputStream fos = new FileOutputStream("d:\\ccc.txt");        BufferedOutputStream bos = new BufferedOutputStream(fos);        for (int i = 0;i < 3;i++){            bos.write("hello world\r\n".getBytes(StandardCharsets.UTF_8));            bos.flush();        }        System.out.println("执行完毕");        bos.close();    }}

实例六:字节缓冲流拷贝文件

package com.io.second;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;/** * 字节缓冲流拷贝文件 */public class Demo3 {    public static void main(String[] args) throws Exception {        BufferedInputStream bis = new BufferedInputStream                (new FileInputStream("d:\\h2.jpg"));        BufferedOutputStream bos = new BufferedOutputStream                (new FileOutputStream("d:\\h3.jpg"));        int len;        while ((len = bis.read())!=-1) {            bos.write(len);            bos.flush();        }        //关闭资源        bis.close();        bos.close();        System.out.println("拷贝完成");    }}

字符流读写文件

字符流读数据——按单个字符读取

  1. 创建字符流读文件对象
Reader reader = new FileReader("a.txt");
  1. 异常处理

  2. 使用while循环读数据

int ch;while((ch = reader.read())!=-1){    System.out.println(ch);}
  1. 关闭资源
reader.close();

字符流读数据——按字符数组读取

  1. 创建字符流读文件对象
Reader reader = new FileReader("a.txt");
  1. 异常处理

  2. 读数据

char[] chs = new char[1024];int len;while((len = reader.read(chs))!=-1){    String s = new String(chs,0,len);//chs表示要操作的数组;0表示起始索引;len表示要操作的字符个数    System.out.println(s);}
  1. 关闭资源
reader.close();

字符流写数据——按单个字符写入

  1. 创建字符流写文件对象
Writer writer = new FileWriter("b.txt");
  1. 异常处理

  2. 写数据

writer.write('中');//写一个字符
  1. 关闭资源
writer.close();

字符流写数据——按字符数组写入

  1. 创建字符流写文件对象
Writer writer = new FileWriter("b.txt");
  1. 异常处理

  2. 写数据

char [] chs = {'a','b','c','d'};fw.write(chs);
  1. 关闭资源
writer.close();

字符流写数据——按字符串写入

  1. 创建字符流写文件对象
Writer writer = new FileWriter("b.txt");
  1. 异常处理

  2. 写数据

String s = "好好学习";fw.write(s);
  1. 关闭资源
writer.close();

字符流拷贝文件——按单个字符读写

  1. 创建字符流读文件对象
Reader reader = new FileReader("a.txt");
  1. 创建字符流写文件对象
Writer writer = new FileWriter("b.txt");
  1. 拷贝数据
int data = reader.read();writer.write(data);
  1. 异常处理
  2. 关闭资源
reader.close();writer.close();

字符流拷贝文件——按字符数组读写

  1. 创建字符流读文件对象
Reader reader = new FileReader("a.txt");
  1. 创建字符流写文件对象
Writer writer = new FileWriter("b.txt");
  1. 拷贝数据
char[] chs = new char[1024];int len = reader.read(chs);writer.write(chs,0,len);
  1. 异常处理
  2. 关闭资源
reader.close();writer.close();

字符缓冲流拷贝文件

  1. 创建字符缓冲流读文件对象
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
  1. 创建字符缓冲流写文件对象
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
  1. 拷贝数据
int len;while((len = br.read())!=-1){    bw.write(len);}
  1. 异常处理
  2. 关闭资源
br.close();bw.close();

字符缓冲流——一次读写一行(独有用法)

  1. 创建字符缓冲流读文件对象
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
  1. 创建字符缓冲流写文件对象
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
  1. 拷贝数据
String str;while((str = br.readLine())!=null){    bw.write(str);    bw.newLine();//根据系统给操作符,写入一个行分隔符(换行符)}
  1. 异常处理
  2. 关闭资源
br.close();bw.close();

实例一:字符流读数据——按单个字符读取

package com.io.fourth;import java.io.FileReader;/** * 字符流读数据——按单个字符读取 * FileReader的使用 */public class Demo01 {    public static void main(String[] args) throws Exception{        //创建对象        FileReader fr = new FileReader("d:\\aaa.txt");        int data;        while ((data = fr.read())!=-1) {            System.out.print((char) data);        }        //关闭资源        fr.close();    }}

实例二:字符流读数据——按字符数组读取

package com.io.fourth;import java.io.FileReader;/** * 字符流读数据——按字符数组读取 * FileReader的使用 */public class Demo02 {    public static void main(String[] args) throws Exception{        //创建对象        FileReader fr = new FileReader("d:\\aaa.txt");        char [] chs = new char[1024];        int len = 0;        while ((len = fr.read(chs))!=-1) {            String s = new String(chs,0,len);            System.out.println(s);        }        //关闭资源        fr.close();    }}

实例三:FileWriter的用法

package com.io.fourth;import java.io.FileWriter;/** * 字符流写数据 * FileWriter的用法 */public class Demo03 {    public static void main(String[] args) throws Exception{        FileWriter fw = new FileWriter("d:\\ddd.txt");        //按单个字符写入        for (int i = 0; i < 3; i++) {            fw.write('中');        }        //按字符数组写入        char [] chs = {'a','b','c','d'};        fw.write(chs);        //按字符串写入        String s = "好好学习";        fw.write(s);        System.out.println("执行完毕");        //关闭资源        fw.close();    }}

实例四:字符缓冲流拷贝文件

package com.io.fourth;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;/** * 字符缓冲流拷贝文件 * 只能拷贝文本文件 * 不能拷贝图片二进制文件(用字节流拷贝) */public class Demo04 {    public static void main(String[] args) throws Exception{        //创建字符流读文件对象        BufferedReader br = new BufferedReader                (new FileReader("d:\\aaa.txt"));        //创建字符流写文件对象        BufferedWriter bw = new BufferedWriter                (new FileWriter("d:\\bbb.txt"));        //单个字符拷贝        int data;        while ((data = br.read())!=-1) {            bw.write(data);            bw.flush();        }        System.out.println("拷贝完成");        //关闭资源        br.close();        bw.close();    }}

实例五:字符缓冲流独有用法——一次读写一行

package com.io.fourth;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;/** * 字符缓冲流独有用法——一次读写一行 */public class Demo05 {    public static void main(String[] args) throws Exception{        BufferedReader br = new BufferedReader                (new FileReader("d:\\ddd.txt"));        BufferedWriter bw = new BufferedWriter                (new FileWriter("d:\\e.txt"));        String s;        while ((s = br.readLine())!=null){            bw.write(s);            bw.newLine();//写入一个换行符        }        System.out.println("拷贝完成");        //关闭资源        br.close();        bw.close();    }}

对象流

ObjectOutputStream/ObjectInputStream

功能

  1. 增强了缓冲区功能;
  2. 增强了读写8种基本数据类型和字符串功能;
  3. 增强了读写对象的功能:
    • readObject() 从流中读取一个对象(反序列化)
    • writeObject() 向流中写入一个对象(序列化)

使用流传输对象的过程称为序列化、反序列化

注意点

  1. 对象要实现Serializable接口才能序列化(该接口是标记接口:无方法、无常量);
  2. 其中的属性也要实现该接口;
  3. serialVersionUID:序列化版本号ID,保证序列化的类和反序列化的是同一个类;
  4. 使用transient(瞬间的)修饰属性,该属性不能被序列化;
  5. 静态属性也不能序列化;
  6. 序列化多个对象时,可以借助集合实现。

实例一:序列化

//Student类package com.io.third;import java.io.Serializable;public class Student implements Serializable {    private String name;    private int age;    public Student() {    }    public Student(String name, int age) {        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    @Override    public String toString() {        return "Student{" +                "name='" + name + '\'' +                ", age=" + age +                '}';    }}

Student类的序列化

package com.io.third;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;/** * 对象的序列化 * ObjectOutputStream的使用 * 对象要实现Serializable接口 */public class Demo01 {    public static void main(String[] args) throws IOException {        ObjectOutputStream oos = new ObjectOutputStream                (new FileOutputStream("d:\\stu.bin"));        Student s = new Student("张三",18);        oos.writeObject(s);        System.out.println("执行完毕");        oos.close();    }}

实例二:反序列化

package com.io.third;import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;/** * 反序列化 * ObjectInputStream的使用 */public class Demo02 {    public static void main(String[] args) throws Exception {        ObjectInputStream ois = new ObjectInputStream                (new FileInputStream("d:\\stu.bin"));        Student s =(Student) ois.readObject();        ois.close();        System.out.println("执行完毕");        System.out.println(s.toString());    }}

常见字符编码

  • IS0-8859-1
  • UTF-8 针对Unicode码表的可变长度字符编码
  • GB2312 简体中文
  • GBK 简体中文、扩充
  • BIG5台湾 繁体中文

当编码方式和解码方式不一致时,会出现乱码

打印流

  1. 封装了print()/println()方法,支持写入后换行;
  2. 支持数据原样打印
  3. 可以用该流将一些数据打印到文件中

实例

package com.io.fourth;import java.io.PrintWriter;/** * 打印流 * PrintWriter的使用 * (1)封装了print() println()方法,支持写入后换行 * (2)支持数据以原样打印 */public class Demo06 {    public static void main(String[] args) throws Exception{        PrintWriter pw = new PrintWriter("d:\\a.txt");        pw.println(97);        pw.println('c');        pw.println(3.14);        pw.println("hello");        System.out.println("执行完毕");        //关闭资源        pw.close();    }}

(桥)转换流

InputStreamReader/OutputStreamWriter

  1. 可将字节流–>字符流;
  2. 可设置字符的编码方式

实例

package com.io.fourth;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.nio.charset.StandardCharsets;/** * 转换流,可指定使用的编码 * 可将字节流转换成字符流 * 可设置字符的编码方式 */public class Demo07 {    public static void main(String[] args) throws Exception{        //读文件        InputStreamReader isr = new InputStreamReader                (new FileInputStream("d:\\ccc.txt"), StandardCharsets.UTF_8);        int data;        while ((data = isr.read())!=-1) {            System.out.print((char) data);        }        //写文件        OutputStreamWriter osr = new OutputStreamWriter                (new FileOutputStream("d:\\c.txt"), "gbk");        for (int i = 0; i < 10; i++) {            osr.write("我爱中国\r\n");        }        System.out.println("执行完毕");        //关闭资源        isr.close();        osr.close();    }}

File类

代表物理盘符中的一个文件或文件夹

构造方法

  • File(String pathname)
  • File(String parent,String child)
  • File(File parent,String child)

成员方法

  • createNewFile() 创建文件,不存在则创建,存在返回false
  • mkdir() mkdirs() 创建目录,不存在则创建,存在返回false
  • isDirectory() 判断File对象是否是目录(文件夹)
  • isFile() 判断File对象是否是文件
  • exists() 判断File对象是否存在
  • delete() 删除文件或空目录
  • getAbsolutePath() 获取绝对路径
  • getPath() 获取文件的相对路径
  • getName() 获取文件名
  • list() 获取指定目录下所有文件(夹)名称数组
  • listFiles() 获取指定目录下所有文件(夹)File数组
  • length() 获取文件的长度
  • renameTo() 修改文件名

File类的使用

package com.io.five;import java.io.File;import java.io.FileFilter;import java.util.Date;/** * File类的使用 * (1)分隔符 * (2)文件操作 * (3)文件夹操作 */public class FileDemo {    public static void main(String[] args) throws Exception {        getSeparator();//分隔符        fileOperator();//文件操作        dirOperator();//文件夹操作    }    //分隔符    public static void getSeparator() {        System.out.println("路径分隔符:"+ File.pathSeparator);        System.out.println("名称分隔符:"+File.separator);    }    //文件操作    public static void fileOperator() throws Exception{        //1.创建文件        //先创建File对象        File file = new File("D:\\file.txt");        //创建文件        if (!file.exists()) {            boolean newFile = file.createNewFile();            System.out.println("文件创建结果:"+newFile);        }        //2.删除文件        //2.1直接删除//        System.out.println("删除结果"+file.delete());        //2.2通过jvm退出时删除//        file.deleteOnExit();//        Thread.sleep(5000);//休眠        //3.获取文件信息        System.out.println("获取文件的相对路径:"+file.getAbsolutePath());        System.out.println("获取文件路径:"+file.getPath());        System.out.println("获取文件名称:"+file.getName());        System.out.println("获取文件父目录:"+file.getParent());        System.out.println("获取文件长度:"+file.length());        System.out.println("获取文件创建时间:"+new Date(file.lastModified()).toLocaleString());        //4.判断        System.out.println("是否可写:"+file.canWrite());        System.out.println("是否是文件:"+file.isFile());        System.out.println("是否隐藏:"+file.isHidden());    }    //文件夹操作    public static void dirOperator() throws Exception {        //1.创建文件夹        File dir = new File("d:\\aaa\\bbb\\ccc");//多级文件夹        if (!dir.exists()) {            //dir.mkdir()只能创建单级文件夹            System.out.println("创建结果:"+dir.mkdirs());        }        //2.删除文件夹        //2.1直接删除(只能删除最底层的文件夹且为空时才能删除)//        System.out.println("删除结果:"+dir.delete());        //2.2通过jvm退出时删除//        dir.deleteOnExit();//        Thread.sleep(5000);        //3.获取文件夹信息        System.out.println("获取文件夹绝对路径:"+dir.getAbsolutePath());        System.out.println("获取文件夹路径:"+dir.getPath());        System.out.println("获取文件夹名称(最里层):"+dir.getName());        System.out.println("获取文件夹父目录:"+dir.getParent());        System.out.println("获取文件夹的创建时间:"+ new Date(dir.lastModified()).toLocaleString());        //4.判断        System.out.println("是否是文件夹:"+dir.isDirectory());        System.out.println("是否被隐藏:"+dir.isHidden());        System.out.println("-----------------------------");        //5.遍历文件夹        File dir1 = new File("C:\\Users\\WIN\\Pictures\\toonme");        String[] files = dir1.list();        for (String file : files) {            System.out.println(file);        }        System.out.println("----------FileFilter接口的使用-------------");        File[] files1 = dir1.listFiles(new FileFilter() {            @Override            public boolean accept(File pathname) {                if (pathname.getName().endsWith(".jpg")) {                    return true;                }                return false;            }        });        for (File file : files1) {            System.out.println(file.getName());        }    }}

FileFilter接口

  1. public interface FileFilter{	boolean accept(File pathname);}
    
  2. 当调用File类中的listFiles()方法时,支持传入FileFilter接口实现类,对获取文件进行过滤,只有满足条件的文件才可出现在listFiles()的返回值中

package com.io.five;import java.io.File;/** * 案例:通过递归遍历文件夹、删除文件夹 */public class FileDemo1 {    public static void main(String[] args) {        listDir(new File("D:\\新建文件夹"));        deleteDir(new File("D:\\新建文件夹"));    }    //案例一:通过递归遍历文件夹    public static void listDir(File dir) {        File[] files = dir.listFiles();        System.out.println(dir.getAbsoluteFile());        if (files.length > 0 && files!=null) {            for (File file : files) {                if (file.isDirectory()) {                    listDir(file);//递归调用                } else {                    System.out.println(file.getAbsoluteFile());                }            }        }    }    //案例二:通过递归删除文件夹    public static void deleteDir(File dir) {        File[] files = dir.listFiles();        if (files!=null && files.length > 0) {            for (File file : files) {                if (file.isDirectory()) {                    deleteDir(file);                } else {                    System.out.println(file.getAbsoluteFile()+"的删除结果:"+file.delete());                }            }        }        System.out.println(dir.getAbsoluteFile()+"的删除结果:"+dir.delete());    }}

Properties(属性集合)

  1. 存储属性名和属性值;
  2. 属性名和属性值都是字符串类型;
  3. 没有泛型;
  4. 和流有关
package com.io.five;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.PrintWriter;import java.util.Map;import java.util.Properties;import java.util.Set;/** * Properties集合的使用 */public class PropertiesDemo {    public static void main(String[] args) throws Exception{        //1.创建集合        Properties properties = new Properties();        //2.添加元素        properties.setProperty("username","alice");        properties.setProperty("age","20");        //3.遍历元素        //3.1keySet()方法        System.out.println("-----keySet()方法-----");        for (Object o : properties.keySet()) {            System.out.println(o+"="+properties.get(o));        }        //3.2entrySet()方法        System.out.println("-----entrySet()方法-----");        for (Map.Entry<Object,Object> entry :properties.entrySet()) {            System.out.println(entry.getKey()+"="+entry.getValue());        }        //3.3stringPropertyNames()方法        System.out.println("-----stringPropertyNames()方法-----");        for (String s:properties.stringPropertyNames()) {            System.out.println(s+"="+properties.getProperty(s));        }        //4.和流有关的方法        //4.1 list()方法        PrintWriter pw = new PrintWriter("d:\\print.txt");        properties.list(pw);        pw.close();        //4.2 store()方法 保存//        FileOutputStream fos = new FileOutputStream("d:\\store.properties");//        properties.store(fos,"注释");//        fos.close();        //4.3 load()方法 加载        FileInputStream fis = new FileInputStream("d:\\store.properties");        Properties properties1 = new Properties();        properties1.load(fis);        System.out.println(properties1);    }}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值