IO流和Lambda表达式

IO流和Lambda表达式

1. IO流
1.1 IO流概述
IO流
	流 水流,电流,气流 
	IO  Input 输入  Output 输出
		输入输出是存在参照物,参照物是当前运行程序。
IO流在开发中的用途
	1. 文件内容操作
	2. 网络数据传输 TCP/IP UDP NIO Netty WebSocket
	3. 数据库内容传递

IO分类
	输入流
		字节输入流
		字符输入流
	输出流
		字节输出流
		字符输出流
1.2 IO流操作涉及到的类
字节输入流
	InputStream 字节输入流基类
	--| FileInputStream 文件操作字节输入流

字节输出流
	OutputStream 字节输出流基类
	--| FileOutputStream 文件操作字节输出流

字符输入流
	Reader 字符输入流基类
	--| FileReader 文件操作字符输入流
字符输出流 
	Writer 字符输出流基类
	--| FileWriter 文件操作字符输出流

学习的方法:
	read
	write
1.3 文件操作字节输入流
构造方法:
	FileInputStream(String pathName);
	FileInputStream(File file);
		一个是根据用户给定的文件路径,一个是根据用户给定的File对象,创建对应的文
		件操作字节输入流,存在异常抛出 FileNotFoundException 文件未找到异常
	
操作方法:
	int read();
		从文件中读取一个字节数据返回。
	int read(byte[] buf);
		从文件中读取数据到当前byte类型数组中,返回值类型是读取到byte类型数组中的
		字节个数
	int read(byte[] buf, int off, int len);
		从文件中读取数据到当前byte类型数组中,要求从off偏移量位置开始,计数长度
		为len,返回值类型是读取到的字节个数
	【注意】
		1.以上所有的read方法,如果读取到文件末尾,返回值为 -1 EOF End Of 
		File
		2. 所有的read方法,都会抛出IOException
package com.qfedu.a_io;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
 * 文件操作字节输入流
 * FileInputStream
 * 
 * 1. 确定文件
 * 2. 开启FileInputStream通道
 * 3. 使用read方法读取数据和数据处理
 * 4. 关闭资源
 */
public class Demo1 {
	public static void main(String[] args) throws IOException {
	}

	public static void readTest2() throws FileNotFoundException, IOException {
		// 1. 确定文件
		String filePath = "G:/aaa/你大爷的.txt";

		// 2. 开启FileInputStream通道
		FileInputStream fis = new FileInputStream(filePath);
		
		// 3. 读取数据,需要准备一个byte类型数组 当前缓冲数组容量为8KB
		byte[] buf = new byte[1024 * 8];
		int length = -1;
		
		while ((length = fis.read(buf)) != -1) {
			// 将读取到的数据,转换成一个String字符串
			System.out.println(new String(buf, 0, length));
		}
		
		// 4. 关闭资源
		fis.close();
	}

	public static void readTtest1() throws FileNotFoundException, IOException {
		// 1. 确定文件
		String filePath = "G:/aaa/你大爷的.txt";

		// 2. 开启FileInputStream通道
		FileInputStream fis = new FileInputStream(filePath);

		int content = -1;
		// 3. 读取数据
		while ((content = fis.read()) != -1) {
			System.out.println((char) content);
		}

		// 4. 关闭资源
		fis.close();
	}
}
1.4 文件操作字节输出流
构造方法:
	FileOutputStream(String filePath);
	FileOutputStream(File file);
	FileOutputStream(String filePath, boolean append);
	FileOutputStream(File file, boolean append));
		根据用户给定的文件路径或者File类对象,创建对应FileOutputStream对象。
	【注意】
		1. 在创建FileOutputStream流对象过程中,如果文件不存在,并且路径合
		法!!!可以直接创建对应文件。
		2. 在未约束FileOutputStream对象情况下,默认采用的写入数据模式是删除
		写。如果想要追加写,在构造方法中添加一个参数 boolean append 赋值为
		true
操作方法:
	void write(int b);
		写入一个字节数据到文件中,要求数据类型为int类型,但是实际写入数据是int类
		型低8位 ==> byte类型数据
	void write(byte[] buf);
		写入一个字节数组到文件中
	void write(byte[] buf, int off, int len);
		写入一个字节数组到文件中,要求从off偏移位置开始,指定长度为len
package com.qfedu.a_io;

import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 文件操作字节输出流
 * 
 *  1. 确定文件位置
 *  2. 打开FileOutputStream流管道
 *  3. 写入数据 write
 *  4. 关闭资源
 */
public class Demo2 {
	public static void main(String[] args) throws IOException {
		// 1. 确定文件位置
		String filePath = "G:/aaa/你二大爷的.txt";
		
		// 2. 创建FileOutputStream流管道
		FileOutputStream fos = new FileOutputStream(filePath);
		
		// 3. 写入数据
		fos.write(550);
		fos.write("ABCDEFG".getBytes());
		fos.write("ABCDEFG".getBytes(), 2, 5);
		
		// 4. 关闭close
		fos.close();
	}
}
1.5 字节流拷贝文件
package com.qfedu.a_io;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 字节流拷贝文件
 */
public class Demo3 {
	public static void main(String[] args) throws IOException {
		long start = System.currentTimeMillis();
		// 1. 开启FileInputStream对象
		FileInputStream fis = new FileInputStream("G:/aaa/1.mp4");
		
		// 2. 开启FileOutputStream对象
		FileOutputStream fos = new FileOutputStream("G:/aaa/华哥の帅帅.mp4");
		
		// 3. 准备缓冲数组
		byte[] buf = new byte[1024 * 8];
		int length = -1;
		
		// 4. 读取数据,写入数据
		while ((length = fis.read(buf)) != -1) {
			fos.write(buf, 0, length);
		}
		
		// 5. 关闭资源,先开后关,后开先关
		fos.close();
		fis.close();
		long end = System.currentTimeMillis();
		
		System.out.println("Time : " + (end - start));
	}
}
1.6 字符流操作限制
1. 操作对应的文件有且只能是记事本可以打开的可视化文本文件。
2. 要求操作过程中,文件对应的编码集和当前程序对应编码集一致。
1.7 文件操作字符输入流
构造方法:
	FileReader(String pathName);
	FileReader(File file);
		一个是根据用户给定的文件路径,一个是根据用户给定的File对象,创建对应的文
		件操作字节输入流,存在异常抛出 FileNotFoundException 文件未找到异常
	
操作方法:
	int read();
		从文件中读取一个字符数据返回。
	int read(char[] buf);
		从文件中读取数据到当前byte类型数组中,返回值类型是读取到char类型数组中的
		字符个数
	int read(char[] buf, int off, int len);
		从文件中读取数据到当前char类型数组中,要求从off偏移量位置开始,计数长度
		为len,返回值类型是读取到的字符个数
	【注意】
		1.以上所有的read方法,如果读取到文件末尾,返回值为 -1 EOF End Of 
		File
		2. 所有的read方法,都会抛出IOException

1.8 文件操作字符输出流

构造方法:
	FileWriter(String filePath);
	FileWriter(File file);
	FileWriter(String filePath, boolean append);
	FileWriter(File file, boolean append));
		根据用户给定的文件路径或者File类对象,创建对应FileWriter对象。
	【注意】
		1. 在创建FileWriter流对象过程中,如果文件不存在,并且路径合
		法!!!可以直接创建对应文件。
		2. 在未约束FileWriter对象情况下,默认采用的写入数据模式是删除
		写。如果想要追加写,在构造方法中添加一个参数 boolean append 赋值为
		true
操作方法:
	void write(int b);
		写入一个字符数据到文件中,要求数据类型为int类型,但是实际写入数据是int类
		型低16位 ==> byte类型数据
	void write(byte[] buf);
		写入一个字节数组到文件中
	void write(byte[] buf, int off, int len);
		写入一个字节数组到文件中,要求从off偏移位置开始,指定长度为len
	void write(String str);
	void write(String str, int off, int len);	
2. 缓冲流
2.1 缓冲的概念
CPU通过内存读取硬盘数据的小要求
	1. 磁盘每一个扇区是4096字节
	2. CPU每一次读取数据都需要首先从磁盘中读取4096字节

缓冲的使用
	1. 提供程序操作文件的效率
	2. 可以保护磁盘
2.2 缓冲流对应类
	缓冲流没有任何的读写能力。只是一个仓库中转站。只是提供缓冲和临时存储功能。所有的读写能力都来自于对应输入流和输出流
	BufferedInputStream
		字节缓冲输入流
			构造方法所需参数是InputStream对象。需要字节输入流来提供读取文件的
			能力。
	BufferedOutputStream
		字节缓冲输出流
			构造方法所需参数OutputStream对象,需要字节输出流提供写入数据到文件
			的能力
	BufferedReader
		字符缓冲输入流
			构造方法所需参数Reader对象,需要字符输出流提供读取数据到文件
			的能力
		String readLine(); 读取一行数据
	BufferedWriter
		字符缓冲输出流
			构造方法所需参数Writer对象,需要字符输出流提供写入数据到文件
			的能力 
		void newLine(); 在文件中换行
2.3 字节缓冲操作,输入输出
package com.qfedu.b_buffered;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 字节缓冲
 */
public class Demo1 {
	public static void main(String[] args) throws IOException {
		writeTest();
		bufferedWrite();

	}

	public static void writeTest() throws FileNotFoundException, IOException {
		long start = System.currentTimeMillis();
		FileOutputStream fis = new FileOutputStream("G:/aaa/十三姨.txt");

		String str = "黄飞鸿 大战 马保国 之 年轻人不讲武德,耗子尾汁\n";

		int num = 1000000;
		while (num > 0) {
			fis.write(str.getBytes());
			num--;
		}
		
		fis.close();
		long end = System.currentTimeMillis();
		System.out.println(end - start);
	}

	public static void bufferedWrite() throws FileNotFoundException, IOException {
		long start = System.currentTimeMillis();
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("G:/aaa/十三姨.txt"));

		String str = "黄飞鸿 大战 马保国 之 年轻人不讲武德,耗子尾汁\n";

		int num = 1000000;

		while (num > 0) {
			bos.write(str.getBytes());
			num--;
		}

		bos.close();
		long end = System.currentTimeMillis();
		// 33
		System.out.println(end - start);
	}

	public static void readTest() throws FileNotFoundException, IOException {
		long start = System.currentTimeMillis();
		FileInputStream fis = new FileInputStream("G:/aaa/你大爷的.txt");

		while (fis.read() != -1) {

		}

		fis.close();

		// 10000ms
		long end = System.currentTimeMillis();
		System.out.println(end - start);
	}

	public static void bufferedReadFile() throws FileNotFoundException, IOException {
		long start = System.currentTimeMillis();

		/*
		 * BufferedInputStream 默认情况下底层是一个8KB字节缓冲数组,所有的读取文件的操作都是在当前
		 * 缓冲数组中完成的,读取在内存数组中获取数据,如果数组数据读取完毕,一次性从硬盘读取8KB数据。
		 */
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("G:/aaa/你大爷的.txt"));

		while (bis.read() != -1) {

		}

		// 130ms
		bis.close();
		long end = System.currentTimeMillis();
		System.out.println(end - start);
	}
}
2.4 缓冲字符流操作读写
package com.qfedu.b_buffered;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Demo2 {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new FileReader("G:/aaa/十三姨.txt"));
		
		System.out.println(br.readLine());
		
		br.close();
		
		BufferedWriter bw = new BufferedWriter(new FileWriter("G:/aaa/十三姨夫.txt"));
		
		bw.write("吴京\n");
		bw.write("张译\n");
		bw.write("管虎\n");
		bw.write("郭帆\n");
		
		bw.close();
	}
}
3. Lambda表达式【重点】
3.1 Lambda表达式使用条件
1. 存在接口
2. 接口中有且只有一个未实现方法,该接口可以认为是【函数式接口】。在原码中存在使用注解@FunctionalInterface 来约束当前接口
3. Lambda表达式用于方法中,要求当前方法的参数是接口,需要为接口的实现类对象。

【说重点】
	一个接口中有且只有一个未实现的abstract方法
	--| 目标 就是为了使用该方法
	----| class 类来遵从当前接口,需要必须实现缺省属性为abstract的方法,
	------| 在方法中传入接口的实现类,最终目标是为了通过实现类对象来调用方法。
	
	Lambda就是直接实现当前方法运行内容 ==> 方法体!!!
3.2 无参数无返回值Lambda
package com.qfedu.c_lambda;

/*
 * 无参数无返回值Lambda
 * 和接口名字无关,只是在考虑当前接口中唯一没有实现的方法,返回值类型为void,参数为空
 * 
 * @FunctionalInterface 函数式接口注解/标记,要求当前接口中有且只有一个未完成方法
 */
@FunctionalInterface
interface A {
	void test();
}

public class Demo1 {
	public static void main(String[] args) {
		
		// low
		testLambda(() -> {
			System.out.println("无参数无返回值Lambda表达式");
		});
		
		// 如果Lambda表达式有且一行代码,可以省略大括号!!!
		testLambda(() -> System.out.println("这才是最好的!!!")); 
	}
	
	public static void testLambda(A a) {
		a.test();
	}
}
3.3 有参数无返回值Lambda
消费方法接口
	当前Lambda表达式对应接口中的方法,有参数,但是没有返回值,这是一个消费方法接口,数据通过当前Lambda处理之后,没有任何的反馈。是最终处理模式!!!
package com.qfedu.c_lambda;

import java.util.ArrayList;

/*
 * 消费接口,接收数据,但是没有反馈
 */
@FunctionalInterface
interface Consumer<T> {
	// 接口数据方法 需要的类型还是泛型!!!
	void accept(T t);
}

public class Demo2 {
	public static void main(String[] args) {
		testLambda("让我看到你的眼!!!", 
				// 脑补数据类型 t ==> String类型 t会成为当前Lambda表达式对应代码块中的局部变量参数
				(str) -> System.out.println(str));
		
		ArrayList<String> list1 = new ArrayList<String>();
		
		list1.add("雪碧");
		list1.add("芬达");
		list1.add("可口可乐");
		list1.add("酷儿");
		list1.add("酸梅汤");
		
		testLambda(list1, (list) -> {
			for (String string : list1) {
				System.out.println(string);
			}
		});
		
		testLambda(10, (i) -> System.out.println("low : " + i));
	}

	/**
	 * 当前方法带有自定义泛型,泛型对应的具体数据类型,通过第一个参数约束
	 * 
	 * @param <T>      自定义泛型
	 * @param t        用于约束当前泛型对应具体数据类型的参数
	 * @param consumer 消费处理数据的接口
	 */
	public static <T> void testLambda(T t, Consumer<T> consumer) {
		consumer.accept(t);
	}
}
3.4 无参数有返回值Lambda
生产者方法接口,什么都不要,返回的全是输出!!!
package com.qfedu.c_lambda;

interface Supplier<T> {
	T get();
}

public class Demo3 {
	public static void main(String[] args) {
		String str = "<<稻香>> 周杰伦";
		
		// 方法中使用的Lambda表达式是可以在当前大括号范围以内使用对应的局部变量!!!
		String reverse = testLambda(str, () -> new StringBuilder(str).reverse().toString());
		System.out.println(reverse);
		
		int[] arr = {1, 3, 5, 7, 29, 2, 4, 6, 8, 20};
		int maxIndex = testLambda2(arr, () -> {
			int index = 0;
			for (int i = 1; i < arr.length; i++) {
				if (arr[index] < arr[i]) {
					index = i;
				}
			}
			
			return index;
		});
		System.out.println(maxIndex);
	}
	
	public static <T> T testLambda(T t, Supplier<T> supplier) {
		return supplier.get();
	}
	
	// Max value index in current int Array; 
	public static int testLambda2(int[] arr, Supplier<Integer> supplier) {
		return supplier.get();
	}
}
3.5 有参数有返回值Lambda
对应的方法都是有脸有面!!!
非常nice的方法!!!

Comparator<T>
	int compare(T o1, T o2);
	Arrays.sort(T[] arr, Comparator<T> compare)

Function<T, R> 转换!!!
	R apply(T t);
package com.qfedu.c_lambda;

import java.util.Arrays;

interface Function<T, R> {
	R apply(T t);
}

public class Demo4 {	
	public static void main(String[] args) {
		Student[] allStus = new Student[10];
		
		for (int i = 0; i < allStus.length; i++) {
			int id = i + 1;
			String name = "苟磊" + (i + 1);
			int age = (int) (Math.random() * 17);
			char gender = '男';
			
			allStus[i] = new Student(id, name, age, gender);
		}
		
		/*
		 * Arrays.sort(allStus, new Comparator<Student>() {
		 * 
		 * @Override public int compare(Student o1, Student o2) { // TODO Auto-generated
		 * method stub return o1.getAge() - o2.getAge(); } });
		 */
		Arrays.sort(allStus, (stu1, stu2) -> stu1.getAge() - stu2.getAge());
		
		for (Student student : allStus) {
			System.out.println(student);
		}
		
		System.out.println();
		// 字符串转Student对象
		String str = "11,苟帅,99,X";
		Student transform = transform(str, Student.class, (info) -> {
			String[] split = info.split(",");
			int id = Integer.valueOf(split[0]);
			String name = split[1];
			int age = Integer.valueOf(split[2]);
			char gender = split[3].charAt(0);
			
			
			return new Student(id, name, age, gender);
		});
		System.out.println(transform);
	}
	
	public static <T, R> R transform(T t, Class<R> cls, Function<T, R> fun) {
		return fun.apply(t);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值