欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

带妹学Java第十九天(至递归)

程序员文章站 2024-03-23 12:23:28
...

重点

1.使用字符流的场景

	 * 1.使用FileReader读取字符
	 * 		原理:先读字节,把字节转成字符(byte -> char)
	 * 2.使用FileWriter写入字符
	 * 		原理:writer(String str),str 转成 字符数组 再转成 字节写入文件
	 *      (string -> char[] -> char -> byte)
	 * 如果是读取文本文件,使用FileReader比较好,不考虑乱码问题
	 * 如果是写入文本文件,不建议使用FileWriter,直接使用FileOutputStream好一点
         因为是字节直接写入文件,不需要过多数据类型转换

2.带缓冲的字符流

2.1概述

 BufferedReader/BufferedWriter
1.这两个类,内部都一个缓冲区,字符数组
2.br.read()方法,内部会读8192(81024)个字符
3.bw.write(),内部会写8192(8
1024)个字符
带妹学Java第十九天(至递归)回顾:带缓冲的字节流,BufferedInputStream/BufferedOutputStream

  1. 这两个类,内部都一个缓冲区,字节数组

2.2带缓冲字符流的使用

 使用BufferedReader、BufferedWriter读写文件

//1.创建Reader
		FileReader fr = new FileReader("a.txt");
		BufferedReader br = new BufferedReader(fr);
		
		//2.创建Writer
		FileWriter fw =new FileWriter("b.txt");
		BufferedWriter bw = new BufferedWriter(fw);
		
		//3.读写
		int c = 0;
		while( (c = br.read()) != -1){
			bw.write(c);
		}
		
		//4.关流
		br.close();//内部关闭FileReader
		bw.close();//内部关闭FileWriter

2.3BufferedReader的readLine()

 这个方法用于每次读取一行数据
 案例:使用readLine方法来读取文件

//1.创建Reader
		FileReader fr = new FileReader("a.txt");
		BufferedReader br = new BufferedReader(fr);
		
		//2.读一行数据
/*		System.out.println(br.readLine());
		System.out.println(br.readLine());
		System.out.println(br.readLine());
		System.out.println(br.readLine());
		System.out.println(br.readLine());
		System.out.println(br.readLine());*/
		String line = null;
		while((line = br.readLine()) != null){
			System.out.println(line);
		}
		
		//3.关流
		br.close();

2.4BufferedWriter的newLine()

 newLine方法是用于写文件时,添加换行,相当于”\r\n”

public static void main(String[] args) throws IOException {
		//需求:往b.txt写a.txt文件的内容【一行一行拷贝,读一行写一行】
		//1.创建Reader
		FileReader fr = new FileReader("a.txt");
		BufferedReader br = new BufferedReader(fr);
		
		//2.创建writer
		FileWriter fw = new FileWriter("b.txt");
		BufferedWriter bw = new BufferedWriter(fw);
		
		//3.读一行写一行
		String line = null;
		while((line = br.readLine()) != null){
			bw.write(line);
			/**
			 * 当使用readline读取一行数据时,不会读回车换行"\r\n"字符
			 */
			//bw.write("\r\n");
			bw.newLine();//换行
		}
		
		//4.关流
		br.close();
		bw.close();
	}

3.装饰(Decorator)设计模式

/**
		 * 一、设计模式【一种固定代码风格】
		 *     面试题:Java中有哪些设计模式
		 *     常用设计模式:装饰模式、单例模式、模版模式、适配器模式、代理模式、工厂模式...
		 * 
		 * 二、装饰(Decorator)设计模式
		 * 	1.装饰模式的概念:
			装饰模式是动态的给一个对象添加一些额外的功能,就增加功能来说,装饰模式比生成子类更为灵活。
			装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。
			装饰模式是创建一个包装对象,也就是使用装饰来包裹真实的对象。	
		    
		    2.装饰模式的实现方式
				1. 装饰对象和真实对象有相同的接口/抽象类。
				2. 装饰对象包含一个真实对象的引用(reference)
				3. 装饰对象的所有方法,内部实现都是通过真实对象的引用来调用,然后实现自己的功能

			3.适用性
				1. 需要扩展一个类的功能,或给一个类添加附加职责。
				2. 当不能采用生成子类来实现,比如final类	
		 */
public class Demo01 {
	public static void main(String[] args) {
	/*	BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
		BufferedOutputStream bos;
		BufferedReader br;
		BufferedWriter bw;*/
		
		/*GYFStudent stu = new GYFStudent();
		stu.code();*/
		
		GYFStudent stu = new GYFStudent(new UniversityStudent());
		stu.code();
	}
}

//1.接口
interface Person{
	public void code();
}

//2.接口实现类
final class UniversityStudent implements Person{
	@Override
	public void code() {
		// TODO Auto-generated method stub
		System.out.println("在大学期间学了一点点C语言...");
	}
}
/*class GYFStudent extends UniversityStudent{
	@Override
	public void code() {
		// TODO Auto-generated method stub
		super.code();
		System.out.println("在GYF IT EDU 学习Java语言...");
	}
}*/

class GYFStudent implements Person{
	private UniversityStudent us;
	public GYFStudent(UniversityStudent us){
		this.us = us;
	}	
	//装饰对象的所有方法,内部实现都是通过真实对象的引用来调用,然后实现自己的功能
	@Override
	public void code() {
		us.code();
		System.out.println("在GYF IT EDU 学习Java语言...");
	}	
}

4.编码字符流

4.1 InputStreamReader

 这个类用于使用指定的码表读写字符

//案例1:使用指定 “码表UTF-8&GBK” 读取字符
		/** charsetName:字符编码的名称 */
		FileInputStream fis = new FileInputStream("a.txt");
		InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
		//读一个字符
	/*	System.out.println((char)isr.read());
		System.out.println((char)isr.read());*/
		
		//读一行
		BufferedReader br = new BufferedReader(isr);
		System.out.println(br.readLine());
		br.close();

4.2OutputStreamWriter

 这个类使用指定的编码 写入文件

//1.创建Writer
		FileOutputStream fos = new FileOutputStream("c.txt");
		OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
		BufferedWriter bw = new BufferedWriter(osw);
		
		//2.写
		bw.write("你好,IO流...搞的我有点晕...");
		bw.newLine();
		bw.write("你好,IO流...搞的我有点晕...");
		bw.newLine();
		
		//3.关流
		bw.close();

5.递归

5.1概述

 递归是一种算法,在程序设计语言中广泛应用。
 递归:就方法内部调用自己
 递归的弊端:不能调用次数过多,容易导致栈内存溢出
 递归的好处:不用知道循环次数
 构造方法不能递归
 递归的方法可以有返回值,也可以没返回值

6.SequenceInputStream

序列流
 序列流可以把多个字节输入流整合成一个, 从序列流中读取数据时,
 将从被整合的第一个流开始读, 读完一个之后继续读第二个, 以此类推.

练习题

1.使用readLine方法来读取文件

//1.创建Reader
		FileReader fr = new FileReader("a.txt");
		BufferedReader br = new BufferedReader(fr);
		
		//2.读一行数据
/*		System.out.println(br.readLine());
		System.out.println(br.readLine());
		System.out.println(br.readLine());
		System.out.println(br.readLine());
		System.out.println(br.readLine());
		System.out.println(br.readLine());*/
		String line = null;
		while((line = br.readLine()) != null){
			System.out.println(line);
		}
		
		//3.关流
		br.close();

2.将文本反转写入另一个文件

/**
 * 掌握思想:
 * 1.for循环的倒序遍历
 */
public class Demo01 {
	public static void main(String[] args) throws IOException {
		//案例:将文本反转写入另一个文件
		
		//1.把文本每一行内容读取出来存在List<String> 集合
		//1.1 集合对象
		List<String> list = new ArrayList<String>();
		
		//1.2一行行读取文件
		BufferedReader br = new BufferedReader(new FileReader("a.txt"));
		String line = null;
		while((line = br.readLine()) != null){
			list.add(line);
		}
		
		System.out.println(list);
		
		//2.当我们要写入文件时,倒序保存List集合中的内容到文件中
		BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
		for(int i = list.size() - 1 ; i>=0; i--){
			bw.write(list.get(i));
			bw.newLine();//换行 
		}
		
		//3.关闭流
		br.close();
		bw.close();
		System.out.println("finish....");
	}
}

3.获取文本上字符出现的次数

/** 掌握:当键盘敲 enter键,两个字符\r\n : 回车换行*/
public class Demo01 {
	public static void main(String[] args) throws IOException {
		//练习:获取文本上字符出现的次数,把数据写入文件
/*		思路:
		1.遍历文本每一个字符
		2.字符出现的次数存在Map中
		*//**
		 * Map<Character,Integer> map = new HashMap<Character,Integer>();
		 * map.put('a',18);
		 * map.put('你',2);
		 *//*
		3.把map中的数据写入文件*/

		//==================================
		//1.创建Map集合
		Map<Character,Integer> map = new HashMap<Character,Integer>();
		//System.out.println(map.get('a'));
		
		//2.遍历每一个字符,每一个字符出现的次数放到map中
		FileReader reader = new FileReader("a.txt");
		int c = 0;
		while((c = reader.read()) != -1){
			//int 还原 char
			char ch = (char)c;
			// 判断char是否在map中第一次出现
			if(map.get(ch) == null){
				map.put(ch, 1);
			}else{
				map.put(ch, map.get(ch) + 1);
			}
		}
		
		//3.把map中数据存在文件count.txt
		//3.1 创建Writer
		BufferedWriter bw = new BufferedWriter(new FileWriter("count.txt"));
		
		//3.2 遍历map,再写入数据
		for(Entry<Character, Integer> entry :map.entrySet()){
			switch (entry.getKey()) {
			case ' ':
				bw.write("空格=" + entry.getValue());
				break;
			case '\t'://\t表示tab 键字符
				bw.write("tab键=" + entry.getValue());
				break;
			case '\r'://
				bw.write("回车=" + entry.getValue());
				break;
			case '\n'://
				bw.write("换行=" + entry.getValue());
				break;
			default:
				bw.write(entry.getKey() + "=" + entry.getValue());
				break;
			}
			bw.newLine();
		}
		
		//4.关流
		reader.close();
		bw.close();
	}
}

4.递归5的阶乘

  • 方法1

带妹学Java第十九天(至递归)

  • 方法2
  • 带妹学Java第十九天(至递归)

5.递归文件目录

public class Demo01 {
	public static void main(String[] args) {
		//递归:文件目录
		/**打印出a目录所有文件名称,包括子文件夹的文件*/
		
		//1.创建目录对象
		File dir = new File("C:/Users/10301/Desktop/a");
		
		//2.打印目录的子文件
		printSubFile(dir);
	}
	
	public static void printSubFile(File dir){
		//打印目录的子文件
		File[] subfiles = dir.listFiles();
		
		for(File f : subfiles){
			if(f.isDirectory()){//文件夹
				printSubFile(f);
			}else{//文件
				System.out.println(f.getAbsolutePath());
			}
			
		}
	}
}

6.从键盘输入文件夹路径,打印该文件夹下所有的.jpg文件名

public class Demo02 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//练习:从键盘输入接收一个文件夹路径,打印出该文件夹下所有的.jpg文件名
		//1.获取文件路径
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入一个文件夹路径...");
		String path = scanner.nextLine();
		
		//2.把路径封装成File对象
		File file = new File(path);
		if(!file.exists()){
			System.out.println("此路径对应的文件不存在");
			return;
		}
		
		if(!file.isDirectory()){
			System.out.println("请输入文件夹路径,而不文件路径");
			return;
		}
		
		//3.遍历文件夹下的子文件
		printSubFile(file);
		
	}
	
	public static void printSubFile(File dir){
		//打印目录的子文件
		File[] subfiles = dir.listFiles();
		
		for(File f : subfiles){
			if(f.isDirectory()){//文件夹
				printSubFile(f);
			}else{//文件
				if(f.getName().endsWith(".jpg")){
					System.out.println(f.getAbsolutePath());
				}
			}
		}
	}
}

7.把两个文件内容写到一个文件中

方法一
带妹学Java第十九天(至递归)
方法二
带妹学Java第十九天(至递归)

8.把三个文件内容写到一个文件中

public class Demo01 {
	public static void main(String[] args) throws Exception {
		//SequenceInputStream序列流使用二
		//需求,把a.txt b.txt c.txt 的内容拷贝到d.txt
		//1.Vector是集合
		Vector<InputStream> vector = new Vector<InputStream>();
		vector.add(new FileInputStream("a.txt"));
		vector.add(new FileInputStream("b.txt"));
		vector.add(new FileInputStream("c.txt"));
		
		//2.Enumeration枚举
		Enumeration<InputStream> e = vector.elements();
		
		//3.序列流
		SequenceInputStream sis = new SequenceInputStream(e);
		
		//4.创建输出流
		FileOutputStream fos = new FileOutputStream("d.txt");
		
		//读写 
		int b = 0;
		while((b = sis.read()) != -1){
			fos.write(b);
		}
		
		sis.close();
		fos.close();
	}
}

面试题

1.Java中有哪些设计模式

常用设计模式:装饰模式、单例模式、模版模式、适配器模式、代理模式、工厂模式…

总结

今天学习了字符流、装饰设计模式、递归。认识到了使用装饰设计模式的好处,可以拓展方法的功能,不局限继承。另外知道了递归的原理,方法内调用方法。
但不能递归次数太多,因为方法是在内存中的栈区,多次递归容易导致内存溢出。

相关标签: # Java java