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();

}

}
 
原文地址:https://www.cnblogs.com/huanghanyu/p/13809083.html