zoukankan      html  css  js  c++  java
  • Java从入门到实战之(17)递归&字节流&字符流练习(1)

    递归就是“在一个方法内可以再次调用自身”,如下,method方法又调用了method方法。

    package cn.demo.digui;
    
    
    
    public class DiGui {
    
    /*
    
    * 递归: 方法自己调用自己 . public void fun(){ fun(); }
    
    */
    
    public static void main(String[] args) {
    
    story();
    
    }
    
    static int count = 2;
    
    public static void story() {
    
    count++;
    
    System.out.println("东方红");
    
    System.out.println("太阳升");
    
    System.out.println("中国出了个大醉侠");
    
    System.out.println("他为人民谋幸福 呼儿嗨哟 ");
    
    System.out.println(count);
    
    story();
    
    }
    
    }

    上面的程序运行后,控制台会一直打印:调用method();当然,运行不久就会看到JVM抛出“堆栈溢出异常”——它类似于“无限循环”,但它比循环更消耗内存;

    堆栈溢出异常如下:

    递归方法开始调用后,在内存中会存在多个method方法,每个method方法均会等待它调用的method方法执行完毕,自己才会执行完毕。

    2 递归的注意事项

    • 递归调用必须要在某个条件下结束,否则就是死递归。

    • 递归调用的层次不能太多,否则会堆栈溢出。

    • 构造方法不能递归调用

    IO概述

    回想之前写过的程序,数据都是在内存中,一旦程序运行结束,这些数据都没有了,等下次再想使用这些数据,可是已经没有了。那怎么办呢?能不能把运算完的数据都保存下来,下次程序启动的时候,再把这些数据读出来继续使用呢?其实要把数据持久化存储,就需要把内存中的数据存储到内存以外的其他持久化设备(硬盘、光盘、U盘等)上。

    当需要把内存中的数据存储到持久化设备上这个动作称为输出(写)Output操作。

    当把持久设备上的数据读取到内存中的这个动作称为输入(读)Input操作。

    因此我们把这种输入和输出动作称为IO操作。

    IO流分类

    按照流向分:输入流与输出流,每个IO流对象均要绑定一个IO资源

    按照类型分:常以字节流与字符流区分

    分类关系如下:

    • 字节流

      • 字节输入流 InputStream 抽象类

        • FileInputStream 操作文件的字节输入流

      • 字节输出流 OuputStream 抽象类

        • FileOutputStream 操作文件的字节输出流

    • 字符流

      • 字符输入流 Reader抽象类

        • InputStreamReader 输入操作的转换流

        • FileReader 用来操作文件的字符输入流(简便的流)

      • 字符输出流 Writer抽象类

        • OutputStreamWriter 输出操作的转换流

        • FileWriter 用来操作文件的字符输出流(简便的流)

    • 数据单位: 

      • 操作字节的流: 字节流 , 任何数据,底层都是字节. (文档,图片,mp3.....)

      • 操作字符的流: 字符流 . 只能操作文本文件.

    • 字节流

      2.2.1 一切均为字节

      在数据传输过程中,一切数据(文本、图像、声音等)最终存储的均为一个个字节,即二进制数字。所以数据传输过程中使用二进制数据可以完成任意数据的传递。

      我们向一个文件中存储一定数据(一些数字),如果使用文本方式打开,则会以文本的方式解释数据。如果以视频的方式打开,则会以视频的方式解释数据。音频、可行执行文件等亦是如此。所以,在文件传输过程中,我们要时刻明确,传输的始终为数据。

      2.2.2 字节输出流

      输出流:OutputStream(抽象类):FileOutputStream(基本输出流)

      构造方法:需要绑定IO资源

      public FileOutputStream(String name)   创建覆盖写出对象

      public FileOutputStream(String name,boolean append) 创建指定是否追加写出对象

      其他方法: 写出时,如果没有该文件对象,会自动创建文件对象

    • write(int n):输出一个字节;(使用int替代了byte)

      write(byte[] b):输出一个字节数组;

      write(byte[] b, int off , int len):输出字节数组的一部分;

      flush():刷新此输出流并强制写出所有缓冲的输出字节;

      close(): 由于每个IO流都需要绑定一个IO资源,在使用时,需要回收资源

    FileOutputStream类,文件输出流

    OutputStream有很多子类,其中子类FileOutputStream可用来写入数据到文件。

    FileOutputStream类,即文件输出流,是用于将数据写入 File的输出流。

    FileOutputStream类写入数据到文件中

    • 将数据写到文件中,代码演示如下:

    package cn.demo.digui;
    
    
    
    import java.io.File;
    
    import java.io.FileOutputStream;
    
    import java.io.IOException;
    
    
    
    public class Demo2 {
    
    public static void main(String[] args) throws IOException {
    
    // 需求:将数据写入到文件中。
    
    // 创建存储数据的文件。
    
    File file = new File("D:\FileDemo\01.txt");
    
    // 创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。
    
    // 输出流目的是文件,会自动创建。如果文件存在,则覆盖。
    
    FileOutputStream fos = new FileOutputStream(file);
    
    // 调用父类中的write方法。
    
    byte[] data = "我是中国人".getBytes();
    
    fos.write(data);
    
    // 关闭流资源。
    
    fos.close();
    
    }
    
    }
    • 输出结果如下:

    给文件中续写和换行

    我们直接new FileOutputStream(file)这样创建对象,写入数据,会覆盖原有的文件,那么我们想在原有的文件中续写内容怎么办呢?

    继续查阅FileOutputStream的API。发现在FileOutputStream的构造函数中,可以接受一个boolean类型的值,如果值true,就会在文件末位继续添加。

    package cn.demo.digui;
    
    
    
    import java.io.File;
    
    import java.io.FileNotFoundException;
    
    import java.io.FileOutputStream;
    
    import java.io.IOException;
    
    public class Demo3 {
    
    public static void main(String[] args) throws IOException {
    
    // fun();
    
    fun2();
    
    // 追加数据
    
    // 创建存储数据的文件。
    
    File file = new File("D:\FileDemo\02.txt");
    
    // 创建流对象
    
    FileOutputStream fos = new FileOutputStream("D:\FileDemo\02.txt", true); // true
    
    // 表示可以追加
    
    // 写出数据
    
    fos.write(65);
    
    // 关闭 资源
    
    fos.close();
    
    }
    
    private static void fun2() throws FileNotFoundException, IOException {
    
    //1.创建流对象
    
    FileOutputStream fos = new FileOutputStream("D:\FileDemo\02.txt");
    
    // 2.写出数据
    
    String s = "hello io ";
    
    byte[] bytes = s.getBytes();
    
    fos.write(bytes);
    
    // 3.关闭流资源
    
    fos.close();
    
    }
    
    }

    文本复制:这块很重要,在实际开发中,经常用到,在这里只是非常的简单,还请多多练习,

    一个人可以被毁灭,但不能被打败。人生中到处是坎坷,你若不努力,爱情与面包都是别人的成果,对自己加油,不放弃!没有学习计算机的天分,那就只能多多练习)

    package cn.demo.digui;
    
    
    
    import java.io.File;
    
    import java.io.FileInputStream;
    
    import java.io.FileOutputStream;
    
    import java.io.IOException;
    
    /**
    
    * 复制文本与图片
    
    */
    
    public class CopyPhoto {
    
    public static void main(String[] args) throws IOException {
    
    // 1,明确源和目的。复制文本
    
    File srcFile = new File("D:\FileDemo\02.txt");// D:\FileDemo\02.txt
    
    File destFile = new File("D:\FileDemo\copyTest.txt");
    
    // 复制图片
    
    // File srcFile = new
    
    // File("D:\FileDemo\008.png");//D:\FileDemo\008.png
    
    // File destFile = new File("D:\FileDemo\copyTest.png");
    
    // 2,明确字节流 输入流和源相关联,输出流和目的关联。
    
    FileInputStream fis = new FileInputStream(srcFile);
    
    FileOutputStream fos = new FileOutputStream(destFile);
    
    // 3, 使用输入流的读取方法读取字节,并将字节写入到目的中。
    
    int ch = 0;
    
    while ((ch = fis.read()) != -1) {
    
    fos.write(ch);
    
    }
    
    // 4,关闭资源。
    
    fos.close();
    
    fis.close();
    
    }
    
    }

    输出结果如下图所示:

    上述代码输入流和输出流之间是通过ch这个变量进行数据交换的。

    上述复制文件有个问题,每次都从源文件读取一个,然后在写到指定文件,接着再读取一个字符,然后再写一个,一直这样下去。效率极低。

    临时数组方式复制文件

    上述代码复制文件效率太低了,并且频繁的从文件读数据,和写数据,能不能一次多把文件中多个数据都读进内容中,然后在一次写出去,这样的速度一定会比前面代码速度快。

    package cn.demo.digui;
    
    
    
    import java.io.File;
    
    import java.io.FileInputStream;
    
    import java.io.FileOutputStream;
    
    import java.io.IOException;
    
    /**
    
    * 复制文本与图片
    
    */
    
    public class CopyPhoto2 {
    
    public static void main(String[] args) throws IOException {
    
    // 1,明确源和目的。复制文本,
    
    File srcFile = new File("D:\FileDemo\03.txt");// D:\FileDemo\02.txt
    
    //创建文件,如果文件不存在,创建true,如果文件存在,则创建false,如果文件路径错误,IOException.
    
    //判断03.txt是否存在
    
    boolean b1 = srcFile.exists();
    
    System.out.println("b1="+b1);
    
    //创建03.txt文本
    
    boolean b2 = srcFile.createNewFile();
    
    System.out.println("b2="+b2);
    
    //复制的路径
    
    File destFile = new File("D:\FileDemo\copyTest3.txt");
    
    // 复制图片
    
    // File srcFile = new
    
    // File("D:\FileDemo\008.png");//D:\FileDemo\008.png
    
    // File destFile = new File("D:\FileDemo\copyTest.png");
    
    // 2,明确字节流 输入流和源相关联,输出流和目的关联。
    
    FileInputStream fis = new FileInputStream(srcFile);
    
    FileOutputStream fos = new FileOutputStream(destFile);
    
    /*// 3, 使用输入流的读取方法读取字节,并将字节写入到目的中。
    
    int ch = 0;
    
    while ((ch = fis.read()) != -1) {
    
    fos.write(ch);
    
    }*/
    
    //3.1定义一个缓冲区。
    
    byte[] buf = new byte[1024];
    
    int len = 0;
    
    while ((len = fis.read(buf)) != -1) {
    
    fos.write(buf, 0, len);// 将数组中的指定长度的数据写入到输出流中,buf 表示 存数据的数组, 0 表示开始的位置, len 有效字符个数
    
    }
    
    // 4,关闭资源。
    
    fos.close();
    
    fis.close();
    
    }
    
    }
     
  • 相关阅读:
    对眼睛有利的屏幕颜色
    C++的动态联编与静态联编【转载】
    关于虚析构函数
    虚析构函数的使用(转载!)
    c/c++内存机制(转)
    delete this
    PhpStorm环境配置
    flutter之路由与导航
    flutter之Widget
    Flutter项目初步认识
  • 原文地址:https://www.cnblogs.com/huanghanyu/p/13809083.html
Copyright © 2011-2022 走看看