Java-day26(IO流)

Java IO原理

在这里插入图片描述

流的分类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一、流的分类:
按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
按数据流的流向不同分为:输入流,输出流
按流的角色的不同分为:节点流,处理流

二、流的体系结构:
在这里插入图片描述
InputStream & Reader
在这里插入图片描述
InputStream
在这里插入图片描述
Reader
在这里插入图片描述
OutputStream & Writer
在这里插入图片描述
OutputStream
在这里插入图片描述
Writer
在这里插入图片描述
三、输入、输出的标准化过程
输入过程:
① 创建File类的对象,指明读取的数据的来源。(要求此文件一定要存在)
② 创建相应的输入流,将File类的对象作为参数,传入流的构造器中
③ 具体的读入过程:
创建相应的byte[ ] 或 char[ ]
④关闭流资源
说明:程序中出现的异常需要使用 try-catch-finally处理。

输出过程:
① 创建File类的对象,指明写出的数据的来源。(不要求此文件一定要存在)
② 创建相应的输出流,将File类的对象作为参数,传入流的构造器中
③ 具体的读入过程:
write(char[ ]/byte[ ] buffer,0,len)
④关闭流资源
说明:程序中出现的异常需要使用 try-catch-finally处理。

节点流(或文件流)

在这里插入图片描述

读数据的操作:

/**
 * @author acoffee
 * @create 2020-10-18 18:19
 */
public class FileReaderWinterTest {
    /*
     * 将day26下的hello.txt文件内容读入控制台,并输出到控制台
     * 说明点:
     * 1.read()的理解:返回并读入一个字符。如果达到文件末尾,返回-1.
     * 2.异常的处理:为了保证刘子源一定可以执行关闭操作。需要使用try-catch-finally处理
     * 3.读入的文件一定要存在,否则就会报FileNotFoundException。
     * */
    @Test
    public void testFileReader() {
        FileReader fr = null;
        try {
            //1.实例化File类的对象,指明要操作的文件
            File file = new File("hello.txt");//相较于工程文件
            //2.提供具体的流
            fr = new FileReader(file);

            int data;
            while ((data = fr.read()) != -1) {
                System.out.print((char) data);//helloworld!!
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //流的关闭
                if (fr != null) {// 这里使用if语句去判断是因为如果fr = new FileReader(file);
                                 // 这个语句出现了异常,程序就会直接出去,从而导致对象是不能实例化
                                 // 所以就不存在fr对象了,然后去执行finally中的代码,
                                 // 所以如果我们以上来就去fr.close()的话就会报异常所以
                                 // 我们就应该先去判断对象是否实例化。            fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


    //对read() (上述方法) 操作进行升级:使用read的重载方法
    @Test
    public void testFileReader1()  {
        FileReader fr = null;
        try {
            //1.File类的实例化
            File file = new File("hello.txt");

            //2.FileReader流的实例化
            fr = new FileReader(file);

            //3.读入的具体的操作细节
            //read(char[] cbuf):返回每次读入cbuf数组中的字符的个数。
            //如果达到文件末尾,返回-1
            char[] cbuf = new char[5];
            int len;
            while ((len = fr.read(cbuf)) != -1) {
                //方式一:
                //错误的写法
//                for (int i = 0; i < cbuf.length; i++) {
//                    System.out.print(cbuf[i]);//helloworld!!rld
//                }
                //正确的写法
//                for (int i = 0; i < len; i++) {
//                    System.out.print(cbuf[i]);//helloworld!!
//                }

                //方式二:
                //错误的方法:同方式一的错误方法
//                String str = new String(cbuf);
//                System.out.print(cbuf);//helloworld!!rld
                //正确的写法
                String str = new String(cbuf, 0, len);
                System.out.print(str);//helloworld!!


            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.流资源的关闭
            try {
                if (fr != null)
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

写入数据的操作

    /*
* 从内存中写出数据到硬盘的文件里
* 说明:
* 1.输出操作,对应的File可以不存在。
* File对应的硬盘的文件如果不存在:在输出的过程中,会自动创建文件
*   File对应的硬盘的文件如果存在:
*       如果流使用的构造器是:FileWriter(file,false) / FileWriter(file):对原有文件的覆盖
        如果流使用的构造器是:FileWriter(file,true):不会对原有文件覆盖,而是在原有文件基础上追加内容
* */
    @Test
    public void testFielWinter() {
        FileWriter fileWriter = null;
        try {
            //1.提供File类的对象,指明写出到的文件
            File file = new File("hello.txt");

            //2.提供FileWinter的对象,用于数据的写出
            //这里写true就不会原来文件的内容进行覆盖,会跟到后面写
            //这里如果写false会对文件进行覆盖,跟不写的情况一样
            fileWriter = new FileWriter(file,true);


            //3.写出的操作
            fileWriter.write("I have a dream\n");
            fileWriter.write("you need to have a dream");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.流资源的关闭
            try {
                if (fileWriter != null){
                fileWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

读取和写出的操作(复制文本)

    @Test
    public void testFileReaderFileWinter(){
        FileReader fileReader = null;
        FileWriter fileWriter = null;
        try {
            //1.创建File类的对象,指明读入和写出的文件
            File srcFile = new File("hello.txt");
            File destFile = new File("hello2.txt");

            //2.创建输入流和输出流的对象
            fileReader = new FileReader(srcFile);
            fileWriter = new FileWriter(destFile);

            //3.数据的读入和写出操作
            char[] cbuf = new char[5];
            int len;
            while ((len = fileReader.read(cbuf)) != -1){
                //每次写出len个字符
                fileWriter.write(cbuf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //4.关闭流资源
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

上述的字符流是不能处理图片文件的

字节流处理图片的操作

    @Test
    public void testFileInputOutputStream() throws IOException {
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            File file = new File("爱情与友情.jpg");
            File file1 = new File("爱情与友情2.jpg");

            fileInputStream = new FileInputStream(file);
            fileOutputStream = new FileOutputStream(file1);

            byte[] bytes = new byte[5];
            int len;
            while ((len = fileInputStream.read(bytes)) != -1) {
                fileOutputStream.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (IOException e) {

                e.printStackTrace();

            }

            try {
                if (fileInputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

指定路径

    //指定路径下的文件的复制
    public void copyFile(String secFile,String DestFile){
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            File file = new File(secFile);
            File file1 = new File(DestFile);

            fileInputStream = new FileInputStream(file);
            fileOutputStream = new FileOutputStream(file1);

            byte[] bytes = new byte[5];
            int len;
            while ((len = fileInputStream.read(bytes)) != -1) {
                fileOutputStream.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (IOException e) {

                e.printStackTrace();

            }

            try {
                if (fileInputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void testCopyFile(){

        long start = System.currentTimeMillis();

        String srcPath = "C:\\Users\\acoffee\\Desktop\\M35DIIQRON9BL91%SVLTVAE.png";
        String destPath = "C:\\Users\\acoffee\\Desktop\\M35DIIQRON9BL91%SVLTVAE1.png";
        copyFile(srcPath,destPath);

        long end = System.currentTimeMillis();

        System.out.println("复制操作花费的时间为:" + (end - start));//160

    }

缓冲流

缓冲流(提高文件的读写效率)
在这里插入图片描述
在这里插入图片描述

内部提供了缓冲区,存入缓冲区中达到了最大值,一次性的读出.所以能提高效率。flush( )方法刷新缓冲区。

/**
 * 处理流之一缓冲流的使用
 * <p>
 * 1.缓冲流:
 * BufferInputStream
 * BufferOnputStream
 * BufferReader
 * BufferWinter
 * 
 * 作用:
 * 1.内部提供了缓冲区,存入缓冲区中达到了最大值,一次性的读出.
 *
 * @author acoffee
 * @create 2020-10-18 21:34
 */
public class BufferdTest {

    /*
     * 实现非文本文件的复制
     * */
    @Test
    public void BufferedStreamTest() {
        BufferedInputStream bufferedInputStream = null;
        BufferedOutputStream bufferedOutputStream = null;

        try {
            //1.造文件
            File srcFile = new File("爱情与友情.jpg");
            File destFile = new File("爱情与友情3.jpg");

            //2.造流
            //2.1造节点流
            FileInputStream fileInputStream = new FileInputStream(srcFile);
            FileOutputStream fileOutputStream = new FileOutputStream(destFile);
            //2.2造缓冲流
            bufferedInputStream = new BufferedInputStream(fileInputStream);
            bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

            //3.复制的细节:读取、写入
            byte[] bytes = new byte[5];
            int len;
            while ((len = bufferedInputStream.read(bytes)) != -1) {
                bufferedOutputStream.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.资源关闭
            //要求:先关闭外层的流,在关闭内层的流(像脱衣服一样)
            try {
                if (bufferedOutputStream != null) {
                    bufferedOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (bufferedInputStream != null) {
                    bufferedInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        //说明:关闭外层流的同时,内层也会自动的进行关闭。关于内层刘的关闭在这里我们可以省略。
//        fileOutputStream.close();
//        fileInputStream.close();
    }
}

与字节流的效率对比(160 - 31)

    //实现文件复制的方法
    public void copyFileWithBuffered(String srcFile,String destFile){
        BufferedInputStream bufferedInputStream = null;
        BufferedOutputStream bufferedOutputStream = null;

        try {
            //1.造文件
            File srcFile1 = new File(srcFile);
            File destFile1 = new File(destFile);

            //2.造流
            //2.1造节点流
            FileInputStream fileInputStream = new FileInputStream(srcFile);
            FileOutputStream fileOutputStream = new FileOutputStream(destFile);
            //2.2造缓冲流
            bufferedInputStream = new BufferedInputStream(fileInputStream);
            bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

            //3.复制的细节:读取、写入
            byte[] bytes = new byte[5];
            int len;
            while ((len = bufferedInputStream.read(bytes)) != -1) {
                bufferedOutputStream.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.资源关闭
            //要求:先关闭外层的流,在关闭内层的流(像脱衣服一样)
            try {
                if (bufferedOutputStream != null) {
                    bufferedOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (bufferedInputStream != null) {
                    bufferedInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    @Test
    public void testCopyFile(){

        long start = System.currentTimeMillis();

        String srcPath = "C:\\Users\\acoffee\\Desktop\\M35DIIQRON9BL91%SVLTVAE.png";
        String destPath = "C:\\Users\\acoffee\\Desktop\\M35DIIQRON9BL91%SVLTVAE1.png";
        copyFileWithBuffered(srcPath,destPath);

        long end = System.currentTimeMillis();

        System.out.println("复制操作花费的时间为:" + (end - start));//31

    }

字符缓冲流

    /*
    * 使用BufferedReader和BufferedWriter实现文本文件的复制
    *
    * */
    @Test
    public void testBufferedReaderBufferedWriter() throws IOException {
        BufferedReader bufferedReader = null;
        BufferedWriter bufferedWriter = null;
        try {
            bufferedReader = new BufferedReader(new FileReader(new File("dbcp.txt")));
            bufferedWriter = new BufferedWriter(new FileWriter(new File("dcbp1.txt")));

            //读写操作
//            char[] chars = new char[1024];
//            int len;
//            while ((len = bufferedReader.read(chars)) != -1){
//                bufferedWriter.write(chars,0,len);
//            }

            //方式二:使用String
            String data;
            while ((data = bufferedReader.readLine()) != null){
                //bufferedWriter.write(data+"\n");//data中不包含换行符,需要手动换行
                bufferedWriter.write(data);
                bufferedWriter.newLine();//换行
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedWriter != null){
                bufferedWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    @Test
    public void test() {

        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("爱情与友情.jpg");
            fos = new FileOutputStream("爱情与友情secret.jpg");

            byte[] buffer = new byte[20];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                //字节数组进行修改
                //错误的
                //            for (byte b : buffer){
                //                b = (byte)(b ^ 5);
                //            }
                //正确的
                for (int i = 0; i < len; i++) {
                    buffer[i] = (byte) (buffer[i] ^ 5);//加密异或5
                    // 解密在异或5就可以了
                    //异或的异或就是本身
                }
                fos.write(buffer, 0, len);

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

练习(缓冲流):

1.第一题
在这里插入图片描述

    //图片的加密
    @Test
    public void test() {

        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("爱情与友情.jpg");
            fos = new FileOutputStream("爱情与友情secret.jpg");

            byte[] buffer = new byte[20];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                //字节数组进行修改
                //错误的
                //            for (byte b : buffer){
                //                b = (byte)(b ^ 5);
                //            }
                //正确的
                for (int i = 0; i < len; i++) {
                    buffer[i] = (byte) (buffer[i] ^ 5);//加密异或5
                    // 解密在异或5就可以了
                    //异或的异或就是本身
                }
                fos.write(buffer, 0, len);

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

第二题:获取文本上每个字符出现的次数
提示:遍历文本的每一个字符;字符及出现的次数保存在Map中;将Map中数据 写入文件

    @Test
    public void testWordCount() {
        FileReader fr = null;
        BufferedWriter bw = null;
        try {
            //1.创建Map集合
            Map<Character, Integer> map = new HashMap<Character, Integer>();

            //2.遍历每一个字符,每一个字符出现的次数放到map中
            fr = new FileReader("dbcp.txt");
            int c = 0;
            while ((c = fr.read()) != -1) {
                //int 还原 char
                char ch = (char) c;
                // 判断char是否在map中第一次出现
                if (map.get(ch) == null) {
                    map.put(ch, 1);
                } else {
                    map.put(ch, map.get(ch) + 1);
                }
            }

            //3.把map中数据存在文件count.txt
            //3.1 创建Writer
            bw = new BufferedWriter(new FileWriter("wordcount.txt"));

            //3.2 遍历map,再写入数据
            Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
            for (Map.Entry<Character, Integer> entry : entrySet) {
                switch (entry.getKey()) {
                    case ' ':
                        bw.write("空格=" + entry.getValue());
                        break;
                    case '\t'://\t表示tab 键字符
                        bw.write("tab键=" + entry.getValue());
                        break;
                    case '\r'://
                        bw.write("回车=" + entry.getValue());
                        break;
                    case '\n'://
                        bw.write("换行=" + entry.getValue());
                        break;
                    default:
                        bw.write(entry.getKey() + "=" + entry.getValue());
                        break;
                }
                bw.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关流
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            if (bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }

    }

转换流

在这里插入图片描述
图解:
在这里插入图片描述

	//关于上述图解的代码实现
    //综合使用InputStreamReader和OutputStreamWriter
    //需要使用try-catch-finally
    @Test
    public void test1() throws IOException {
        //1.造文件,造流
        File file = new File("dbcp_gbk.txt");
        File file1 = new File("dbcp.txt");

        FileInputStream fis = new FileInputStream(file1);
        FileOutputStream fos = new FileOutputStream(file);

        InputStreamReader isr = new InputStreamReader(fis, "utf-8");
        OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");

        //2.读写过程
        char[] cbuf = new char[20];
        int len;
        while ((len = isr.read(cbuf)) != -1){
            osw.write(cbuf,0,len);
        }

        //3.关闭资源
        isr.close();
        osw.close();
    }

练习:

问题:从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续 进行输入操作,直至当输入“e”或者“exit”时,退出程序。

package exer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author acoffee
 * @create 2020-10-20 9:53
 */
public class OtherStreamTest {
    //从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续
    // 进行输入操作,直至当输入“e”或者“exit”时,退出程序。

    //方式一:使用Scanner实现,调用next()返回一个字符串
    //方式二:使用System.in实现。System.in → 转换流 → BufferedReader 的 readLine()

    public static void main(String[] args) {


        BufferedReader br = null;
        try {
            InputStreamReader isr = new InputStreamReader(System.in);
            br = new BufferedReader(isr);

            while (true) {
                String data = br.readLine();
                if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)) {
                    System.out.println("程序结束");
                    break;
                }
                String upperCase = data.toUpperCase();
                System.out.println(upperCase);

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

问题:创建一个名为MyInput的程序。包含从键盘读取int, double, float, boolean, short, byte和字符串值的方法。(相当于创建一个Scanner方法)

package com.atguigu.java;
// MyInput.java: Contain the methods for reading int, double, float, boolean, short, byte and
// string values from the keyboard

import java.io.*;

public class MyInput {
    // Read a string from the keyboard
    public static String readString() {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        // Declare and initialize the string
        String string = "";

        // Get the string from the keyboard
        try {
            string = br.readLine();

        } catch (IOException ex) {
            System.out.println(ex);
        }

        // Return the string obtained from the keyboard
        return string;
    }

    // Read an int value from the keyboard
    public static int readInt() {
        return Integer.parseInt(readString());
    }

    // Read a double value from the keyboard
    public static double readDouble() {
        return Double.parseDouble(readString());
    }

    // Read a byte value from the keyboard
    public static double readByte() {
        return Byte.parseByte(readString());
    }

    // Read a short value from the keyboard
    public static double readShort() {
        return Short.parseShort(readString());
    }

    // Read a long value from the keyboard
    public static double readLong() {
        return Long.parseLong(readString());
    }

    // Read a float value from the keyboard
    public static double readFloat() {
        return Float.parseFloat(readString());
    }
}

打印流

在这里插入图片描述
在这里插入图片描述

数据流

在这里插入图片描述

    /*
    3. 数据流
    3.1 DataInputStream 和 DataOutputStream
    3.2 作用:用于读取或写出基本数据类型的变量或字符串

    练习:将内存中的字符串、基本数据类型的变量写出到文件中。

    注意:处理异常的话,仍然应该使用try-catch-finally.
     */
    @Test
    public void test3() throws IOException {
        //1.
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
        //2.
        dos.writeUTF("刘一");
        dos.flush();//刷新操作,将内存中的数据写入文件
        dos.writeInt(23);
        dos.flush();
        dos.writeBoolean(true);
        dos.flush();
        //3.
        dos.close();


    }
    /*
    将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。

    注意点:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致!

     */
    @Test
    public void test4() throws IOException {
        //1.
        DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
        //2.
        String name = dis.readUTF();
        int age = dis.readInt();
        boolean isMale = dis.readBoolean();

        System.out.println("name = " + name);
        System.out.println("age = " + age);
        System.out.println("isMale = " + isMale);

        //3.
        dis.close();

    }

每日一练

1. 说明流的三种分类方式

流向:输入流、输出流
数据单位:字节流、字符流
流的角色:节点流、处理流

2. 写出4个IO流中的抽象基类,4个文件流,4个缓冲流

InputStream FileXxx BufferedXxx
OutputStream
Reader
Writer

InputStreamReader:父类Reader
异常: XxxException XxxError

RandomAccessFile

3. 字节流与字符流的区别与使用情境
字节流:read(byte[] buffer) / read() 非文本文件
字符流:read(char[] cbuf) / read() 文本文件

4. 使用缓冲流实现a.jpg文件复制为b.jpg文件的操作

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(“a.jpg”)));

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(“b.jpg”)));

byte[] buffer = new byte[1024];
int len;
while((len = bis.read(buffer))!= -1){
	bos.write(buffer,0,len);
}

bos.close();
bis.close();

//此时的异常应该使用try-catch-finally处理。

5.转换流是哪两个类,分别的作用是什么?请分别创建两个类的对象。

InputStreamReader:将输入的字节流转换为输入的字符流。 解码
OutputStreamWriter:将输出的字符流转换为输出的字节流。编码

InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”),”utf-8);

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“b.txt”),”gbk”);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值