小学数学练习-Java入门小试牛刀

简介: 小学数学练习

小学数学练习

1.1【问题描述】

编写一个帮助小学生练习数学的程序,帮助小学生练习 100 以内的四种数学运算:加、减、乘、除。

1.2【基本要求】

a) 程序应先询问用户的 ID 号(ID 号包括两个大写字母和 4 位数字),例如:
请输入用户 ID 号:AB1234
程序应对输入的 ID 号验证,符合 ID 号要求的格式, 然后程序提示三种选择:
(1)开始测试
(2)检查分数
(3)退出
b) 测试:该程序将给出 10 道数学题,例如:
12 * 3 =36
48 + 32 =80

56 / 28 =2

注意:
i)学生将依次回答每一个问题(在等于号后面给出答案) ,然后给出下一道题。
ii)试题应包含四种数学运算:加、减、乘、除, 它们是随机产生的。 相邻的问题应该是不同的操作,
每个操作必须至少出现一次。 报告中应给出实现方法或算法。
iii)为每道题随机生成数字, 但必须确保参与运算的数字和结果都小于 100 且大于零的整数, 除法时
还要注意两个整数要能整除。 报告中应给出实现方法或算法。
iv)十道题做完后,记录学生完成这十道题所用的时间。
v)给每个学生一个分数。将该学生的 ID、成绩和使用时间保存到一个名为 record.txt 的文件中。
vi)在屏幕上输出以下信息:(3 列信息, 第 1 列是 b) 中的测试题, 蓝色部分)
问题 | 正确答案 | 你的答案
c) 成绩检查:从文件“record.txt” 中列出该学生的所有历史成绩(其他学生的不显示)。例如:
你以前的记录是:
AB1234 80 150 秒
AB1234 50 182 秒
AB1234 90 98 秒

1.3【模块划分】

// 主类
public class One{}
// 用户类
class User{}
// 功能类
class Fun{}

// 封装主类
public class One {

    public static void main(String[] args) {
        // 初始化界面
        Fun fun = new Fun();
        // 加载一位新的用户
        User user = new User(fun.start());
        // 用户进入界面
        fun.index(user);
    }
}

/**
 * 封装用户类
 */
class User{
    /**
     * 用户ID
      */
    private String id;
    /**
     * 用户成绩
     */
    private int scores = 0;
    /**
     * 用户所用时间
     */
    private int time = 0;

    /**
     * 用户做题数据
     */
    private String data = "";

    /**
     * 初始化用户
      */
    public User(String id){
        this.id = id;
    }

    // 一堆堆get,set方法
    .......
    
    // 添加数据的方法
    public void addData(String data){
        this.data = this.data.concat(data);
    }
}


class Fun{

    /**
     * 用户输入ID号模块
     */
    public String start(){}
    /**
     * 首页
     */
    public void index(User user){}

    /**
     * 保存成绩
     */
    public void recordUser(User user) {}

    /**
     * 检查用户
     */
    public void checkUser(User user){}

    /**
     * 随机出题
     */
    public void test(User user){}


    /**
     * 加法
     */
    public void add(User user){}

    /**
     * 减法
     */
    public void delete(User user){}

    /**
     * 乘法
     */
    public void multi(User user){}

    /**
     * 除法
     */
    public void div(User user){}

    /**
     * 校验用户名
     */
    public boolean verify(String id){}

/**
     * 用户输入ID号模块
     */
    public String start(){
        System.out.print("请输入用户 ID 号");
        Scanner sc = new Scanner(System.in);
        String id = sc.next();
         while (!verify(id)){
             System.out.println("ID 号包括两个大写字母和 4 位数字,请重新输入用户ID");
             id = sc.next();
         }
         return id;
    }
  /**
     * 校验用户名
     */
    public boolean verify(String id){
    // 正则表达式
        String format = "[A-Z]{2}[0-9]{4}";
        return id.matches(format);
    }

/**
     * 加法
     */
    public void add(User user){
        Scanner sc = new Scanner(System.in);
        int[] tar = randTil(0);
        String ques = tar[0] + "+" + tar[1] + "=";
        System.out.print(ques);
        int result = sc.nextInt();
        if(result == tar[2]){
            user.setScores(user.getScores() + 10);
        }
        user.addData(ques + "|" + tar[2] + " | " + result + "--");
    }

    /**
     * 减法
     */
    public void delete(User user){
        Scanner sc = new Scanner(System.in);
        int[] tar = randTil(0);
        String ques = tar[2] + "-" + tar[1] + "=";
        System.out.print(ques);
        int result = sc.nextInt();
        if(result == tar[0]){
            user.setScores(user.getScores() + 10);
        }
        user.addData(ques + "|" + tar[0] + " | " + result + "--");
    }

    /**
     * 乘法
     */
    public void multi(User user){
        Scanner sc = new Scanner(System.in);
        int[] tar =  randTil(1);
        String ques = tar[0] + "*" + tar[1] + "=";
        System.out.print(ques);
        int result = sc.nextInt();
        if(result == tar[2]){
            user.setScores(user.getScores() + 10);
        }
        user.addData(ques + "|" + tar[2] + " | " + result + "--");
    }

    /**
     * 除法
     */
    public void div(User user){
        Scanner sc = new Scanner(System.in);
        int[] tar = randTil(1);
        String ques = tar[2] + "\\" + tar[1] + "=";
        System.out.print(ques);
        int result = sc.nextInt();
        if(result == tar[0]){
            user.setScores(user.getScores() + 10);
        }
        user.addData(ques + "|" + + tar[0] + " | " + result + "--");
    }
    /**
     * 数字生成工具
     */
    public int[] randTil(int cal){
        int[] tar = new int[3];
        int num1 = (int)(Math.random()*99) + 1;
        int num2 = (int)(Math.random()*99) + 1;
        if(cal == 0){
            tar[2] = Math.max(num1, num2);
            if(num1 > num2){
                tar[0] = tar[2] - num2;
                tar[1] = num2;
            }else {
                tar[0] = num1;
                tar[1] = tar[2] - num1;
            }
        }
        if(cal == 1){
            tar[0] = (int)(Math.random()*(100/num1-1)) + 1;
            tar[1] = num1;
            tar[2] = tar[0] * tar[1];
        }
        return tar;
    }

 /**
     * 随机出题
     */
    public void test(User user){
        // 初始化用户答题数据
        user.setData("");
        // 创建储存题目分布数组
        int[] num = new int[10];
        // 上一次出现过的数字
        int lastNum = -1;
        // 先保证四种运算出现一次
        for (int i = 0; i < 4; i++) {
            lastNum = randNoRe(lastNum,0, 10);
            num[lastNum] = i + 1;
        }

        lastNum = -1;
        for(int i = 0; i < 10; i++){
           if(num[i] == 0){
                // 只填未填好的数字
                num[i] = randNoRe(lastNum, 1, 4);
                if(i < num.length - 1){
                    if(num[i] == num[i + 1]){
                        i--;
                        num[i] = 0;
                        continue;
                    }
                }
            }
            lastNum = num[i];
        }
        for(int n : num){
            switch (n){
                case 1 : add(user); break;
                case 2 : delete(user); break;
                case 3 : multi(user); break;
                case 4 : div(user); break;
                default:break;
            }
        }
        String[] datas = user.getData().split("--");
        System.out.println("问题 | 正确答案 | 你的答案");
        for (String data : datas) {
            System.out.println(data);
        }
        System.out.println("本次得分:" + user.getScores());
    }

    /**
     * 随机生成与上一次不同的数字组成的数组
     * lastNum:上一个数字,a,b生成范围
     */
    public int randNoRe(int lastNum, int a, int b){
        int n = (int)(Math.random()*b + a);
        while(lastNum == n) {
            n = (int) (Math.random()*b + a);
        }
        return n;
    }

 /**
     * 文件路径
     */
    private static final String FILE_PATH = "E:\\record.txt";
    
/**
     * 保存成绩
     */
    public void recordUser(User user) {
        FileWriter fileWriter = null;
        try {
            File file = new File(FILE_PATH);
            // 判断文件是否存在
            if (!file.isFile()) {
                file.createNewFile();
            }
            // 追加文件
            fileWriter = new FileWriter(file, true);
            // 追加内容
            fileWriter.append(user.getId()).append("  ").append(String.valueOf(user.getScores())).append("  ").append(String.valueOf(user.getTime())).append(" 秒-");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(fileWriter != null){
                try {
                    // 刷新流对象中的缓冲中的数据
                    fileWriter.flush();
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 检查用户
     */
    public void checkUser(User user){

        String[] s1 = null;
        FileReader fileReader = null;
        try{
            // 处理流读取
            fileReader = new FileReader(new File(FILE_PATH));
            BufferedReader bf = new BufferedReader(fileReader);
            String s;
            while ((s = bf.readLine()) != null){
                s1 = s.split("-");
            }
            // 判断是否是新用户
            boolean flag = true;
            for(String str : s1){
                if(str.substring(0,6).equals(user.getId())){
                        // 控制打印次数
                        if(flag){
                            System.out.println("你以前的记录是:");
                            flag = false;
                        }
                        System.out.println(str);
                    }
                }
            // 是新用户
            if(flag){
                System.out.println("新用户,欢迎你使用!");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(fileReader != null){
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

 /**
     * 首页
     */
    public void index(User user){
            // 列出用户历史成绩
            checkUser(user);

            boolean flag = true;
            while (flag) {
                System.out.println("(1)开始测试\n" +
                        "(2)检查分数\n" +
                        "(3)退出"
                );
                // 用户进行功能选择
                Scanner sc = new Scanner(System.in);
                int choice = sc.nextInt();
                switch (choice) {
                    case 1:
                        // 初始化用户成绩
                        user.setScores(0);
                        // 开始计时
                        long start = System.currentTimeMillis();
                        // 开始测试
                        test(user);
                        // 结束计时
                        long end = System.currentTimeMillis();
                        // 设置用户游戏时间
                        user.setTime((int) ((end - start) / 1000));
                        // 保存成绩
                        recordUser(user);
                        break;
                    case 2:
                        // 检查分数
                        checkUser(user);
                        break;
                    case 3:
                        flag = false;
                        System.out.println("退出成功");
                        break;
                    default:break;
                }
            }
    }

1.4【算法思想】

关于如何生成10个数字(每个数字与前一个不同,每个数字至少出现过一次)
在这里插入图片描述

1.5【题解】

import java.io.*;
import java.util.Scanner;

/**
 * @author xh
 */
public class One {

    public static void main(String[] args) {
        // 初始化界面
        Fun fun = new Fun();
        // 加载一位新的用户
        User user = new User(fun.start());
        // 用户进入界面
        fun.index(user);
    }
}

/**
 * 用户类
 */
class User{
    /**
     * 用户ID
      */
    private String id;
    /**
     * 用户成绩
     */
    private int scores = 0;
    /**
     * 用户所用时间
     */
    private int time = 0;

    /**
     * 用户做题数据
     */
    private String data = "";

    /**
     * 初始化用户
      */
    public User(String id){
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public int getScores() {
        return scores;
    }

    public void setScores(int scores) {
        this.scores = scores;
    }

    public int getTime() {
        return time;
    }

    public void setTime(int time) {
        this.time = time;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public void addData(String data){
        this.data = this.data.concat(data);
    }
}

class Fun{
    /**
     * 文件路径
     */
    private static final String FILE_PATH = "E:\\record.txt";

    /**
     * 用户输入ID号模块
     */
    public String start(){
        System.out.print("请输入用户 ID 号");
        Scanner sc = new Scanner(System.in);
        String id = sc.next();
         while (!verify(id)){
             System.out.println("ID 号包括两个大写字母和 4 位数字,请重新输入用户ID");
             id = sc.next();
         }
         return id;
    }

    /**
     * 首页
     */
    public void index(User user){
            // 列出用户历史成绩
            checkUser(user);

            boolean flag = true;
            while (flag) {
                System.out.println("(1)开始测试\n" +
                        "(2)检查分数\n" +
                        "(3)退出"
                );
                // 用户进行功能选择
                Scanner sc = new Scanner(System.in);
                int choice = sc.nextInt();
                switch (choice) {
                    case 1:
                        // 初始化用户成绩
                        user.setScores(0);
                        // 开始计时
                        long start = System.currentTimeMillis();
                        // 开始测试
                        test(user);
                        // 结束计时
                        long end = System.currentTimeMillis();
                        // 设置用户游戏时间
                        user.setTime((int) ((end - start) / 1000));
                        // 保存成绩
                        recordUser(user);
                        break;
                    case 2:
                        // 检查分数
                        checkUser(user);
                        break;
                    case 3:
                        flag = false;
                        System.out.println("退出成功");
                        break;
                    default:break;
                }
            }
    }


    /**
     * 保存成绩
     */
    public void recordUser(User user) {
        FileWriter fileWriter = null;
        try {
            File file = new File(FILE_PATH);
            // 判断文件是否存在
            if (!file.isFile()) {
                file.createNewFile();
            }
            // 追加文件
            fileWriter = new FileWriter(file, true);
            // 追加内容
            fileWriter.append(user.getId()).append("  ").append(String.valueOf(user.getScores())).append("  ").append(String.valueOf(user.getTime())).append(" 秒-");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(fileWriter != null){
                try {
                    // 刷新流对象中的缓冲中的数据
                    fileWriter.flush();
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 检查用户
     */
    public void checkUser(User user){

        String[] s1 = null;
        FileReader fileReader = null;
        try{
            // 处理流读取
            fileReader = new FileReader(new File(FILE_PATH));
            BufferedReader bf = new BufferedReader(fileReader);
            String s;
            while ((s = bf.readLine()) != null){
                s1 = s.split("-");
            }
            // 判断是否是新用户
            boolean flag = true;
            for(String str : s1){
                if(str.substring(0,6).equals(user.getId())){
                        // 控制打印次数
                        if(flag){
                            System.out.println("你以前的记录是:");
                            flag = false;
                        }
                        System.out.println(str);
                    }
                }
            // 是新用户
            if(flag){
                System.out.println("新用户,欢迎你使用!");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(fileReader != null){
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 随机出题
     */
    public void test(User user){
        // 初始化用户答题数据
        user.setData("");
        // 创建储存题目分布数组
        int[] num = new int[10];
        // 上一次出现过的数字
        int lastNum = -1;
        // 先保证四种运算出现一次
        for (int i = 0; i < 4; i++) {
            lastNum = randNoRe(lastNum,0, 10);
            num[lastNum] = i + 1;
        }

        lastNum = -1;
        for(int i = 0; i < 10; i++){
            if(num[i] == 0){
                // 只填未填好的数字
                num[i] = randNoRe(lastNum, 1, 4);
                if(i < num.length - 1){
                    if(num[i] == num[i + 1]){
                        i--;
                        num[i] = 0;
                        continue;
                    }
                }
            }
            lastNum = num[i];
        }
        for(int n : num){
            switch (n){
                case 1 : add(user); break;
                case 2 : delete(user); break;
                case 3 : multi(user); break;
                case 4 : div(user); break;
                default:break;
            }
        }
        String[] datas = user.getData().split("--");
        System.out.println("问题 | 正确答案 | 你的答案");
        for (String data : datas) {
            System.out.println(data);
        }
        System.out.println("本次得分:" + user.getScores());
    }

    /**
     * 随机生成与上一次不同的数字组成的数组
     * lastNum:上一个数字,a,b生成范围
     */
    public int randNoRe(int lastNum, int a, int b){
        int n = (int)(Math.random()*b + a);
        while(lastNum == n) {
            n = (int) (Math.random()*b + a);
        }
        return n;
    }

    /**
     * 数字生成工具
     */
    public int[] randTil(int cal){
        int[] tar = new int[3];
        int num1 = (int)(Math.random()*99) + 1;
        int num2 = (int)(Math.random()*99) + 1;
        if(cal == 0){
            tar[2] = Math.max(num1, num2);
            if(num1 > num2){
                tar[0] = tar[2] - num2;
                tar[1] = num2;
            }else {
                tar[0] = num1;
                tar[1] = tar[2] - num1;
            }
        }
        if(cal == 1){
            tar[0] = (int)(Math.random()*(100/num1-1)) + 1;
            tar[1] = num1;
            tar[2] = tar[0] * tar[1];
        }
        return tar;
    }


    /**
     * 加法
     */
    public void add(User user){
        Scanner sc = new Scanner(System.in);
        int[] tar = randTil(0);
        String ques = tar[0] + "+" + tar[1] + "=";
        System.out.print(ques);
        int result = sc.nextInt();
        if(result == tar[2]){
            user.setScores(user.getScores() + 10);
        }
        user.addData(ques + "|" + tar[2] + " | " + result + "--");
    }

    /**
     * 减法
     */
    public void delete(User user){
        Scanner sc = new Scanner(System.in);
        int[] tar = randTil(0);
        String ques = tar[2] + "-" + tar[1] + "=";
        System.out.print(ques);
        int result = sc.nextInt();
        if(result == tar[0]){
            user.setScores(user.getScores() + 10);
        }
        user.addData(ques + "|" + tar[0] + " | " + result + "--");
    }

    /**
     * 乘法
     */
    public void multi(User user){
        Scanner sc = new Scanner(System.in);
        int[] tar =  randTil(1);
        String ques = tar[0] + "*" + tar[1] + "=";
        System.out.print(ques);
        int result = sc.nextInt();
        if(result == tar[2]){
            user.setScores(user.getScores() + 10);
        }
        user.addData(ques + "|" + tar[2] + " | " + result + "--");
    }

    /**
     * 除法
     */
    public void div(User user){
        Scanner sc = new Scanner(System.in);
        int[] tar = randTil(1);
        String ques = tar[2] + "\\" + tar[1] + "=";
        System.out.print(ques);
        int result = sc.nextInt();
        if(result == tar[0]){
            user.setScores(user.getScores() + 10);
        }
        user.addData(ques + "|" + + tar[0] + " | " + result + "--");
    }

    /**
     * 校验用户名
     */
    public boolean verify(String id){
        String format = "[A-Z]{2}[0-9]{4}";
        return id.matches(format);
    }
}

知识总结

一、文件

问题引入:如何判断输入、输出?

参照物:Java程序

输出:程序→文件
内存中的数据储存到持久化设备,这个动作称为输出 Output
输入:文件→程序
持久设备上的数据读取到内存中,这个动作称为输入 Input

Java中把文件或者目录(文件夹)都封装成File对象,如果我们要去操作硬盘上的文件,或者文件夹只要找到File这个类,调用它的功能操作文件或者文件夹

1.File类的构造函数

        String pathName = "e:\\hello.java";
        File f1 = new File(pathName);

        File f2 = new File("e:\\","hello.java");
    
        File dir = new File("e:\\");
        File f3 = new File(dir,"hello.java");

在这里插入图片描述

2.File类的获取

在这里插入图片描述

3.文件和文件夹的创建删除等

在这里插入图片描述

4.listFiles()方法介绍

在这里插入图片描述

        File[] files = dir.listFiles();
        for(File file : files){
            System.out.println(file);
        }

注意:
1、指定的目录必须是存在
2、指定的必须是目录。否则容易引发返回数组为null,出现NullPointerException


二、流

关键字
input 输入 output 输出 stream 流 writer 字符输入流 reader 字符输入流 File 文件
只要会了字节流就都会了
字节流能处理一切

有诗曰:输入还是输出?字符还是字节?

流的分类表

分类 字节输入流 字节输出流 字符输入流 字符输出流
抽象基类 InputStream OutputStream Reader Writer
访问文件 FileInputStream FileOutputStream FileReader FileWriter
访问数组 ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter
访问字符串 StringReader StringWriter
缓冲流 BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter
转换流 InputStreamReader OutputStreamWriter
对象流 ObjectInputStream ObjectOutputStream

转换流能都将字符流转成字节流

1.字节流

1.1、字节输出流OutputStream

输出流中定义都是写write方法
在这里插入图片描述

1.11、FileOutputStream类

给文件续写、换行

        File file = new File("c:\\file.txt");
        // 第二个参数 传入true
        FileOutputStream fos = new FileOutputStream(file, true); 
        String str = "\r\n" +"换行内容";
        fos.write(str.getBytes());
1.2、字节输入流InputStream

在这里插入图片描述

1.21、读写数据read(byte[])方法
        FileOutputStream fos = new FileOutputStream(destFile);
        // 缓冲区,临时数组容器
        byte[] buf = new byte[1024];//长度定义成1024的整数倍        
        int len = 0;
        while((len=fis.read(buf))!=-1){
            System.out.println(new String(buf,0,len));
            // 将数组中的指定长度的数据写入到输出流中。
            fos.write(buf, 0, len);            
        }
        // 关闭资源。
        fos.close();

2、字符流

2.1.字符编码表

编码表:其实就是生活中字符和计算机二进制的对应关系表。
1、ASCII: 一个字节中的7位就可以表示。对应的字节都是正数。0-xxxxxxx
2、iso-8859-1:拉丁码表 latin,用了一个字节用的8位。1-xxxxxxx 负数。
3、GB2312:简体中文码表。包含6000-7000中文和符号。用两个字节表示。两个字节第一个字节是负数,第二个字节可能是正数

  • GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,其中的一部分文字,第一个字节开头是1,第二字节开头是0

  • GB18030:最新的中文码表,目前还没有正式使用。

4、unicode:国际标准码表:无论是什么文字,都用两个字节存储。

  • Java中的char类型用的就是这个码表。char c = 'a';占两个字节。
  • Java中的字符串是按照系统默认码表来解析的。简体中文版 字符串默认的码表是GBK。

5、UTF-8:基于unicode,一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息(后期到api中查找)。

能识别中文的码表:GBK、UTF-8;正因为识别中文码表不唯一,涉及到了编码解码问题。

对于我们开发而言;常见的编码 GBK UTF-8 ISO-8859-1

编码与解码:
文字--->(数字) :编码。 “abc”.getBytes() byte[]
(数字)--->文字 : 解码。 byte[] b={97,98,99} new String(b)
2.2.FileReader读取包含中文的文件
FileReader fr = new FileReader("D:\\test\\cn.txt");
    int ch = 0;
    while((ch = fr.read())!=-1){
        //输出的字符对应的编码值
        System.out.println(ch);
        //输出字符本身
        System.out.println((char)ch);
    }

FileOutputStream fos = new FileOutputStream("D:\\test\\cn.txt");
        fos.write("文字".getBytes());
        fos.close();
2.3.flush()和close()的区别

在这里插入图片描述
flush():将流中的缓冲区缓冲的数据刷新到目的地中,刷新后,流还可以继续使用
close():关闭资源,但在关闭前会将缓冲区中的数据先刷新到目的地,否则丢失数据,然后在关闭流。流不可以使用。如果写入数据多,一定要一边写一边刷新,最后一次可以不刷新,由close完成刷新并关闭。


3.转换流

字符流与字节流之间的桥梁


OutputStreamWriter流对象,如何把字符转成字节输出的呢?

其实在OutputStreamWriter流中维护自己的缓冲区,当我们调用OutputStreamWriter对象的write方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数存放到OutputStreamWriter缓冲区中。然后再调用刷新功能,或者关闭流,或者缓冲区存满后会把缓冲区中的字节数据使用字节流写到指定的文件中。


//创建读取文件的字节流对象
        InputStream in = new FileInputStream("c:\\ccf.txt");
        //创建转换流对象 
        //InputStreamReader isr = new InputStreamReader(in);这样创建对象,会用本地默认码表读取,将会发生错误解码的错误
        InputStreamReader isr = new InputStreamReader(in,"utf-8");
        //使用转换流去读字节流中的字节
        int ch = 0;
        while((ch = isr.read())!=-1){
            System.out.println((char)ch);
        }
        //关闭流
        isr.close();

注意:在读取指定的编码的文件时,一定要指定编码格式,否则就会发生解码错误,而发生乱码现象。


总结:
字节--->字符 : 看不懂的--->看的懂的。 需要读。输入流。 InputStreamReader(我们需要字符
字符--->字节 : 看的懂的--->看不懂的。 需要写。输出流。 OutputStreamWriter(文件需要字节


4.缓冲流

Java中提供了一套缓冲流,它的存在,可提高IO流的读写速度

4.1.字节缓冲流

字节缓冲流根据流的方向,共有2个

  • 写入数据到流中,字节缓冲输出流 BufferedOutputStream
  • 读取流中的数据,字节缓冲输入流 BufferedInputStream

内部都包含了一个缓冲区通过缓冲区读写,就可以提高了IO流的读写速度

4.11 字节缓冲输出流BufferedOutputStream
/*
     * 写数据到文件的方法
     * 1,创建流
     * 2,写数据
     * 3,关闭流
     */
    private static void write() throws IOException {
        //创建基本的字节输出流
        FileOutputStream fileOut = new FileOutputStream("abc.txt");
        //使用高效的流,把基本的流进行封装,实现速度的提升
        BufferedOutputStream out = new BufferedOutputStream(fileOut);
        //2,写数据
        out.write("hello".getBytes());
        //3,关闭流
        out.close();
    }
4.12.字节缓冲输入流 BufferedInputStream
/*
     * 从文件中读取数据
     * 1,创建缓冲流对象
     * 2,读数据,打印
     * 3,关闭
     */
    private static void read() throws IOException {
        //1,创建缓冲流对象
        FileInputStream fileIn = new FileInputStream("abc.txt");
        //把基本的流包装成高效的流
        BufferedInputStream in = new BufferedInputStream(fileIn);
        //2,读数据
        int ch = -1;
        while ( (ch = in.read()) != -1 ) {
            //打印
            System.out.print((char)ch);
        }
        //3,关闭
        in.close();
    }
4.2.字符缓冲流
4.2.1字符缓冲输出流 BufferedWriter

void newLine() 根据当前的系统,写入一个换行符

/*
 * BufferedWriter 字符缓冲输出流
 * 方法
 *     public void newLine()写入一个行分隔符
 * 
 * 需求: 通过缓冲输出流写入数据到文件
 * 分析:
 *     1,创建流对象
 *     2,写数据
 *     3,关闭流
 * 
 */
public class BufferedWriterDemo {
    public static void main(String[] args) throws IOException {
        //创建流
        //基本字符输出流
        FileWriter fileOut = new FileWriter("file.txt");
        //把基本的流进行包装
        BufferedWriter out = new BufferedWriter(fileOut);
        //2,写数据
        for (int i=0; i<5; i++) {
            out.write("hello");
            out.newLine();
        }
        //3,关闭流
        out.close();
    }
}
4.2.2字符缓冲输入流 BufferedReader

public String readLine()
读取一个文本行,包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null

/*
 * BufferedReader 字符缓冲输入流
 * 
 * 方法:
 *     String readLine() 
 * 需求:从文件中读取数据,并显示数据
 */
public class BufferedReaderDemo {
    public static void main(String[] args) throws IOException {
        //1,创建流
        BufferedReader in = new BufferedReader(new FileReader("file.txt"));
        //2,读数据
        //一次一个字符
        //一次一个字符数组
        //一次读取文本中一行的字符串内容
        String line = null;
        while( (line = in.readLine()) != null ){
            System.out.println(line);
        }
        
        //3,关闭流
        in.close();
    }
}

流的总结:

四个明确:

  • 明确一:要操作的数据是数据源还是数据目的。

       源:InputStream      Reader
       目的:OutputStream   Writer

先根据需求明确要读,还是要写。

  • 明确二:要操作的数据是字节还是文本呢?

       源:
           字节:InputStream
           文本:Reader
       目的:
           字节:OutputStream
           文本:Writer

明确具体的体系。

  • 明确三:明确数据所在的具体设备。

       源设备:
           硬盘:文件  File开头。
           内存:数组,字符串。
           键盘:System.in;
           网络:Socket
       目的设备:
           硬盘:文件  File开头。
           内存:数组,字符串。
           屏幕:System.out
           网络:Socket

要使用哪个流对象

  • 明确四:是否需要额外功能呢?

       额外功能:
           转换吗?转换流。InputStreamReader OutputStreamWriter
           高效吗?缓冲区对象。BufferedXXX
    

三个过程

  • 向文件中写入数据的过程

       1,创建输出流对象
       2,写数据到文件
       3,关闭输出流
    
  • 从文件中读数据的过程

       1,创建输入流对象
       2,从文件中读数据
       3,关闭输入流
    
  • 文件复制的过程

       1,创建输入流(数据源)
       2,创建输出流(目的地)
       3,从输入流中读数据
       4,通过输出流,把数据写入目的地
       5,关闭流
    

三、小案例

1、文件的基本操作

@Test
public void testFile() throws Exception{
//创建文件
File file = new File("E:\\test\\b.txt");
file.createNewFile();
//查看文件夹下的文件
File file2 = new File("E:\\test\\b.txt");
String[] list = file2.list();
for (int i = 0; i < list.length; i++) {
System.out.println(list[i]);
} 
}

2、复制文件带有进度条

@Test
public void testFileInputStream() throws Exception {
File file = new File("E:\\test\\a\\233.mp4");
//拿到文件的大小
long dataLength = file.length();
//构建一个输入流,他的数据要流入内存,咱们的程序
InputStream inputStream = new FileInputStream(file);
//构建一个输出流,他的数据要从内存(咱们的程序)流到另一个文件夹
OutputStream outputStream = new FileOutputStream("E:\\test\\b\\233.mp4");
//新建一个水泵,能存一点水,每次对对1k
byte[] buffer = new byte[1024 *1024*50];
Long currentLength = 0L;
//如果read返回-1说明读完了
int len;
int showNumber = 0;
while ( (len = inputStream.read(buffer)) != -1 ){
outputStream.write(buffer,0,len);
currentLength += len;
//当下加载了百分之多少
int currentPer = (int)(((double)currentLength/dataLength)*100);
//目的是不重复显示
if(showNumber != currentPer){
showNumber = currentPer;
System.out.println("已经拷贝了百分之" + showNumber);
}
}
outputStream.flush();
outputStream.close();
inputStream.close();
}

3、字节流读文件

@Test
public void testInputStream() throws Exception{
//怼了一个输入流到文件上
InputStream wordInput = new FileInputStream("E:\\test\\a\\word.txt");
//建立缓冲区
byte[] bytes = new byte[1024];
int len;
while ( (len = wordInput.read(bytes)) != -1 ){
System.out.println(new String(bytes,0,len, Charset.forName("ISO8859-1")));
} 
wordInput.close();
}

4、字符流对文件

@Test
public void testReader() throws Exception{
//怼了一个输入流到文件上
Reader reader = new FileReader("E:\\test\\a\\word.txt");
BufferedReader br = new BufferedReader(reader);
String str;
while ((str = br.readLine()) != null){
System.out.println(str);
} 
reader.close();
br.close();
}

5、向文件里写内容

@Test
public void testWriter() throws Exception{
//怼了一个输入流到文件上
Writer writer = new FileWriter("E:\\test\\a\\writer.txt");
BufferedWriter bw = new BufferedWriter(writer);
Scanner scanner = new Scanner(System.in);
while (true){
System.out.print("请输入:");
String words = scanner.next();
bw.write(words);
bw.flush();
}
}

6、StringReader就是往String上怼

@Test
public void testStringReader() throws Exception{
//怼了一个string
OutputStream os = new FileOutputStream("E:\\test\\a\\user.txt");
ObjectOutput oo = new ObjectOutputStream(os);
oo.writeObject(new User("小航",3,4));
oo.flush();
oo.close();
os.close();
}

四:小实验-下载网易云音乐

step1:
https://music.163.com/
进入官网,随便搜首歌曲
在这里插入图片描述
step2:进入页面,打开开发者工具(浏览器F12),选择network
在这里插入图片描述
step3:选择media过滤,选择一个有效链接
https://m701.music.126.net/20210714161041/4fa28b697be05c47052a5b51039e5668/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/5755656629/2ce0/caf3/9e65/4e8df6c581219b094bdce6db938379be.m4a

在这里插入图片描述
step4:打开ideal,创建一个class文件Url

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
 * @author xh
 */
public class Url {

    // 文件基本路劲
    private static final String BASE_URL = "C:\\Users\\Administrator\\Desktop\\homework\\";

    public static void main(String[] args) throws Exception{
        download("https://m701.music.126.net/20210714161041/4fa28b697be05c47052a5b51039e5668/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/5755656629/2ce0/caf3/9e65/4e8df6c581219b094bdce6db938379be.m4a");
    }

    /**
     * 下载方法
     */
    private static void download(String path) throws IOException {
        System.out.println("文件开始下载!");
        // 创建一个url对象
        URL url = new URL(path);
        // 打开和网络的连接,拿到流对象
        InputStream inputStream = url.openStream();
        // 获取文件名(从最后一个 / 截取字符串)
        String fileName = url.getFile().substring(url.getFile().lastIndexOf("/") + 1);
        System.out.println(url.getFile().substring(url.getFile().lastIndexOf("/") + 1));
        File file = new File(BASE_URL + fileName);
        boolean newFile = file.createNewFile();
        if(newFile){
            FileOutputStream outputStream = new FileOutputStream(file);
            byte[] buf = new byte[1024];
            int len;
            while((len = inputStream.read(buf)) != -1){
                outputStream.write(buf,0,len);
                outputStream.flush();
            }
            inputStream.close();
            outputStream.close();

            System.out.println("文件下载成功!");
        }else{
            System.out.println("文件下载失败!");
        }
    }
}
相关文章
|
1月前
|
设计模式 前端开发 Java
【前端学java】SpringBootWeb极速入门-分层解耦(03)
【8月更文挑战第13天】SpringBootWeb极速入门-分层解耦(03)
15 2
【前端学java】SpringBootWeb极速入门-分层解耦(03)
|
1月前
|
开发框架 前端开发 Java
【前端学java】SpringBootWeb极速入门-实现一个简单的web页面01
【8月更文挑战第12天】SpringBootWeb极速入门-实现一个简单的web页面01
50 3
【前端学java】SpringBootWeb极速入门-实现一个简单的web页面01
|
1月前
|
JSON 前端开发 Java
【前端学java】SpringBootWeb极速入门-请求参数解析(02)
【8月更文挑战第12天】SpringBootWeb极速入门-请求参数解析(02)
15 1
【前端学java】SpringBootWeb极速入门-请求参数解析(02)
|
20天前
|
算法 Java 开发者
Java 编程入门:从零到一的旅程
本文将带领读者开启Java编程之旅,从最基础的语法入手,逐步深入到面向对象的核心概念。通过实例代码演示,我们将一起探索如何定义类和对象、实现继承与多态,并解决常见的编程挑战。无论你是编程新手还是希望巩固基础的开发者,这篇文章都将为你提供有价值的指导和灵感。
|
21天前
|
存储 Java 程序员
Java中的集合框架:从入门到精通
【8月更文挑战第30天】在Java的世界里,集合框架是一块基石,它不仅承载着数据的存储和操作,还体现了面向对象编程的精髓。本篇文章将带你遨游Java集合框架的海洋,从基础概念到高级应用,一步步揭示它的奥秘。你将学会如何选择合适的集合类型,掌握集合的遍历技巧,以及理解集合框架背后的设计哲学。让我们一起探索这个强大工具,解锁数据结构的新视角。
|
23天前
|
Java 程序员 UED
Java中的异常处理:从入门到精通
【8月更文挑战第28天】在Java编程的世界里,异常处理是一块基石,它确保了程序的健壮性和可靠性。本文将通过深入浅出的方式,带你了解Java异常处理的基本概念、分类、以及如何有效地捕获和处理异常。我们将一起探索try-catch-finally结构的奥秘,并学习如何使用throws关键字声明方法可能会抛出的异常。此外,我们还会讨论自定义异常类的创建和使用,以及最佳实践。无论你是Java新手还是有一定经验的开发者,这篇文章都将为你提供宝贵的知识,帮助你编写出更加稳定和可靠的代码。
|
23天前
|
编解码 网络协议 Oracle
java网络编程入门以及项目实战
这篇文章是Java网络编程的入门教程,涵盖了网络编程的基础知识、IP地址、端口、通讯协议(TCP和UDP)的概念与区别,并提供了基于TCP和UDP的网络编程实例,包括远程聊天和文件传输程序的代码实现。
java网络编程入门以及项目实战
|
9天前
|
Java 程序员
Java中的异常处理:从入门到精通
在Java编程的世界中,异常处理是保持程序稳定性和可靠性的关键。本文将通过一个独特的视角—把异常处理比作一场“捉迷藏”游戏—来探讨如何在Java中有效管理异常。我们将一起学习如何识别、捕捉以及处理可能出现的异常,确保你的程序即使在面对不可预见的错误时也能优雅地运行。准备好了吗?让我们开始这场寻找并解决Java异常的冒险吧!
|
1月前
|
前端开发 IDE Java
"揭秘前端转Java的秘径:SpringBoot Web极速入门,掌握分层解耦艺术,让你的后端代码飞起来,你敢来挑战吗?"
【8月更文挑战第19天】面向前端开发者介绍Spring Boot后端开发,通过简化Spring应用搭建,快速实现Web应用。本文以创建“Hello World”应用为例,展示项目基本结构与运行方式。进而深入探讨三层架构(Controller、Service、DAO)下的分层解耦概念,通过员工信息管理示例,演示各层如何协作及依赖注入的使用,以此提升代码灵活性与可维护性。
34 2
|
1月前
|
Java 测试技术 Spring
Java 新手入门:依赖注入的 N 种姿势,总有一款适合你!
Java 新手入门:依赖注入的 N 种姿势,总有一款适合你!
30 2