小学数学练习-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 Map全攻略,一篇文章就够了!
【10月更文挑战第17天】本文详细介绍了Java编程中Map的使用,涵盖Map的基本概念、创建、访问与修改、遍历方法、常用实现类(如HashMap、TreeMap、LinkedHashMap)及其特点,以及Map在多线程环境下的并发处理和性能优化技巧,适合初学者和进阶者学习。
48 3
|
10天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
16天前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
22天前
|
存储 安全 Java
🌟Java零基础-反序列化:从入门到精通
【10月更文挑战第21天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
63 5
|
19天前
|
安全 Java 调度
Java中的多线程编程入门
【10月更文挑战第29天】在Java的世界中,多线程就像是一场精心编排的交响乐。每个线程都是乐团中的一个乐手,他们各自演奏着自己的部分,却又和谐地共同完成整场演出。本文将带你走进Java多线程的世界,让你从零基础到能够编写基本的多线程程序。
32 1
|
26天前
|
Java 数据处理 开发者
Java多线程编程的艺术:从入门到精通####
【10月更文挑战第21天】 本文将深入探讨Java多线程编程的核心概念,通过生动实例和实用技巧,引导读者从基础认知迈向高效并发编程的殿堂。我们将一起揭开线程管理的神秘面纱,掌握同步机制的精髓,并学习如何在实际项目中灵活运用这些知识,以提升应用性能与响应速度。 ####
43 3
|
27天前
|
Java
Java中的多线程编程:从入门到精通
本文将带你深入了解Java中的多线程编程。我们将从基础概念开始,逐步深入探讨线程的创建、启动、同步和通信等关键知识点。通过阅读本文,你将能够掌握Java多线程编程的基本技能,为进一步学习和应用打下坚实的基础。
|
29天前
|
存储 安全 Java
从入门到精通:Java Map全攻略,一篇文章就够了!
【10月更文挑战第19天】本文介绍了Java编程中重要的数据结构——Map,通过问答形式讲解了Map的基本概念、创建、访问与修改、遍历方法、常用实现类(如HashMap、TreeMap、LinkedHashMap)及其特点,以及Map在多线程环境下的使用和性能优化技巧,适合初学者和进阶者学习。
44 4
|
1月前
|
开发框架 IDE Java
java制作游戏,如何使用libgdx,入门级别教学
本文是一篇入门级教程,介绍了如何使用libgdx游戏开发框架创建一个简单的游戏项目,包括访问libgdx官网、设置项目、下载项目生成工具,并在IDE中运行生成的项目。
50 1
java制作游戏,如何使用libgdx,入门级别教学
|
28天前
|
Java
[Java]Socket套接字(网络编程入门)
本文介绍了基于Java Socket实现的一对一和多对多聊天模式。一对一模式通过Server和Client类实现简单的消息收发;多对多模式则通过Server类维护客户端集合,并使用多线程实现实时消息广播。文章旨在帮助读者理解Socket的基本原理和应用。
23 1