java基础练习复习一:递归&字节流&字符流一

递归就是“在一个方法内可以再次调用自身”,如下,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();
	}
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值