JAVA基础再回首(二十一)——递归、IO流概述、字节流写数据、读取数据、复制数据、字节缓冲流

JAVA基础再回首(二十一)——递归、IO流概述、字节流写数据、读取数据、复制数据、字节缓冲流

版权声明:转载必须注明本文转自程序员杜鹏程的博客:http://blog.csdn.net/m366917

不知不觉已经写了二十篇博客了,当你决定要去干一件事的时候,就要坚持,要有不达目的誓不罢休的精神。好了,不多说了,我们开始学习吧。

今天我们先来学习一个知识点叫递归。什么是递归呢,下面我们来看一下

递归

  • 递归
    • 方法定义中调用方法本身的现象

学习递归呢,我们要一定要学习他解决问题的思想

  • 递归解决问题的思想
    • 做递归要写一个方法
    • 找到出口条件
    • 找到规律

递归的注意事项

  • 递归一定要有出口,否则就是死递归
  • 递归的次数不能太多,否则就内存溢出
  • 构造方法不能递归使用

下面我们来做个小练习吧。用代码实现求5的阶乘。

//首先我们知道要实现5的阶乘,有两种方案
//一种是循环实现,一种是递归实现。我们这两种方案都实现一下
public class DiGuiDemo {
    public static void main(String[] args) {
        int jc = 1;
        for (int x = 2; x <= 5; x++) {
            jc *= x;
        }
        System.out.println("5的阶乘是:" + jc);

        System.out.println("5的阶乘是:"+jieCheng(5));
    }
    /*
     * 做递归要写一个方法:
     *      返回值类型:int
     *      参数列表:int n
     * 出口条件:
     *      if(n == 1) {return 1;}
     * 规律:
     *      if(n != 1) {return n*方法名(n-1);}
     */
    public static int jieCheng(int n){
        if(n==1){
            return 1;
        }else {
            return n*jieCheng(n-1);
        }
    }
}

输出结果
这里写图片描述

接下来我们终于可以学习期盼已久的IO流了。

IO流概述

  • IO流概述
    • IO流用来处理设备之间的数据传输
      • 上传文件和下载文件
    • Java对数据的操作是通过流的方式
    • Java用于操作流的对象都在IO包中
  • IO流分类
    • 按照数据流向
      • 输入流 读取数据
      • 输出流 写出数据
    • 按照数据类型
      • 字节流
        • 字节输入流 读取数据 InputStream
        • 字节输出流 写出数据 OutputStream
      • 字符流
        • 字符输入流 读取数据 Reader
        • 字符输出流 写出数据 Writer

我们了解了io流的分类,那么什么情况下使用哪种流呢?

  • 如果数据所在的文件通过windows自带的记事本打开并能读懂里面的内容,就用字符流。其他用字节流。
  • 如果你什么都不知道,就用字节流

注意:一般我们在探讨IO流的时候,如果没有明确说明按哪种分类来说,默认情况下是按照数据类型来分的。

  • IO流常用基类(这个我们上面也提到了)
    • 字节流的抽象基类:
      • InputStream ,OutputStream。
    • 字符流的抽象基类:
      • Reader , Writer。

注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。

  • 如:InputStream的子类FileInputStream。
  • 如:Reader的子类FileReader。

字节流写数据

OutputStream它的子类FileOutputStream

下面我们就来练习一下吧,往一个文本文件中输入一句话:”helloworld”
我们先来分析一下

这个操作最好是采用字符流来做,但是呢,字符流是在字节流之后才出现的,所以,先讲解字节流如何操作。
由于是要往文件中写一句话,所以我们要采用字节输出流(OutputStream)。
由于我们是往文件中写东西,所以就要用OutputStream它的子类FileOutputStream
那我们就来了解一下它的构造方法

  • FileOutputStream的构造方法
    • FileOutputStream(File file)
    • FileOutputStream(String name)
public class FileOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        // 创建字节输出流对象(FileOutputStream的这两种构造方法效果是一样的用那个都可以)

        // FileOutputStream(File file)
        // File file = new File("fos.txt");
        // FileOutputStream fos = new FileOutputStream(file);

        // FileOutputStream(String name)
        FileOutputStream fos = new FileOutputStream("fos.txt");


        //写数据
        fos.write("helloworld".getBytes());
        fos.write("java".getBytes());

        //释放资源
        //关闭此文件输出流并释放与此流有关的所有系统资源。
        fos.close();
    }
}

运行程序,我们刷新项目可以看到,有一个fos.txt的文件,里面的内容是helloworld。

我们来总结一下

  • 我们最后为什么一定要close()呢?

    • 让流对象变成垃圾,这样就可以被垃圾回收器回收了
    • 通知系统去释放跟该文件相关的资源
  • 字节输出流操作步骤:

    • A:创建字节输出流对象
    • B:写数据
    • C:释放资源

    这总结写的么问题吧,让你的思路更清晰,代码写的更流畅

字节流写数据的方式

查看API可以知道,字节流写数据一共有三种方式,下面我们来学习一下

  • public void write(int b) :写一个字节
  • public void write(byte[] b):写一个字节数组
  • public void write(byte[] b,int off,int len):写一个字节数组的一部分

我们就在上面的那个例子中来操作吧

        // 调用write()方法
        fos.write(97); //输出结果是97 -- 底层二进制数据 -- 通过记事本打开 -- 找97对应的字符值 -- a

        //public void write(byte[] b):写一个字节数组
        byte[] bys={97,98,99,100,101};
        fos.write(bys);//输出结果是abcde

        //public void write(byte[] b,int off,int len):写一个字节数组的一部分
        fos.write(bys,1,3);//输出结果是bcd

我们学完了字节流写数据的方法,下面就来学习一下字节流读取数据的方法吧

字节流读取数据

InputStream的子类FileInputStream
学习了写数据,那么来学习读取数据就好理解多了

  • FileInputStream的构造方法
    • FileInputStream(File file)
    • FileInputStream(String name)
  • FileInputStream的成员方法
    • public int read():一次读取一个字节
    • public int read(byte[] b):一次读取一个字节数组

我们先来看下字节输入流操作步骤:

  • A:创建字节输入流对象
  • B:调用read()方法读取数据,并把数据显示在控制台
  • C:释放资源

和写数据相比只要第二步我们不了解,那下面就来学习

    //我们在项目中新建一个fis.txt文件,并写入helloword数据,然后用代码实现读取它
    public class FileInputStreamDemo {
    public static void main(String[] args) throws IOException {
        //创建字节输入流对象
        FileInputStream fis = new FileInputStream("fis.txt");

        int by = 0;
        // 读取,赋值,判断
        while ((by = fis.read()) != -1) {
            System.out.print((char) by);
        }

        // 释放资源
        fis.close();
    }
}

运行程序可以发现fis.txt文件中的helloword内容显示在了控制台

假如我们要读取字节数比较大的文件的时候,我们就不能一次读取一个字节了,就要一次读取一个字节数组。那么就是FileInputStream成员方法中的第二种了,下面我们用代码演示一下:

    // 数组的长度一般是1024或者1024的整数倍
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = fis.read(bys)) != -1) {
            System.out.print(new String(bys, 0, len));
        }

这样就可以一次读取1024个字节数了,读取大文件的时候速度也比较快。

字节流复制数据

我们上面学习了写数据和读取数据,前面也学习了File的操作,那么我们可不可以字节流复制数据也就是复制文本文件的一些操作呢,那肯定是可以的了。我们就来见识一下它的厉害吧!

  • 数据源:从哪里来
    • a.txt – 读取数据 – FileInputStream
  • 目的地:到哪里去
    • b.txt – 写数据 – FileOutputStream
public class CopyFileDemo {
    public static void main(String[] args) throws IOException {
        // 封装数据源
        FileInputStream fis = new FileInputStream("a.txt");
        // 封装目的地
        FileOutputStream fos = new FileOutputStream("b.txt");

        int by = 0;
        while ((by = fis.read()) != -1) {
            fos.write(by);
        }
        // 释放资源(先关谁都行)
        fos.close();
        fis.close();
    }
}

这样我们就完成了把a.txt复制了一份并命名为b.txt的文件了
但是我们平时在开发中要负责一个文件的话,不这样写,要用一次读取一个字节数组的方法来写

public class CopyFileDemo {
    public static void main(String[] args) throws IOException {
        // 封装数据源
        FileInputStream fis = new FileInputStream("a.txt");
        FileOutputStream fos = new FileOutputStream("b.txt");

        // 复制数据
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = fis.read(bys)) != -1) {
            fos.write(bys, 0, len);
        }

        // 释放资源
        fos.close();
        fis.close();
    }
}

字节缓冲流

字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想(装饰设计模式),所以提供了字节缓冲区流
这种类被称为:缓冲区类(高效类)

  • 字节缓冲输出流
    • BufferedOutputStream
  • 字节缓冲输入流
    • BufferedInputStream

我们先用字节缓冲输出流来把一个字符串写到文件中

public class BufferedOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        // BufferedOutputStream(OutputStream out)
        // 简单的写法
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream("bos.txt"));

        // 写数据
        bos.write("hello".getBytes());

        // 释放资源
        bos.close();
    }
}

这样我们就把hello这个字符串转化为字节写到了bos.txt 中
然后我们来学习读取数据

public class BufferedInputStreamDemo {
    public static void main(String[] args) throws IOException {
        // BufferedInputStream(InputStream in)
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                "bos.txt"));

        // 读取数据
        int by = 0;
        while ((by = bis.read()) != -1) {
            System.out.print((char) by);
        }

        // 释放资源
        bis.close();
    }
}

很明显我们有两种方式可以读取,上面的读取数据的方法也可以写成下面这样的

        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            System.out.print(new String(bys, 0, len));
        }

但是要注意,这两种方式针对同一个对象在一个代码中只能使用一个。

学了这么多,别忘了多练习一下哦。
好了,今天IO流就学到这里了。下篇我们继续来学习。

欢迎有兴趣的同学加我朋友的QQ群:点击直接加群555974449 请备注:java基础再回首我们一起来玩吧。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值