Day21JavaSE——IO流之字符流

Day21JavaSE——IO流之字符流

字符流出现的原因
String中的编解码问题
转换流

字符流出现的原因

A: 案例演示:	字符流出现的原因:由于字节流操作中文不是特别方便,所以,java就提供了字符流。
B: 码表
C:字符流:  字符流 = 字节流 + 编码表

String中的编解码问题

public class Test1 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        //编码
        //解码
        String str = "我爱你";
        //使用平台默认的码表进行编码
        byte[] bytes = str.getBytes();
        System.out.println(Arrays.toString(bytes));

        //解码
        String s = new String(bytes);
        System.out.println(s);

        //也就是说我们在编码和解码的时候使用同一张码表,就不会出现乱码的问题
        String str2 = "中文乱码问题";
        byte[] gbks = str2.getBytes("GBK");

        //解码
        String s1 = new String(gbks, "UTF-8");
        System.out.println(s1);

        //乱码就是编解码用的不是同一张码表
    }
}

字符流

Writer

OutputStreamWriter

public class Test1 {
    public static void main(String[] args) throws IOException {
        //OutputStreamWriter
        /*OutputStreamWriter 是字符流通向字节流的桥梁:
        * 可使用指定的 码表 将要写入流中的字符编码成字节。
        * 它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。*/
        /*OutputStreamWriter(OutputStream out)
        * 创建一个使用默认字符编码的OutputStreamWriter。
        * OutputStreamWriter(OutputStream out, Charset cs)
        * 创建一个使用给定字符集的OutputStreamWriter。
        * OutputStreamWriter(OutputStream out, CharsetEncoder enc)
        * 创建一个使用给定字符集编码器的OutputStreamWriter。
        * OutputStreamWriter(OutputStream out, String charsetName)
        * 创建一个使用命名字符集的OutputStreamWriter。*/
        OutputStreamWriter out1 = new OutputStreamWriter(new FileOutputStream("a.txt"));

        //可以指定码表
        OutputStreamWriter out2 = new OutputStreamWriter(new FileOutputStream("b.txt"), "UTF-8");
    }
}
字符流的5种写数据的方式
public void write(int c) 写一个字符
public void write(char[] cbuf) 写一个字符数组
public void write(char[] cbuf,int off,int len) 写一个字符数组的 一部分
public void write(String str) 写一个字符串
public void write(String str,int off,int len) 写一个字符串的一部分
public class Test2 {
    public static void main(String[] args) throws IOException {
        OutputStreamWriter out1 = new OutputStreamWriter(new FileOutputStream("a.txt"));
        System.out.println("==========写入字符==========");
        out1.write('我');
        out1.flush();

        System.out.println("==========写入换行符==========");
        out1.write("\r\n");

        System.out.println("==========写入字符串==========");
        out1.write("你好。。。。");
        //字符流需要刷新,将缓冲区中的数据刷新到磁盘中
        out1.write("\r\n");
        out1.flush();
        out1.write("公司的发货速度");
        out1.write("\r\n");
        out1.flush();
        //释放资源
        out1.close();//刷新并关闭
    }
}
public class Test3 {
    public static void main(String[] args) throws IOException {
        //创建一个文件对象并创建输出字符流对象,使用UTF-8编码
        OutputStreamWriter out1 = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBK");
        out1.write("这样是不是乱码了");
        out1.write("\r\n");
        out1.flush();

        //一次写入一个字符数组
        out1.write(new char[]{'a','b','c','哈','哈'});
        out1.write("\r\n");

        //一次写入字符串的一部分
        out1.write("士大夫敢死队风格",2,3);
        out1.write("\r\n");

        //一次写入字符数组的一部分,从0索引处开始 写3个字符
        out1.write(new char[]{'a', 'b', 'c', '哈', '哈'},0,3);
        //字符流,记得要刷新
        out1.flush();
        //释放资源
        out1.close();

        System.out.println("================================");
        //追加写入
        //追加写入  在你传入的字节流中 给个true 表示追加写入
        OutputStreamWriter out2 = new OutputStreamWriter(new FileOutputStream("b.txt",true));
        out2.write("这样是不是乱码了");
        out2.write("\r\n");
        out2.flush();

        //一次写入一个字符数组
        out2.write(new char[]{'a','b','c','哈','哈'});
        out2.write("\r\n");

        //一次写入字符串的一部分
        out2.write("士大夫敢死队风格",2,3);
        out2.write("\r\n");

        //一次写入字符数组的一部分,从0索引处开始 写3个字符
        out2.write(new char[]{'a', 'b', 'c', '哈', '哈'},0,3);
        //字符流,记得要刷新
        out2.flush();
        //释放资源
        out2.close();
    }
}
public class Test4 {
    public static void main(String[] args) {
        //异常处理
        OutputStreamWriter out1 = null;
        try {
            out1 = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBK");
            out1.write("这样是不是乱码了");
            out1.write("\r\n");
            out1.flush();

            //一次写入一个字符数组
            out1.write(new char[]{'a','b','c','哈','哈'});
            out1.write("\r\n");

            //一次写入字符串的一部分
            out1.write("士大夫敢死队风格",2,3);
            out1.write("\r\n");

            //一次写入字符数组的一部分,从0索引处开始 写3个字符
            out1.write(new char[]{'a', 'b', 'c', '哈', '哈'},0,3);
            //字符流,记得要刷新
            out1.flush();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //释放资源
            try{
                if(out1!=null){
                    out1.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

Reader

InputStreamReader

InputStreamReader的构造方法
InputStreamReader(InputStream is):用默认的编码(GBK)读取数据
InputStreamReader(InputStream is,String charsetName):用指定的编码读取数据
public class Test1 {
    public static void main(String[] args) throws IOException {
        //InputStreamReader是字节流通向字符流的桥梁:
        //它使用指定的 码表 读取字节并将其解码为字符。
        //它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集
        /*protected  Reader()
        * 创建一个新的字符流阅读器,其关键部分将在阅读器本身上同步。
        * protected  Reader(Object lock)
        * 创建一个新的字符流阅读器,其关键部分将在给定对象上同步。*/
        //输入流所关联的文件,如果不存在,就报错了
        InputStreamReader in1 = new InputStreamReader(new FileInputStream("e.txt"));
        //你也可以指定码表
        InputStreamReader in = new InputStreamReader(new FileInputStream("a.txt"), "UTF-8");
    }
}
字符流的2种读数据的方式
public class Test2 {
    public static void main(String[] args) {
        InputStreamReader in = null;
        InputStreamReader in1 = null;
        InputStreamReader in2 = null;
        try {
            in = new InputStreamReader(new FileInputStream("b.txt"));
            System.out.println("========一次读取一个字符========");
            int ch = in.read();
            System.out.println((char) ch);
            ch = in.read();
            System.out.println((char) ch);
            ch = in.read();
            System.out.println((char) ch);
            ch = in.read();
            System.out.println((char) ch);
            ch = in.read();
            System.out.println((char) ch);
            ch = in.read();
            System.out.println((char) ch);
            ch = in.read();
            System.out.println((char) ch);
            ch = in.read();
            System.out.println((char) ch);
            //如果读取不到,就返回-1 我们就可以使用 -1 来判断这个文件是否读取完毕
            ch = in.read();
            System.out.println(ch);

            System.out.println("=======一次读取一个字符数组=======");
            in1 = new InputStreamReader(new FileInputStream("a.txt"));
            //定义一个字符数组作为缓存区
            char[] dataBuffer = new char[1000];
            //一次取1000个字符放到数组中,返回值为实际取得的字符个数
            int len = in1.read(dataBuffer);
            System.out.println(len);
            System.out.println(Arrays.toString(dataBuffer));

            //将字符数组转换成字符串
            String s = String.valueOf(dataBuffer);
            System.out.println(s);

            System.out.println("=======读取字符数组的一部分=======");
            char[] dataBuffer1 = new char[1000];
            in2 = new InputStreamReader(new FileInputStream("a.txt"));
            int len2 = in2.read(dataBuffer1, 2, 8);
            System.out.println(len2);
            System.out.println(Arrays.toString(dataBuffer1));

            String s1 = String.valueOf(dataBuffer1);
            System.out.println(s1);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (in1 != null) {
                    in1.close();
                }
                if (in2 != null) {
                    in2.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
异常处理
public class Test3 {
    public static void main(String[] args) {
        //流的异常处理
        InputStreamReader in=null;
        try {
            in = new InputStreamReader(new FileInputStream("b.txt"));
            //定义一个字符数组来充当容器,可以一次取到这个容器中
            char[] dataBuffer = new char[1000];
            //一次读取一部分字符,放到字符数组中
            int len = in.read(dataBuffer, 0, 8);
            System.out.println(len);
            System.out.println(Arrays.toString(dataBuffer));
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(in!=null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

高效字符流

public class Test1 {
    public static void main(String[] args) throws IOException {
        //高效的字符流
        //BufferedReader
        //BufferedWriter
      /*  构造方法摘要
        BufferedReader(Reader in)
        创建一个使用默认大小输入缓冲区的缓冲字符输入流。*/

        BufferedReader reader = new BufferedReader(new FileReader("Test1.java"));
      /*  BufferedWriter(Writer out)
        创建一个使用默认大小输出缓冲区的缓冲字符输出流。*/
        BufferedWriter writer= new BufferedWriter(new FileWriter("haha.java"));


        char[] chars = new char[2000]; //定义一个字符数组,充当缓冲区
        int len = 0;//用来记录实际读取到的字符个数
        int count = 1;
        while ((len = reader.read(chars)) != -1) {
            System.out.println("循环次数" + (count++));
            writer.write(chars, 0, len);
            writer.flush();
        }

        reader.close();
        writer.close();
    }
}
public class Test2 {
    public static void main(String[] args) throws IOException {
        //高效字符流
        //BufferedReader 里面有特有的方法 String readLine() 一次读一行文本
        //BufferedWriter void newLine() 写入一个换行符,具有平台兼容性。
        //使用高效的字符流。读取一行,写入一行来复制文件,逐行复制。
        BufferedReader reader = new BufferedReader(new FileReader("Test1.java"));
        BufferedWriter writer = new BufferedWriter(new FileWriter("hehe.java"));
        //循环的进行读取一行,写入一行
        //一行一行读取,读取不到返回的是null
        //定义一个变量,此函数以字符串的形式返回读取的那行文本
        String line=null;
        while ((line = reader.readLine()) != null) {
            writer.write(line);
            writer.flush();
        }
        reader.close();
        writer.close();
    }
}

案例演示

案例1

/*A:案例演示: 需求:把ArrayList集合中的字符串数据存储到文本文件
         * 分析:
         * a: 创建一个ArrayList集合
         * b: 添加元素
         * c: 创建一个高效的字符输出流对象
         * d: 遍历集合,获取每一个元素,把这个元素通过高效的输出流写到文本文件中
         * e: 释放资源*/
public class Test1 {
    public static void main(String[] args) {
        ArrayList<String> strings = new ArrayList<>();
        strings.add("aaa");
        strings.add("bbb");
        strings.add("ccc");
        strings.add("ddd");
        strings.add("eee");
        strings.add("fff");
        strings.add("ggg");
        strings.add("hhh");
        strings.add("iii");
        strings.add("jjj");
        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new FileWriter("案例A把ArrayList集合中的字符串数据存储到文本文件.txt"));
            //char[] dataBuffer = new char[1000];
            for (int i = 0; i < strings.size(); i++) {
                char[] chars = strings.get(i).toCharArray();
                writer.write(chars);
                writer.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(writer!=null){
                    writer.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

案例2

/*A:案例演示:  需求:从文本文件中读取数据(每一行为一个字符串数据)到集合中,并遍历集合
        * 分析:
        * a: 创建高效的字符输入流对象
        * b: 创建一个集合对象
        * c: 读取数据(一次读取一行)
        * d: 把读取到的数据添加到集合中
        * e: 遍历集合
        * f: 释放资源*/
public class Test2 {
    public static void main(String[] args) {
        BufferedReader reader=null;
        try {
            reader = new BufferedReader(new FileReader("案例A把ArrayList集合中的字符串数据存储到文本文件.txt"));
            ArrayList<String> strings = new ArrayList<>();
            String s = reader.readLine();
            while ( s != null) {
                strings.add(s);
                s = reader.readLine();
            }
            for (String string : strings) {
                System.out.println(string);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(reader!=null){
                    reader.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

案例3

 /*A:案例演示:  需求:我有一个文本文件,每一行是一个学生的名字,请写一个程序,每次允许随机获取一个学生名称
         * 分析:
         * a: 创建一个高效的字符输入流对象
         * b: 创建集合对象
         * c: 读取数据,把数据存储到集合中
         * d: 产生一个随机数,这个随机数的范围是 0 - 集合的长度 . 作为: 集合的随机索引
         * e: 根据索引获取指定的元素
         * f: 输出
         * g: 释放资源*/
public class Test3 {
    public static void main(String[] args) {
        //随机获取文本中的字符串
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("案例A把ArrayList集合中的字符串数据存储到文本文件.txt"));
            ArrayList<String> strings = new ArrayList<>();
            String s = reader.readLine();
            while (s != null) {
                strings.add(s);
                s = reader.readLine();
            }
            Random random = new Random();
            int index = random.nextInt(strings.size());
            System.out.println(strings.get(index));
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(reader!=null){
                    reader.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

案例4(复制多级文件夹)必须掌握

/*A:案例演示:  需求: 复制多级文件夹
        * 分析:
        * a: 封装源目录为一个对象
        * b: 封装目标目录的父路径为一个File对象
        * c: 判断源文件是目录还是文件
        *   1、是目录
        *       获取源目录名字
        *       调用构造方法在目标目录中创建一个新目录,名字与源目录同名
        *       获取源目录对应的路径下所有的文件对应的File数组
        *       遍历数组,获取每一个元素,进行进行递归
        *   2、是文件
        *       封装源文件和目标文件(注意这里一定要是文件的路径,不能是文件夹)为流
        *       //封装IO流若是传入的File对象里面封装的是文件夹
        *       //就会报java.io.FileNotFoundException: D:\xxx(拒绝访问。)异常
        *       //流只能访问文件,不能访问文件夹
        *
        *       调用流的函数将源文件复制到目标文件
        *       释放资源*/
public class Test4 {
    public static void main(String[] args) {
        File srcFolder = new File("C:\\Users\\adair_liu\\Desktop\\Java");
        File aimFolder = new File("F:\\05学习");
        try {
            copyFolderUseFile(srcFolder,aimFolder);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private static void copyFolderUseFile(File srcFolder,File aimFolder) throws IOException {
        //判断源文件是否是目录
        //获取源文件下的所有文件,遍历
        if(srcFolder.isDirectory()){
            //如果是就在目标文件夹下创建一个目录
            String srcName = srcFolder.getName();
            File file = new File(aimFolder, srcName);
            //创建文件夹
            file.mkdirs();
            //获取源目录下的文件列表
            File[] files = srcFolder.listFiles();
            //遍历列表
            for (File file1 : files) {
                //递归文件夹内的所有文件
                copyFolderUseFile(file1,file);
            }
        }else if(srcFolder.isFile()){
            //进入这里的就是文件,文件用流复制
            String srcName = srcFolder.getName();
            File file = new File(aimFolder, srcName);
            copyFileUseFlu(srcFolder,file);
        }
    }
    private static void copyFileUseFlu(File srcFolder,File aimFolder) throws IOException {
        FileInputStream dataIn = new FileInputStream(srcFolder);
        //之前在这里出现的java.io.FileNotFoundException: D:\xxx(拒绝访问。)异常
        //是因为IO流只能访问文件,而无法访问文件夹
        //所以在将文件对象封装成流时文件对象里面封装的是文件路径,而不是文件夹路径
        FileOutputStream dataOut = new FileOutputStream(aimFolder);
        //将源文件复制到目标文件
        byte[] dataBuffer = new byte[1024 * 8];
        int len=0;
        while ((len = dataIn.read(dataBuffer)) != -1) {
            dataOut.write(dataBuffer,0,len);
            dataOut.flush();
        }
        dataIn.close();
        dataOut.close();
    }
}

案例5

 /*A:案例演示:
         * 需求:键盘录入3个学生信息(姓名,语文成绩(chineseScore),数学成绩(mathScore),英语成绩(englishScore)),按照总分从高到低存入文本文件
         * 分析:
         * a: 创建一个学生类: 姓名,语文成绩(chineseScore),数学成绩(mathScore),英语成绩(englishScore)
         * b: 因为要排序,所以需要选择TreeSet进行存储学生对象
         * c: 键盘录入学生信息,把学生信息封装成一个学生对象,在把学生对象添加到集合中
         * d: 创建一个高效的字符输出流对象
         * e: 遍历集合,把学生的信息写入到指定的文本文件中
         * f: 释放资源*/
public class Student {
    private String name;
    private int chineseScore;
    private int mathScore;
    private int englishScore;
    public Student(){}
    public Student(String name,int chineseScore,int mathScore,int englishScore){
        this.name=name;
        this.chineseScore=chineseScore;
        this.mathScore=mathScore;
        this.englishScore=englishScore;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getChineseScore() {
        return chineseScore;
    }

    public void setChineseScore(int chineseScore) {
        this.chineseScore = chineseScore;
    }

    public int getMathScore() {
        return mathScore;
    }

    public void setMathScore(int mathScore) {
        this.mathScore = mathScore;
    }

    public int getEnglishScore() {
        return englishScore;
    }

    public void setEnglishScore(int englishScore) {
        this.englishScore = englishScore;
    }

    //获取总分
    public int getTotalScore(){
        return chineseScore+mathScore+englishScore;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return chineseScore == student.chineseScore &&
                mathScore == student.mathScore &&
                englishScore == student.englishScore &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, chineseScore, mathScore, englishScore);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", chineseScore=" + chineseScore +
                ", mathScore=" + mathScore +
                ", englishScore=" + englishScore +
                '}';
    }
}
public class Test6 {
    public static void main(String[] args) {
        BufferedWriter stuWriter = null;
        TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int num = o1.getTotalScore() - o2.getTotalScore();
                int num1 = num == 0 ? o1.getName().compareTo(o2.getName()) : num;
                return -num1;
            }
        });
        for (int i = 1; i < 4; i++) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入第" + i + "个学生姓名");
            String name = sc.nextLine();
            System.out.println("请输入第" + i + "个学生语文成绩");
            int chinese = sc.nextInt();
            System.out.println("请输入第" + i + "个学生数学成绩");
            int math = sc.nextInt();
            System.out.println("请输入第" + i + "个学生英语成绩");
            int english = sc.nextInt();
            Student student = new Student(name, chinese, math, english);
            set.add(student);
        }
        try {
            stuWriter = new BufferedWriter(new FileWriter("student.txt",true));
            for (Student student : set) {
                stuWriter.write(student.getName()+"\t"+student.getChineseScore()+"\t"+student.getMathScore()+"\t"+student.getEnglishScore());
                stuWriter.newLine();
                stuWriter.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(stuWriter!=null){
                    stuWriter.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

案例6

 /*A:案例演示:
         * 需求:键盘录入3个学生信息(姓名,语文成绩(chineseScore),数学成绩(mathScore),英语成绩(englishScore)),按照总分从高到低存入文本文件
         * //增加一个需求:每一次录入成绩,都保存在一个新的文件中
         * //遍历学生这个集合,把每个学生的信息,存储到文本文件中
         * //写个表头 改成追加写入
         * //用时间来命名这个文件名*/
public class Test7 {
    public static void main(String[] args) {
        BufferedWriter stuWriter = null;
        TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int num = o1.getTotalScore() - o2.getTotalScore();
                int num1 = num == 0 ? o1.getName().compareTo(o2.getName()) : num;
                return -num1;
            }
        });
        for (int i = 1; i < 4; i++) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入第" + i + "个学生姓名");
            String name = sc.nextLine();
            System.out.println("请输入第" + i + "个学生语文成绩");
            int chinese = sc.nextInt();
            System.out.println("请输入第" + i + "个学生数学成绩");
            int math = sc.nextInt();
            System.out.println("请输入第" + i + "个学生英语成绩");
            int english = sc.nextInt();
            Student student = new Student(name, chinese, math, english);
            set.add(student);
        }
        //增加一个需求:每一次录入成绩,都保存在一个新的文件中
        //遍历学生这个集合,把每个学生的信息,存储到文本文件中
        //写个表头 改成追加写入
        //用时间来命名这个文件名
        long ms = System.currentTimeMillis();
        //将ms值封装成具体的时间
        Date date = new Date(ms);
        String fileName = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒").format(date);
        try {
            stuWriter = new BufferedWriter(new FileWriter(fileName,true));
            stuWriter.write("序号\t\t\t\t姓名\t语文\t数学\t英语\t总分");
            stuWriter.newLine();
            stuWriter.flush();
            int i=1;
            for (Student student : set) {
                stuWriter.write((i++)+"\t"+student.getName()+"\t"+student.getChineseScore()+"\t"+student.getMathScore()+"\t"+student.getEnglishScore());
                stuWriter.newLine();
                stuWriter.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(stuWriter!=null){
                    stuWriter.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}
 stuWriter = new BufferedWriter(new FileWriter(fileName,true));
            stuWriter.write("序号\t\t\t\t姓名\t语文\t数学\t英语\t总分");
            stuWriter.newLine();
            stuWriter.flush();
            int i=1;
            for (Student student : set) {
                stuWriter.write((i++)+"\t"+student.getName()+"\t"+student.getChineseScore()+"\t"+student.getMathScore()+"\t"+student.getEnglishScore());
                stuWriter.newLine();
                stuWriter.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(stuWriter!=null){
                    stuWriter.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值