什么是Stream?
也叫Stream流,是JDK8开始新增的一套API(java.util.Stream*),可以用于操作集合或者数组的数据
public class Test03 {
public static void main(String[] args) {
//1;创建list集合
ArrayList list1 = new ArrayList<>();
ArrayList list2 = new ArrayList<>();
Collections.addAll(list1, "aa", "bbb", "cc", "java", "dd", "a", "bab", "abc");
Collections.addAll(list2, "aaa", "bbb", "ddd");
//2:合并流,去重,按字符串长度降序排序
Stream.concat(list1.stream(), list2.stream())
.distinct().sorted((s1, s2) -> s2.length() - s1.length()).forEach(s -> System.out.println(s));
//用逗号链接的字符串
String s = "11,22,5,1,88,33,6";
//切分,转流,转int,求最大值
//int max = Arrays.stream(s.split(",")).mapToInt(i -> Integer.parseInt(i)).max().getAsInt();
//System.out.println(max);
int integer = Arrays.stream(s.split(",")).map(i -> Integer.parseInt(i)).max((s1, s2) -> s1 - s2).get();
System.out.println(integer);
}
}
java
bbb
bab
abc
aaa
ddd
aa
cc
dd
a
88
Process finished with exit code 0
package com.demo05_Stream;
import javax.swing.*;
import java.util.*;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/*
*
* 练习获取流对象的三种方式
* 1:直接利用Collection接口的的默认方法stream获取流的对象
* 2:直接利用Arrays的静态方法stream,传递数组获取流对象
* 3:直接利用Stream接口的静态方法of,传递可变参数,获取流对象
* */
public class Tes01 {
public static void main(String[] args) {
//1:创建ArrayList集合,存字符串数据
ArrayList list = new ArrayList<>();
Collections.addAll(list, "aa", "bbb", "cc", "java", "dd");
//2:获取流对象
Stream stream = list.stream();
System.out.println(stream.count());
//3:获取数组的流对象 专门针对数组获取流对象
Integer[] arr = {1,3,5};
Stream stream1 = Arrays.stream(arr);
System.out.println(stream1);
//4:零散的数据
Stream stream2 = Stream.of(2, 5, 8, 3, 6, 9);
System.out.println(stream2.count());
int[] arr2 = {1,4,7};
//不要使用of方法,传递数组,否则,会将整个数组当成一个元素处理
Stream arr21 = Stream.of(arr2);
IntStream arr22 = Arrays.stream(arr2);
System.out.println(arr21.count());
System.out.println(arr22.count());
//map集合无法直接获取流对象,但是可以间接获取
HashMap map = new HashMap<>();
map.put("aa", "11");
Stream> stream3 = map.entrySet().stream();
System.out.println(stream3.count());
}
}
5
java.util.stream.ReferencePipeline$Head@b4c966a
6
1
3
1
Process finished with exit code 0
package com.demo05_Stream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
/*
* 练习流中的常见 中间方法(延迟方法);
* 特点:
* 调用这些方法之后,会返回一个新的流对象,可以使用链式编程;
*
* */
public class Test02 {
public static void main(String[] args) {
//1:创建list集合
ArrayList list = new ArrayList<>();
Collections.addAll(list,"aa", "bbb", "cc", "java", "dd","a","bab","abc");
//2:过滤,无需自己遍历集合,只需要写如何赛选元素即可;(只负责写过滤规则)
//包含a的数据
//此时lambda的s表示的是 集合中的每一个元素
list.stream().filter(s -> s.contains("a")).
distinct().sorted().skip(1).limit(8).forEach(s ->System.out.println(s));
//distinct去除流中重复元素
//sorted对元素进行升序排序
//skip跳过前几个元素
//limit获取前几个元素
}
}
aa
abc
bab
java
Process finished with exit code 0
package com.streamdemo;
import java.util.ArrayList;
import java.util.List;
/**
* 体验Stream流
*
* 创建一个集合,存储多个字符串元素
* "张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"
*
* 把集合中所有以"张"开头的元素存储到一个新的集合
*
*
* 把"张"开头的集合中的长度为3的元素存储到一个新的集合
* 遍历上一步得到的集合
*
*/
public class MyStream1 {
public static void main(String[] args) {
//集合的批量添加
ArrayList list1 = new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));
//list.add()
//遍历list1把以张开头的元素添加到list2中。
ArrayList list2 = new ArrayList<>();
for (String s : list1) {
if(s.startsWith("张")){
list2.add(s);
}
}
//遍历list2集合,把其中长度为3的元素,再添加到list3中。
ArrayList list3 = new ArrayList<>();
for (String s : list2) {
if(s.length() == 3){
list3.add(s);
}
}
for (String s : list3) {
System.out.println(s);
}
System.out.println("=======================");
//Stream流
list1.stream().filter(s->s.startsWith("张"))
.filter(s->s.length() == 3)
.forEach(s-> System.out.println(s));
}
}
张三丰
张无忌
张翠山
=======================
张三丰
张无忌
张翠山
Process finished with exit code 0
一、list集合:
private static void method1() {
ArrayList list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
// Stream stream = list.stream();
// stream.forEach(s-> System.out.println(s));
list.stream().forEach(s-> System.out.println(s));
}
}
二、HashMap集合:
private static void method2() {
HashMap hm = new HashMap<>();
hm.put("zhangsan",23);
hm.put("lisi",24);
hm.put("wangwu",25);
hm.put("zhaoliu",26);
hm.put("qianqi",27);
//双列集合不能直接获取Stream流
//keySet
//先获取到所有的键
//再把这个Set集合中所有的键放到Stream流中
//hm.keySet().stream().forEach(s-> System.out.println(s));
//entrySet
//先获取到所有的键值对对象
//再把这个Set集合中所有的键值对对象放到Stream流中
hm.entrySet().stream().forEach(s-> System.out.println(s));
}
lisi=24
qianqi=27
zhaoliu=26
zhangsan=23
wangwu=25
Process finished with exit code 0
private static void method2() {
HashMap hm = new HashMap<>();
hm.put("zhangsan",23);
hm.put("lisi",24);
hm.put("wangwu",25);
hm.put("zhaoliu",26);
hm.put("qianqi",27);
//双列集合不能直接获取Stream流
//keySet
//先获取到所有的键
//再把这个Set集合中所有的键放到Stream流中
hm.keySet().stream().forEach(s-> System.out.println(s));
//entrySet
//先获取到所有的键值对对象
//再把这个Set集合中所有的键值对对象放到Stream流中
//hm.entrySet().stream().forEach(s-> System.out.println(s));
}
private static void method1() {
ArrayList list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
lisi
qianqi
zhaoliu
zhangsan
wangwu
Process finished with exit code 0
private static void method3() {
int [] arr = {1,2,3,4,5};
Arrays.stream(arr).forEach(s-> System.out.println(s));
}
1
2
3
4
5
Process finished with exit code 0
四、同种数据类型的多个数据:
private static void method4() {
Stream.of(1,2,3,4,5,6,7,8).forEach(s-> System.out.println(s));
}
1
2
3
4
5
6
7
8
Process finished with exit code 0
package com.streamdemo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.stream.Stream;
/**
* Stream流的获取
单列集合 : 集合对象.stream();
双列集合 : 不能直接获取,需要间接获取
集合对象.keySet().stream();
集合对象.entrySet().stream();
数组 :
Arrays.stream(数组名);
同种数据类型的多个数据:
Stream.of(数据1,数据2,数据3......);
*/
public class MyStream2 {
package com.streamdemo;
import java.util.ArrayList;
/**
* Stream流的中间方法
*/
public class MyStream3 {
public static void main(String[] args) {
// Stream filter(Predicate predicate):过滤
// Predicate接口中的方法 boolean test(T t):对给定的参数进行判断,返回一个布尔值
ArrayList list = new ArrayList<>();
list.add("张三丰");
list.add("张无忌");
list.add("张翠山");
list.add("王二麻子");
list.add("张良");
list.add("谢广坤");
//filter方法获取流中的 每一个数据.
//而test方法中的s,就依次表示流中的每一个数据.
//我们只要在test方法中对s进行判断就可以了.
//如果判断的结果为true,则当前的数据留下
//如果判断的结果为false,则当前数据就不要.
// list.stream().filter(
// new Predicate() {
// @Override
// public boolean test(String s) {
// boolean result = s.startsWith("张");
// return result;
// }
// }
// ).forEach(s-> System.out.println(s));
//因为Predicate接口中只有一个抽象方法test
//所以我们可以使用lambda表达式来简化
// list.stream().filter(
// (String s)->{
// boolean result = s.startsWith("张");
// return result;
// }
// ).forEach(s-> System.out.println(s));
list.stream().filter(s ->s.startsWith("张")).forEach(s-> System.out.println(s));
}
}
张三丰
张无忌
张翠山
张良
Process finished with exit code 0
filter方法:
package com.Teacher.demo02_Stream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
public class MyStream2 {
public static void main(String[] args) {
// 当使用流对象调用方法大的时候,建议使用链式编程
// 因为每个状态的流对象只能使用1次;
Map map = new HashMap<>();
map.put(1,"a");
map.put(2,"b");
map.put(3,"c");
map.put(4,"d");
// 获取流对象
Set> set = map.entrySet();
Stream> s1 = set.stream();
// 过滤出key大于1的数据
Stream> s2 = s1.filter(s -> {
// s表示的就是每一个键值对对象
return s.getKey() > 1;
});
/*
// 由于s1状态的流对象,在上面已经调用过一次方法了,不能再次调用方法了,如果需要继续过滤数据
应该使用s1对象过滤之后得出的新的流对象继续调用方法才是正确的;
s1.filter(s->{
// s表示的就是每一个键值对对象
return s.getKey()%2==0;
});
*/
s2.filter(s->{
// s表示的就是每一个键值对对象
return s.getKey()%2==0;
}).forEach(s-> System.out.println(s.getKey()+","+s.getValue()));
}
}
2,b
4,d
Process finished with exit code 0
package com.streamdemo;
import java.util.ArrayList;
import java.util.stream.Stream;
/**
* Stream流的中间方法
*/
public class MyStream4 {
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
list.add("张三丰");
list.add("张无忌");
list.add("张翠山");
list.add("王二麻子");
list.add("张良");
list.add("谢广坤");
list.add("谢广坤");
list.add("谢广坤");
list.add("谢广坤");
list.add("谢广坤");
//method1(list);
//method2(list);
//method3();
//method4(list);
}
private static void method4(ArrayList list) {
// Stream distinct():去除流中重复的元素。依赖(hashCode和equals方法)
list.stream().distinct().forEach(s-> System.out.println(s));
}
private static void method3() {
//static Stream concat(Stream a, Stream b):合并a和b两个流为一个流
ArrayList list = new ArrayList<>();
list.add("张三丰");
list.add("张无忌");
list.add("张翠山");
list.add("王二麻子");
list.add("张良");
list.add("谢广坤");
list.add("谢广坤");
list.add("谢广坤");
list.add("谢广坤");
list.add("谢广坤");
ArrayList list2 = new ArrayList<>();
list2.add("张三丰");
list2.add("张无忌");
list2.add("张翠山");
list2.add("王二麻子");
list2.add("张良");
list2.add("谢广坤");
// Stream stream1 = list.stream();
// Stream stream2 = list2.stream();
//
// Stream stream3 = Stream.concat(stream1, stream2);
// stream3.forEach(s -> System.out.println(s));
Stream.concat(list.stream(),list2.stream()).forEach(s-> System.out.println(s));
}
private static void method2(ArrayList list) {
// Stream skip(long n):跳过指定参数个数的数据
list.stream().skip(2).forEach(s-> System.out.println(s));
}
private static void method1(ArrayList list) {
// Stream limit(long maxSize):截取指定参数个数的数据
list.stream().limit(2).forEach(s-> System.out.println(s));
}
}
package com.streamdemo;
import java.util.ArrayList;
import java.util.function.Consumer;
/**
* Stream流的终结方法
*/
public class MyStream5 {
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
list.add("张三丰");
list.add("张无忌");
list.add("张翠山");
list.add("王二麻子");
list.add("张良");
list.add("谢广坤");
//method1(list);
// long count():返回此流中的元素数
long count = list.stream().count();
System.out.println(count);
}
private static void method1(ArrayList list) {
// void forEach(Consumer action):对此流的每个元素执行操作
// Consumer接口中的方法 void accept(T t):对给定的参数执行此操作
//在forEach方法的底层,会循环获取到流中的每一个数据.
//并循环调用accept方法,并把每一个数据传递给accept方法
//s就依次表示了流中的每一个数据.
//所以,我们只要在accept方法中,写上处理的业务逻辑就可以了.
list.stream().forEach(
new Consumer() {
@Override
public void accept(String s) {
System.out.println(s);
}
}
);
System.out.println("====================");
//lambda表达式的简化格式
//是因为Consumer接口中,只有一个accept方法
list.stream().forEach(
(String s)->{
System.out.println(s);
}
);
System.out.println("====================");
//lambda表达式还是可以进一步简化的.
list.stream().forEach(s->System.out.println(s));
}
}
package com.streamdemo;
import java.util.ArrayList;
import java.util.List;
/**
* Stream流的收集方法
* 练习:
* 定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10
* 将集合中的奇数删除,只保留偶数。
* 遍历集合得到2,4,6,8,10。
*/
public class MyStream6 {
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list.add(i);
}
// list.stream().filter(
// (Integer i)->{
// return i % 2 == 0;
// }
// )
list.stream().filter(number -> number % 2 == 0).forEach(number -> System.out.println(number));
System.out.println("====================");
for (Integer integer : list) {
System.out.println(integer);
}
}
}
2
4
6
8
10
====================
1
2
3
4
5
6
7
8
9
10
Process finished with exit code 0
package com.streamdemo;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Stream流的收集方法
* 练习:
* 定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10
* 将集合中的奇数删除,只保留偶数。
* 遍历集合得到2,4,6,8,10。
*/
public class MyStream7 {
public static void main(String[] args) {
ArrayList list1 = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list1.add(i);
}
list1.add(10);
list1.add(10);
list1.add(10);
list1.add(10);
list1.add(10);
//filter负责过滤数据的.
//collect负责收集数据.
//获取流中剩余的数据,但是他不负责创建容器,也不负责把数据添加到容器中.
//Collectors.toList() : 在底层会创建一个List集合.并把所有的数据添加到List集合中.
List list = list1.stream().filter(number -> number % 2 == 0)
.collect(Collectors.toList());//toList
System.out.println(list);
Set set = list1.stream().filter(number -> number % 2 == 0)
.collect(Collectors.toSet());//toSet 去重
System.out.println(set);
}
}
[2, 4, 6, 8, 10, 10, 10, 10, 10, 10]
[2, 4, 6, 8, 10]
Process finished with exit code 0
案例一:
/*
* 练习收集流中的数据
* 收集数据永远使用 Collect(收集器对象)
* Collections.toList();
* CollecTions.toSet();
* CollecTions.toMap(两个lambda需要告诉这个方法,如何将流中的一个数据作为key和value);
* */
public class MyStream02 {
public static void main(String[] args) {
//1:将一些字符串转成流对象
Stream stream = Stream.of("11","7","33","55","22","88","22","88","66");
//2:去重,转int,找偶数,收集到list集合中
List list = stream.distinct().map(s -> Integer.parseInt(s)).filter(s -> s % 2 == 0).collect(Collectors.toList());
System.out.println(list);
//将list中的数据转成流,收集map集合中,食用原始数字作为map的key,数字放大10倍,作为map的value
Map map = list.stream().collect(Collectors.toMap(s -> s, s -> s * 10));
System.out.println(map);
//将字符串转成流,将数据收集到map集合,使用字母作为map的key,汉字作为map的value
Stream stringStream = Stream.of("a.你好","b.我好","c.大家好");
Map map1 = stringStream.collect(Collectors.toMap(s -> s.split("\\.")[0], s -> s.split("\\.")[1]));
System.out.println(map1);
}
}
案例二:
/*
* 练习将流中的数据收集到容器中
* toArray()收集到数组中
* collector(收集器);收集器是什么,最终就返回什么
* 收集器的获取方式:
* Collectors 工具类静态方法:
* toSet():
* toList();
* toMap(两个Function);
* */
public class Test05 {
public static void main(String[] args) {
//收集到list
List list = Stream.of(3, 5, 7, 8, 9, 3, 5, 7, 2).distinct().sorted().collect(Collectors.toList());
System.out.println(list);
//收集到set
Set set = Stream.of(3, 5, 7, 8, 9, 3, 5, 7, 2).distinct().sorted().collect(Collectors.toSet());
System.out.println(set);
//收集到数组
Object[] array = Stream.of(3, 5, 7, 8, 9, 3, 5, 7, 2).distinct().sorted().toArray();
System.out.println(Arrays.toString(array));
//收集到map 我们需要自己指定如何将流中的每一个数据,转成key和valve
Map map = Stream.of(3, 5, 7, 8, 9, 3, 5, 7, 2).distinct().sorted().collect(Collectors.toMap(s -> s, s -> 10 * s));
System.out.println(map);
}
}
查看API学习其他的
package com.streamdemo;
public class Actor {
private String name;
public Actor() {
}
public Actor(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Actor{" +
"name='" + name + '\'' +
'}';
}
}
package com.streamdemo;
import java.util.ArrayList;
import java.util.stream.Stream;
/**
* 现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作
* 1.男演员只要名字为3个字的前两人
* 2.女演员只要姓杨的,并且不要第一个
* 3.把过滤后的男演员姓名和女演员姓名合并到一起
* 4.把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
* 演员类Actor,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法
*/
public class MyStream9 {
public static void main(String[] args) {
ArrayList manList = new ArrayList<>();
manList.add("张国立");
manList.add("张晋");
manList.add("刘烨");
manList.add("郑伊健");
manList.add("徐峥");
manList.add("王宝强");
ArrayList womanList = new ArrayList<>();
womanList.add("郑爽");
womanList.add("杨紫");
womanList.add("关晓彤");
womanList.add("张天爱");
womanList.add("杨幂");
womanList.add("赵丽颖");
//男演员只要名字为3个字的前两人
Stream stream1 = manList.stream().filter(name -> name.length() == 3).limit(2);
//女演员只要姓杨的,并且不要第一个
Stream stream2 = womanList.stream().filter(name -> name.startsWith("杨")).skip(1);
Stream.concat(stream1,stream2).forEach(name -> {
Actor actor = new Actor(name);
System.out.println(actor);
});
}
}
//将两个流中的数据合并后,将流中的数据从String类型,转成Actor类型
/*Stream.concat(stream1,stream2).forEach(name -> {
Actor actor = new Actor(name);
System.out.println(actor);
});*/
//将两个流中的数据合并后,将流中的数据从String类型,转成Actor类型
// list收集collect
//List list = Stream.concat(stream1, stream2).map(s -> new Actor(s)).collect(Collectors.toList());//这是收集
//若不想收集forEach
Stream.concat(stream1, stream2).map(s -> new Actor(s)).forEach(s -> System.out.println(s));
Actor{name='张国立'}
Actor{name='郑伊健'}
Actor{name='杨幂'}
Process finished with exit code 0
public class Test01 {
public static void main(String[] args) {
//绝对路径,创建文件夹对象 从盘符开始的路径
File f1 = new File("D:\\IdeaProjects\\object");
System.out.println(f1);
System.out.println(f1.exists());
//相对路径,默认相对于项目路径 可以在idea中进行修改,不建议!
File f2 = new File("aaa");
System.out.println(f2);
System.out.println(f2.exists());
File f3 = new File(f1,"aaa");
System.out.println(f3);
System.out.println(f3.exists());
}
}
D:\IdeaProjects\object
true
aaa
false
D:\IdeaProjects\object\aaa
false
Process finished with exit code 0
package com.Demo06_File;
import java.io.File;
public class Test02 {
public static void main(String[] args) {
//使用相对路径,创建两个文件对象
File f1 = new File("1.txt");
File f2 = new File("day08/1.txt");
System.out.println(f1.exists());
System.out.println(f2.exists());
//判断是文件还是文件夹
//当f1对象的exists方法是false的时候,下面的两个方法也都是false
System.out.println(f1.isFile());//记着isFile.判断当前文件对象指代的是否是文件,是文件返回true
System.out.println(f1.isDirectory());
System.out.println("f2="+f2.isFile());
System.out.println("f2="+f2.isDirectory());
System.out.println("f2的名称="+f2.getName());//记着.获取文件的名称
System.out.println(f2.length());
File f3 = new File("D:\\IdeaProjects\\object");
//length方法,针对文件有效,对文件夹不准
System.out.println(f3.length());
//获取f2的绝对路径
System.out.println(f2.getAbsolutePath()); //记着.获取绝对路径
System.out.println(f2.getParent());
}
}
false
false
false
false
f2=false
f2=false
f2的名称=1.txt
0
4096
D:\IdeaProjects\object\day08\1.txt
day08
Process finished with exit code 0
private static void method1() {
//File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
String path = "E:\\wenjian\\a.txt";
File file = new File(path);
//问题:为什么要把字符串表示形式的路径变成File对象?
//就是为了使用File类里面的方法.
}
private static void method2() {
//File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的File实例
String path1 = "E:\\wenjian";
String path2 = "a.txt";
File file = new File(path1,path2);//把两个路径拼接.
System.out.println(file);//C:\itheima\a.txt
}
--------------------------------------------
打印结果:
E:\wenjian\a.txt
Process finished with exit code 0
private static void method3() {
//File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的File实例
File file1 = new File("E:\\wenjian");
String path = "a.txt";
File file = new File(file1,path);
System.out.println(file);//C:\itheima\a.txt
}
----------------------------------------
控制台打印结果:
E:\wenjian\a.txt
Process finished with exit code 0
package com.filemodule.filedemo;
import java.io.File;
public class FileDemo2 {
public static void main(String[] args) {
//这个路径固定不变了.
File file = new File("D:\\it\\a.txt");
//当前项目下的a.txt
File file2 = new File("a.txt");
//当前项目下 --- 指定模块下的 a.txt
File file3 = new File("filemodule\\a.txt");
}
}
//public boolean createNewFile() 创建一个新的空的文件
//注意点:
//1.如果文件存在,那么创建失败,返回false
//2.如果文件不存在,那么创建成功,返回true
//3.createNewFile方法不管调用者有没有后缀名,只能创建文件.
private static void method1() throws IOException {
File file1 = new File("C:\\it\\aaa");
boolean result1 = file1.createNewFile();
System.out.println(result1);
}
//public boolean mkdir() 创建一个单级文件夹
//注意点:
//1.只能创建单级文件夹,不能创建多级文件夹
//2.不管调用者有没有后缀名,只能创建单级文件夹
private static void method2() {
File file = new File("C:\\it\\aaa.txt");
boolean result = file.mkdir();
System.out.println(result);
}
//public boolean mkdirs() 创建一个多级文件夹
//注意点:
//1,可以创建单级文件夹,也可以创建多级文件夹
//2.不管调用者有没有后缀名,只能创建文件夹
//疑问:
//既然mkdirs能创建单级,也能创建多级.那么mkdir还有什么用啊? 是的
File file = new File("C:\\it\\aaa.txt");
boolean result = file.mkdirs();
System.out.println(result);
import java.io.File;
public class FileDemo4 {
//注意点:
//1.不走回收站的.
//2.如果删除的是文件,那么直接删除.如果删除的是文件夹,那么能删除空文件夹
//3.如果要删除一个有内容的文件夹,只能先进入到这个文件夹,把里面的内容全部删除完毕,才能再次删除这个文件夹
//简单来说:
//只能删除文件和空文件夹.
public static void main(String[] args) {
//method1();
File file = new File("C:\\it");
boolean result = file.delete();
System.out.println(result);
}
private static void method1() {
File file = new File("C:\\it\\a.txt");
boolean result = file.delete();
System.out.println(result);
}
}
判断功能
方法名 | 说明 |
---|---|
public boolean isDirectory() | 测试此抽象路径名表示的File是否为目录 |
public boolean isFile() | 测试此抽象路径名表示的File是否为文件 |
public boolean exists() | 测试此抽象路径名表示的File是否存在 |
获取功能
方法名 | 说明 |
---|---|
public String getAbsolutePath() | 返回此抽象路径名的绝对路径名字符串 |
public String getPath() | 将此抽象路径名转换为路径名字符串 |
public String getName() | 返回由此抽象路径名表示的文件或目录的名称 |
public File[] listFiles() | 返回此抽象路径名表示的目录中的文件和目录的File对象数组 |
private static void method1() {
File file = new File("C:\\it\\a.txt");
//public boolean isFile() 测试此抽象路径名表示的File是否为文件
boolean result1 = file.isFile();
//public boolean isDirectory() 测试此抽象路径名表示的File是否为目录
boolean result2 = file.isDirectory();
System.out.println(result1);//true
System.out.println(result2);//false
}
private static void method2() {
File file = new File("C:\\it");
boolean result1 = file.isFile();//是否为文件
boolean result2 = file.isDirectory();//是否为目录
System.out.println(result1);//false
System.out.println(result2);//true
}
private static void method3() {
File file = new File("a.txt");
//public boolean exists() 测试此抽象路径名表示的File是否存在
boolean result = file.exists();//File是否存在
System.out.println(result);//false
}
private static void method4() { //注意点:
File file = new File("a.txt"); //1.如果调用者是文件,那么获取的是文件名和后缀名
//public String getName() 返回由此抽象路径名表示的文件或目录的名称
String name = file.getName();
System.out.println(name);
//注意点:
File file1 = new File("C:\\it");//2.如果调用者是一个文件夹,那么获取的是文件夹的名字
//public String getName() 返回由此抽象路径名表示的文件或目录的名称
String name2 = file1.getName();
System.out.println(name2);
}
package com.filemodule.filedemo;
import java.io.File;
public class FileDemo6 {
public static void main(String[] args) {
File file = new File("D:\\aaa");
File[] files = file.listFiles();//返回值是一个File类型的数组
System.out.println(files.length);
for (File path : files) {
System.out.println(path);
}
//进入文件夹,获取这个文件夹里面所有的文件和文件夹的File对象,并把这些File对象都放在一个数组中返回.
//包括隐藏文件和隐藏文件夹都可以获取.
//注意事项:
//1.当调用者是一个文件时
//2,当调用者是一个空文件夹时
//3.当调用者是一个有内容的文件夹时
//4.当调用者是一个有权限才能进入的文件夹时
}
}
package com.filemodule.filetest;
import java.io.File;
import java.io.IOException;
public class Test1 {
public static void main(String[] args) throws IOException {
//练习一:在当前模块下的aaa文件夹中创建一个a.txt文件
/* File file = new File("filemodule\\aaa\\a.txt");
file.createNewFile();*/
//注意点:文件所在的文件夹必须要存在.
File file = new File("filemodule\\aaa");
if(!file.exists()){
//如果文件夹不存在,就创建出来
file.mkdirs();
}
File newFile = new File(file,"a.txt");
newFile.createNewFile();
}
}
package com.filemodule.filetest;
import java.io.File;
public class Test2 {
public static void main(String[] args) {
//练习二:删除一个多级文件夹
//delete方法
//只能删除文件和空文件夹.
//如果现在要删除一个有内容的文件夹?
//先删掉这个文件夹里面所有的内容.
//最后再删除这个文件夹
File src = new File("C:\\Users\\apple\\Desktop\\src");
deleteDir(src);
}
private static void deleteDir(File src) {
//先删掉这个文件夹里面所有的内容.
//递归 方法在方法体中自己调用自己.
//注意: 可以解决所有文件夹和递归相结合的题目
//1.进入 --- 得到src文件夹里面所有内容的File对象.
File[] files = src.listFiles();
//2.遍历 --- 因为我想得到src文件夹里面每一个文件和文件夹的File对象.
for (File file : files) {
if(file.isFile()){
//3.判断 --- 如果遍历到的File对象是一个文件,那么直接删除
file.delete();
}else{
//4.判断
//递归
deleteDir(file);//参数一定要是src文件夹里面的文件夹File对象
}
}
//最后再删除这个文件夹
src.delete();
}
}
package com.filemodule.filetest;
import java.io.File;
import java.util.HashMap;
public class Test3 {
public static void main(String[] args) {
//统计一个文件夹中,每种文件出现的次数.
//统计 --- 定义一个变量用来统计. ---- 弊端:同时只能统计一种文件
//利用map集合进行数据统计,键 --- 文件后缀名 值 ---- 次数
File file = new File("filemodule");
HashMap hm = new HashMap<>();
getCount(hm, file);
System.out.println(hm);
}
private static void getCount(HashMap hm, File file) {
File[] files = file.listFiles();
for (File f : files) {
if(f.isFile()){
String fileName = f.getName();
String[] fileNameArr = fileName.split("\\.");
if(fileNameArr.length == 2){
String fileEndName = fileNameArr[1];
if(hm.containsKey(fileEndName)){
//已经存在
//将已经出现的次数获取出来
Integer count = hm.get(fileEndName);
//这种文件又出现了一次.
count++;
//把已经出现的次数给覆盖掉.
hm.put(fileEndName,count);
}else{
//不存在
//表示当前文件是第一次出现
hm.put(fileEndName,1);
}
}
}else{
getCount(hm,f);
}
}
}
}
09
简述Stream流的使用思想以及获取Stream流的常见方式?
答:
使用思想:
① 生成流: 通过数据源(集合,数组等)生成流
② 中间操作:一个流后面可以跟随零个或多个中间操作,其目的主要是打开流,做出某种程度的数据过滤/映射,然后返回一个新的流,交给下一个操作使用
③ 终结操作:一个流只能有一个终结操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作
获取Stream流的常见方式:
① Collection体系的集合可以直接调用Collection接口中的默认方法stream()去生成流
② Map体系的集合可以通过间接的方式去生成流,具体步骤如下所示:
1. 获取所有的键所对应的Set集合
2. 然后通过Set集合对象调用Stream方法生成流
③ 数组可以通过Stream接口的静态方法of方法生成流
如下程序
上述程序执行完毕以后,在控制台的输出结果如下所示:
请说明出现该错误的原因?
答:forEach方法是一个终结操作的方法,当执行了一次forEach方法以后,流中的元素就已经被用光了。
不能在执行forEach终结操作了。
运行如下程序观察控制台输出结果,说明产生该问题的主要原因?
// 创建一个List集合对象
List list = Arrays.asList("hello", "java8", "stream");
// 获取上述list集合所对应的流对象
list.stream().map(s -> {
list.add("world") ; // 向list集合中添加元素
return s.toUpperCase(); // 将流中的元素转换成大写
}).forEach( s -> System.out.println(s)); // 遍历流中的元素
答:
控制台会输出如下异常:Exception in thread "main" java.lang.UnsupportedOperationException
主要原因:在通过流处理数据的时候,对数据源进行了修改
package com.Teacher09.demo01_KeHouLianXi.ti0;
import java.util.Arrays;
import java.util.List;
public class Demo {
public static void main(String[] args) {
// 创建一个List集合对象
List list = Arrays.asList("hello", "java8", "stream");
// 获取上述list集合所对应的流对象
list.stream().map(s -> {
//list.add("world") ; // 向list集合中添加元素
return s.toUpperCase(); // 将流中的元素转换成大写 return什么,就会将流中的数据修改成什么
}).forEach(s -> System.out.println(s));
// System.out.println("------------------------");
//list.stream().forEach(s-> System.out.println(s));
}
}
请说明如下程序执行完毕以后的结果并说明原因?
答:
① 在io-day01项目目录下生成一个a.txt文件夹
② 在io-day01项目目录下创建it/xian文件夹失败,因为mkdir方法只能创建单级文件夹
③ 在io-day01项目中删除itcast文件夹失败,因为delete方法只能删除不带内容的文件夹
public class Demo {
public static void main(String[] args) {
File f = new File("a/b/c");
f.mkdirs();
System.out.println("-----");
}
}
如下程序是计算1-10之间的数据和,请说明如下程序执行完毕以后的结果并说明原因?如果想让程序进行正常执行,应该如何进行改造? (单纯的考递归)
答:
① 程序执行结果:在控制台会输出Exception in thread "main" java.lang.StackOverflowError异常信息。
原因:是递归调用没有指定出口
② 让程序正常执行,代码如下所示:答:
public class FileDemo02 {
public static void main(String[] args) {
// 调用calc方法计算1-10之间的数据之和
int result = calc(10);
System.out.println(result);
}
// 计算1-number之间的数据之和
public static int calc(int number) {
if(number == 1) {
return 1 ;
}else {
return number + calc(number - 1) ;
}
}
}
训练目标:掌握JDK1.8的新特性Stream流的基本使用,以及理解其在实际开发中的应用
需求背景:Microsoft Excel是Microsoft(微软)为使用Windows操作系统的电脑编写的一款电子表格软件。在实际的工作中,如果要处理的数据量较大,那么此时会由多个业务人员将要处理的数据
录入到excel中,那么在进行录入的时候可能就会产生数据重复录入。因此在录入完毕以后,往往需要进行数据查重和去重操作。
需求描述: 在素材的stream01项目的提供了两个excel文件(sku01.xlsx、sku02.xlsx),这两个excel文件存储的都是商品的数据,在这两个文件中存在一些重复性的数据。现需要在该项目的指定
位置补全相关的代码实现数据去重的操作,并且需要按照商品的价格进行降序排序。程序执行完毕以后可以将处理以后的结果数据存储到一个新的excel文件(sku.xlsx)中。新excel文件的内容如下
实现提示:
1、读取excel表格中的数据到List集合中代码已经实现
2、将一个List集合中的数据写入到一个excel文件中代码已经实现
3、在Entry类中指定位置补全相关代码
4、在Sku类中的指定位置补全代码
package com.Teacher09.demo01_KeHouLianXi.ti01.entry;
import com.Teacher09.demo01_KeHouLianXi.ti01.domain.Sku;
import com.Teacher09.demo01_KeHouLianXi.ti01.listener.SkuAnalysisEventListener;
import com.alibaba.excel.EasyExcel;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
//Stream$File
public class Entry {
public static void main(String[] args) {
// 创建一个ArrayList集合对象,来存储读取到的day10_day11_IO/excel/sku01.xlsx中的数据
List sku01 = new ArrayList();
// 创建一个ArrayList集合对象,来存储读取到的day10_day11_IO/excel/sku02.xlsx中的数据
List sku02 = new ArrayList();
// 读取数据
EasyExcel.read("day10_day11_IO/excel/sku01.xlsx" , Sku.class , new SkuAnalysisEventListener(sku01)).sheet(0).doRead();
EasyExcel.read("day10_day11_IO/excel/sku02.xlsx" , Sku.class , new SkuAnalysisEventListener(sku02)).sheet(0).doRead();
// 补全等号右边的代码
sku01.addAll(sku02) ;
List skus = sku01.stream().distinct().sorted((s1, s2) -> {//distinct 去重,sorted排序
int i = s2.getPrice() - s1.getPrice();// [主要条件] 降序 s2.getPrice() - s1.getPrice()
return i == 0 ? s2.getSn().compareTo(s1.getSn()) : i;// [次要条件]
}).collect(Collectors.toList());//收集collect
// 保存去重以后的数据到新的excel中
EasyExcel.write("day10_day11_IO/excel/sku.xlsx" , Sku.class).sheet("商品去重结果").doWrite(skus);
}
}
5、如果商品的条码是相同的则认为是同一条数据
去重:
public class Sku{
@ExcelProperty("商品条码")
private String sn ; // 商品条码
// 补全代码
@Override
public boolean equals(Object o) {
// 只要条码相同,我们就认为是的同一个数据
if(!(o instanceof Sku)){ //判断类型
return false;
}
Sku s = (Sku) o; //强转
return sn.equals(s.sn);
}
@Override
public int hashCode() {
// 根据条码生成一个哈希值,.如果两个商品的条码相同,就让他们生成相同的哈希值;
return sn.hashCode();
}
}
代码实现:见《答案/代码/stream01》
训练目标:掌握JDK1.8的新特性Stream流的基本使用,以及理解其在实际开发中的应用
需求背景:在完成数据查询功能的时候,如果查询到的满足条件的数据量比较大,为了减少系统内存的消耗。那么此时就需要使用分页查询。分页查询就是一次查询一部分的数据进行返回。比如
京东商城的搜索功能实现的时候使用的就是分页查询。如下所示:
默认查询的是第一页的数据,当点击对应的页码的时候就会查询指定页码的这一部分的数据。分页查询需要已知两个参数:页码,每页查询的数据条数。通过这两个数据就可以计算出要查询的数据
的开始行号。进而就可以实现分页查询。
需求描述:将编程题目一中处理完毕的以后的数据集合中的第3页数据写入到新的excel中。在素材的stream02项目的指定位置补全相关代码,新的excel文件的内容如下所示
实现提示:
1、读取excel表格中的数据到List集合中代码已经实现
2、将一个List集合中的数据写入到一个excel文件中代码已经实现
3、在Entry类中指定位置补全相关代码
4、在Sku类中的指定位置补全代码
5、如果商品的条码是相同的则认为是同一条数据
6、考虑使用stream流中的skip方法和limit方法(每页查询10条数据)
代码实现:见《答案/代码/stream02》
package com.Teacher09.demo01_KeHouLianXi.ti02.entry;
import com.Teacher09.demo01_KeHouLianXi.ti02.domain.Sku;
import com.Teacher09.demo01_KeHouLianXi.ti02.listener.SkuAnalysisEventListener;
import com.alibaba.excel.EasyExcel;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Entry {
public static void main(String[] args) {
// 创建一个ArrayList集合对象,来存储读取到的excel/sku01.xlxs中的数据
List sku01 = new ArrayList();
// 创建一个ArrayList集合对象,来存储读取到的excel/sku02.xlxs中的数据
List sku02 = new ArrayList();
// 读取数据
EasyExcel.read("day10_day11_IO/excel/sku01.xlsx" , Sku.class , new SkuAnalysisEventListener(sku01)).sheet(0).doRead();
EasyExcel.read("day10_day11_IO/excel/sku02.xlsx" , Sku.class , new SkuAnalysisEventListener(sku02)).sheet(0).doRead();
int pn = 3;
int psize = 6;
// 补全等号右边的代码
sku01.addAll(sku02) ;
List skus = sku01.stream().distinct().sorted((s1, s2) -> {
int i = s2.getPrice() - s1.getPrice();// 主要条件
return i == 0 ? s2.getSn().compareTo(s1.getSn()) : i;// 次要条件
}).skip((pn-1)*psize).limit(psize).collect(Collectors.toList());//skip,limit截取
// 保存去重以后的数据到新的excel中
EasyExcel.write("day10_day11_IO/excel/sku.xlsx" , Sku.class).sheet("商品去重结果").doWrite(skus);
}
}
package com.ioproject.bytestream.output;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputDemo1 {
public static void main(String[] args) throws IOException {
//1.创建字节输出流的对象 --- 告诉虚拟机我要往哪个文件中写数据了
FileOutputStream fos = new FileOutputStream("D:\\a.txt");//1
//FileOutputStream fos = new FileOutputStream(new File("D:\\a.txt"));//2
//注意:1.如果文件不存在,会帮我们创建
//2.如果文件存在,会把文件清空
//2,写数据
fos.write(97);
//3,释放资源
fos.close();
}
}
package com.ioproject.bytestream.output;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputDemo3 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("day10_IO\\a.txt");
fos.write(97);
fos.write(98);
fos.write(99);
fos.close();
}
}
public class OutputDemo4 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("day10_IO\\a.txt");
/*byte [] bys = {97,98,99};
fos.write(bys);*/
byte [] bys = {97,98,99,100,101,102,103};
fos.write(bys,1,2);
fos.close();
}
}
package com.ioproject.bytestream.output;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputDemo5 {
public static void main(String[] args) throws IOException {
//第二个参数就是续写开关,如果没有传递,默认就是false,
//表示不打开续写功能,那么创建对象的这行代码会清空文件.
//如果第二个参数为true,表示打开续写功能
//那么创建对象的这行代码不会清空文件.
FileOutputStream fos = new FileOutputStream("day10_IO\\a.txt",true);
fos.write(97);
//能加一个换行
fos.write("\r\n".getBytes());
fos.write(98);
//能加一个换行
fos.write("\r\n".getBytes());
fos.write(99);
//能加一个换行
fos.write("\r\n".getBytes());
fos.write(100);
//能加一个换行
fos.write("\r\n".getBytes());
fos.write(101);
//能加一个换行
fos.write("\r\n".getBytes());
fos.close();
}
}
package com.ioproject.bytestream.output;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputDemo6 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
//System.out.println(2/0);
fos = new FileOutputStream("E:\\a.txt");
fos.write(97);
}catch(IOException e){
e.printStackTrace();
}finally {
//finally语句里面的代码,一定会被执行.
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字节流读数据 :
package com.ioproject.bytestream.output;
import java.io.FileInputStream;
import java.io.IOException;
public class OutputDemo7 {
public static void main(String[] args) throws IOException {
//如果文件[存在],那么就不会报错.
//如果文件[不存在],那么就直接报错.
FileInputStream fis = new FileInputStream("day10_IO\\a.txt");
int read = fis.read();//读 read
//一次读取一个[字节],返回值就是本次读到的那个[字节数据].
//也就是字符在[码表]中对应的那个数字.
//如果我们想要看到的是[字符数据],那么一定要强转成[char]
System.out.println((char)read);
//释放资源
fis.close();
}
}
多个数据读取:
package com.ioproject.bytestream.output;
import java.io.FileInputStream;
import java.io.IOException;
public class OutputDemo8 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("day10_IO\\a.txt");
//1,文件中多个字节我怎么办?
/*while(true){
int i1 = fis.read();
System.out.println(i1);
}*/
int b;
while ((b = fis.read())!=-1){
System.out.print((char) b);
}
fis.close();
}
}
字节输入流
FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名
字节输入流读取数据的步骤
创建字节输入流对象
调用字节输入流对象的读数据方法
释放资源
读数据对应的方法
read() 不带参数,返回的是本次读取的数据的 码值 ,如果读取到末尾则返回-1;
read(字节数组) 返回的是本次读取的数据的 个数(数据都保存到了字节数组中) ,如果读取到末尾则返回-1;
package com.Teacher.demo04_ByteIn;
import java.io.FileInputStream;
import java.util.Arrays;
/*
使用字节数组,配合循环,读数据
*/
public class MyInput {
public static void main(String[] args) throws Exception {
// 1: 创建字节输入流对象
FileInputStream fin = new FileInputStream("day10_IO/a.txt");
//2: 准备一个长度为3的数组,准备读数据
byte[] arr = new byte[3];
// 3: 准备一个专门保存每次循环时,读取到的字节的个数
int len = 0;
// 4: 循环开始读
// fin.read(arr) 利用fin这个输入流,读数据,把读取到的数据存到数组arr\中
// read(arr) 方法返回的是 本次读取的个数,然后把个数赋值给 len变量
// 使用len变量保存的值与 -1 比较,如果不是-1,则说明读取有效,可以正常操作,反之说明读取到了末尾,可以结束循环了
int i = 1;
while ((len = fin.read(arr)) != -1) {
// 说明本次循环读取的个数是有效的,反之,如果len==-1,说明已经读取到末尾了,就可以结束循环了
// 如何把本次读取到的 len个有效数据,转成字符串呢?
System.out.println("第" + i + "次循环,len=" + len);
System.out.println("第" + i + "次循环,数组的内容是:=" + Arrays.toString(arr));
i++;
// 利用String类的构造方法,将 len个数据转成字符串
System.out.print(new String(arr, 0, len));
}
fin.close();
/*
while (true){
len=fin.read(arr);
if(len==-1){
break;
}
}*/
}
}
abcdgfe
第1次循环,len=3
第1次循环,数组的内容是:=[97, 98, 99]
abc第2次循环,len=3
第2次循环,数组的内容是:=[100, 103, 102]
dgf第3次循环,len=3
第3次循环,数组的内容是:=[101, 13, 10]
e
Process finished with exit code 0
package com.ioproject.bytestream.output;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputDemo9 {
public static void main(String[] args) throws IOException {
//创建了字节输入流,准备读数据.
FileInputStream fis = new FileInputStream("E:\\it\\aaa.avi");
//创建了字节输出流,准备写数据.
FileOutputStream fos = new FileOutputStream("day10_IO\\aaa.avi");
int b;
while((b = fis.read())!=-1){
fos.write(b);
}
fis.close();
fos.close();
}
}
package com.ioproject.bytestream.output;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputDemo10 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("E:\\it\\aaa.avi");
FileOutputStream fos = new FileOutputStream("day10_IO\\aaa.avi");
byte [] bytes = new byte[1024];//一般读8192
int len; //本次读到的有效字节个数 -- 这次读了几个字节.
while((len = fis.read(bytes))!=-1){//查看源码 Ctrl+n 找InputStream
fos.write(bytes,0,len);
}
fis.close();
fos.close();
}
}
用缓冲流一个字节一个字节的拷贝案例(如下):
package com.ioproject.bytestream.output;
import java.io.*;
public class OutputDemo11 {
public static void main(String[] args) throws IOException {
//就要利用缓冲流去拷贝文件
//创建一个字节缓冲输入流
//在底层创建了一个默认长度为8192的字节数组
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day10_IO\\a.avi"));
//创建一个字节缓冲输出流
//在底层创建了一个默认长度为8192的字节数组
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day10_IO\\copy.avi"));
int b;
while((b = bis.read()) != -1){
bos.write(b);
}
bis.close();
bos.close();
}
}
结合数组,进行文件拷贝(如下)
package com.ioproject.bytestream.output;
import java.io.*;
public class OutputDemo12 {
public static void main(String[] args) throws IOException {
//缓冲流结合数组,进行文件拷贝
//创建一个字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day10_IO\\a.avi"));
//创建一个字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day10_IO\\copy.avi"));
byte [] bytes = new byte[1024];
int len;
while((len = bis.read(bytes)) !=-1){
bos.write(bytes,0,len);
}
bis.close();
bos.close();
}
}
package com.charstream.charstream1;
import java.io.FileInputStream;
import java.io.IOException;
public class CharStreamDemo1 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("day10_IO\\a.txt");
int b ;
while((b = fis.read()) != -1){
System.out.println((char) b);
}
fis.close();
}
}
a.txt
abcdgfe 嘿嘿
abcdgfe å¿å¿
Process finished with exit code 0
private static void method1() throws UnsupportedEncodingException {
// byte[] getBytes():
//使用平台的默认字符集将该 String编码为一系列字节,将结果存储到新的字节数组中
// byte[] getBytes(String charsetName):
//使用指定的字符集将该 String编码为一系列字节,将结果存储到新的字节数组中
String s = "程序员";
//利用idea默认的UTF-8将中文编码为一系列的字节
byte[] bytes1 = s.getBytes();
System.out.println(Arrays.toString(bytes1));
//byte[] bytes2 = s.getBytes("UTF-8");
byte[] bytes2 = s.getBytes("GBK");
System.out.println(Arrays.toString(bytes2));
}
[-25, -88, -117, -27, -70, -113, -27, -111, -104]
[-77, -52, -48, -14, -44, -79]
Process finished with exit code 0
private static void method2() throws UnsupportedEncodingException {
byte [] bytes1 = {-25, -88, -117, -27, -70, -113, -27, -111, -104};
//gbk
byte [] bytes2 = {-77, -52, -48, -14, -44, -79};
//利用默认的UTF-8进行解码
String s1 = new String(bytes1);
System.out.println(s1);//程序员
//利用指定的GBK进行解码
String s2 = new String(bytes2,"gbk");
System.out.println(s2);//程序员
}
程序员
程序员
Process finished with exit code 0
package com.charstream.charstream1;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class CharStreamDemo2 {
public static void main(String[] args) throws UnsupportedEncodingException {
method1();
method2();
// String(byte[] bytes):
//通过使用平台的默认字符集解码指定的字节数组来构造新的 String
// String(byte[] bytes, String charsetName):
//通过指定的字符集解码指定的字节数组来构造新的 String
//UTF-8
}
请在D盘根目录下创建一个文件:test1.txt(随意录入一些内容),再创建一个目录:测试目录
要求:
获取、打印file1和file2的绝对路径;
获取、打印file1和file2的文件名和目录名;
获取、打印file1和file2的文件大小;
分别判断file1和file2是否存在;
分别判断file1和file2是否是文件?是否是目录?
效果:
参考代码:
public static void main(String[] args) {
File file1 = new File("D:\\test1.txt");
File file2 = new File("D:\\测试目录");
//1. 获取、打印file1和file2的绝对路径;
System.out.println("文件1的绝对路径是:"+file1.getAbsolutePath());
System.out.println("文件夹2的绝对路径是:"+file2.getAbsolutePath());
//2. 获取、打印file1和file2的文件名和目录名;
System.out.println("文件1的名称是:"+file1.getName());
System.out.println("文件夹2的名称是:"+file2.getName());
//3. 获取、打印file1和file2的文件大小;
System.out.println("文件1的大小是:"+file1.length());
System.out.println("文件夹2的大小是(文件夹获取的不准确):"+file2.length());
//4. 分别判断file1和file2是否存在;
System.out.println("file1表示的文件存在吗?"+file1.exists());
System.out.println("file2表示的文件夹存在吗?"+file2.exists());
//5. 分别判断file1和file2是否是文件?是否是目录?
System.out.println("file1表示的是文件吗?"+file1.isFile());
System.out.println("file2表示的是文件吗?"+file2.isFile());
}
package com.Teacher10.demo01_KeHouLianXi.A;
import java.io.File;
/*
求指定文件夹的大小
*/
public class ti1 {
private static long c = 0;
public static void main(String[] args) {
File f = new File("E:\\Daily software");
length(f);
System.out.println(c);
}
// 这个方法就是专门求指定文件夹大小的方法
public static void length(File f) {
// 1:获取该文件夹下的所有内容
File[] files = f.listFiles();
//2: 遍历
for (File file : files) {
//3: 判断, file是文件还是文件夹
if (file.isFile()) {
// 累加大小
c += file.length();
} else {
// 是文件夹,递归继续找它的内容
length(file);
}
}
}
}
6543235439
Process finished with exit code 0
请编写main()方法,创建以下File对象:
File file1 = new File(“test.txt”);//相对路径
File file2 = new File(“一级目录”);
File file3 = new File(“目录A/目录B/目录C”);
要求:
(相对路径,可以相对于项目也可以相对于模块)
判断file1是否存在?如果不存在,创建这个文件。
判断file2是否存在?如果不存在,创建这个目录。
判断file3是否存在?如果不存在,创建这个多级目录。
效果:
参考代码:
public static void main(String[] args) throws IOException {
File f1 = new File("test.txt");//相对路径,(我设置的是相对于模块的)
File f2 = new File("abc");
File f3 = new File("a\\b\\c");
//1. 判断f1是否存在?如果不存在,创建这个文件。
if (!f1.exists()) {
f1.createNewFile();
}
//2. 判断f2是否存在?如果不存在,创建这个目录。
if (!f2.exists()) {
f2.mkdirs();
}
//3. 判断file3是否存在?如果不存在,创建这个多级目录。
if (!f3.exists()) {
f3.mkdirs();
}
}
请在D盘下创建一个目录“多级目录”,下面随意创建一些文件和目录。
请编写main()方法,创建以下File对象:
File file = new File(“D:\多级目录”);
要求:
遍历这个多级文件夹下的所有内容(包含子文件夹的内容),判断每个File对象是否文件
如果是文件,打印:【文件】+ 绝对路径
如果是目录,打印:【目录】+ 绝对路径
效果
参考代码:
public static void main(String[] args) {
File file = new File("D:\\a");
//处理文件夹的方法
dir(file);
}
public static void dir(File file) {
File[] arr = file.listFiles();
for (File f : arr) {
if(f.isFile()){
System.out.println("文件:"+f.getAbsolutePath());
}else {
//说明f是文件夹,先打印,然后再递归处理
System.out.println("文件夹:"+f.getAbsolutePath());
dir(f);
}
}
}
使用键盘输入多个学生的信息,并将这些学生的信息保存到模块的1.txt文件中;
要求:
1:学生信息包含姓名、年龄(用一行字符串表示即可,无需创建学生对象);
2:每个学生信息占一行,学生信息之间使用逗号分隔;
3:至少输入3个学生信息;
效果
参考代码:
public static void main(String[] args) throws Exception {
//创建文件对象,准备写数据
FileOutputStream fout = new FileOutputStream("1.txt");
Scanner sc = new Scanner(System.in);
for (int i = 1; true; i++) {
System.out.println("请输入第"+i+"个学生姓名和年龄,学生信息之间使用逗号分隔(ok表示结束):");
String s = sc.next();
if("ok".equalsIgnoreCase(s)){
System.out.println("拜拜!");
break;
}
// \r\n表示换行
fout.write((s+"\r\n").getBytes());
}
fout.close();
}
将上一题产生的文件中的学生按照年龄升序排序后重新写回原文件;
效果
参考代码:
public static void main(String[] args) throws Exception {
File f = new File("1.txt");
//创建文件对象,准备读数据
FileInputStream fin = new FileInputStream(f);
byte[] arr = new byte[(int)f.length()];//文件中有多少字节,就创建多大的数组,一次性读完
fin.read(arr);//读到的数据都保存到了arr中
//把数组转成字符串
String s = new String(arr);
//使用换行符切分字符串
String[] split = s.split("\r\n");
//再使用逗号切分数组中的每一个元素,可以得到学生的姓名和年龄
//创建set集合并指定排序规则
TreeSet set = new TreeSet<>((s1,s2)->s1.getAge()-s2.getAge()==0?s1.getName().compareTo(s2.getName()):s1.getAge()-s2.getAge());
for (String s1 : split) {
String[] split1 = s1.split(",");
//把按照切分出来的数组的第1个值作为name,第二个值作为age创建学生对象,并按照年龄排序
Student stu = new Student(split1[0],Integer.parseInt(split1[1]));
set.add(stu);
}
//创建输出流,并把set集合中的学生信息重新写入1.txt文件中;(重写Student的toString方法了)
FileOutputStream fout = new FileOutputStream("1.txt");
for (Student stu : set) {
fout.write((stu.toString()+"\r\n").getBytes());
}
fin.close();
fout.close();
System.out.println("排序已完成");
}
训练目标:掌握java中File的基本使用,以及理解其在实际开发中的应用
需求背景:当电脑磁盘上存储的文件越来越多的时候,要从系统中查找某一个文件就变的比较麻烦。为了快速从磁盘上找的某一类文件,此时就可以借助于类似于Everything这样的文件搜索工具
实现文件的搜素。如下所示,就是借助于Everything搜素本地磁盘上所有以.java结尾的文件的效果:
需求描述: 现通过程序模拟Everything搜索工具搜索效果,在素材everthing项目中的指定位置补全代码实现搜索功能。案例的实现效果如下所示:
实现提示:
1、需要使用到递归算法
2、控制台输出内容对齐可以调用padRight方法通过补全字符的方式进行实现
3、使用SimpleDateFormat对日期数据进行格式化
代码实现:见《答案/代码/everthing》
package com.Teacher10.demo01_KeHouLianXi.B.ti1;
//day09\素材\everthing\src\com\it\file\entry
import java.io.File;
import java.util.Date;
public class Entry {
public static void main(String[] args) {
// 定义要搜索的文件的后缀名
String suffix = "java";
// 搜索tanhua-admin这个文件夹中所有以.java结尾的文件,并将搜索到文件名称和文件的绝对路径打印到控制台
File sourceDir = new File("E:\\");
// 调用printAllSuffixFilePath方法
System.out.println(padRight("名称", 25, ' ') + "\t" + padRight("路径", 109, ' ') + "\t" + padRight("大小(字节)", 5, ' ') + "\t" + "最后一次修改时间");
printAllSuffixFilePath(sourceDir, suffix);
}
/*// 进行递归搜索
public static void printAllSuffixFilePath(File sourceDir , String suffix) {
if(!sourceDir.exists()){
System.out.println("文件或文件夹路径不正确...");
return;
}
if(sourceDir.isFile()){
// 判断参数路径如果是文件,则进行如下处理
if(sourceDir.getName().contains(suffix)){
System.out.print(padRight(sourceDir.getName(),25,' '));
System.out.print(padRight(sourceDir.getAbsolutePath(),115,' '));
System.out.print(padRight(sourceDir.length()+"",15,' '));
System.out.print(padRight(new Date(sourceDir.lastModified()).toLocaleString(),20,' '));
System.out.println();
}
}else {
// 判断文件夹是不是包含java,如果包含,则打印当前这个文件夹,如果不包含,则不打印;
// 但是无论当前文件夹是否包含java,我们都应该递归遍历它;
// 判断参数路径如果是文件,则进行如下处理
if(sourceDir.getName().contains(suffix)){
System.out.print(padRight(sourceDir.getName(),25,' '));
System.out.print(padRight(sourceDir.getAbsolutePath(),115,' '));
System.out.print(padRight(sourceDir.length()+"",15,' '));
System.out.print(padRight(new Date(sourceDir.lastModified()).toLocaleString(),20,' '));
System.out.println();
}
// 代码执行到这里,说明sourceDir肯定是文件夹
File[] files = sourceDir.listFiles();
for (File file : files) {
// 拿到sourceDir里面的每个内容之后,继续调用自定义的方法
printAllSuffixFilePath(file,suffix);
}
}
// 补全代码
}*/
// 进行递归搜索
public static void printAllSuffixFilePath(File sourceDir, String suffix) {
if (!sourceDir.exists()) {
System.out.println("文件或文件夹路径不正确...");
return;
}
// 判断文件或文件夹是不是包含java,如果包含,则打印当前这个东西,如果不包含,则不打印;
// 但是无论当前文件夹是否包含java,我们都应该递归遍历它;
// 判断参数路径如果是文件,则进行如下处理
if (sourceDir.getName().contains(suffix)) {
System.out.print(padRight(sourceDir.getName(), 25, ' '));
System.out.print(padRight(sourceDir.getAbsolutePath(), 115, ' '));
System.out.print(padRight(sourceDir.length() + "", 15, ' '));
System.out.print(padRight(new Date(sourceDir.lastModified()).toLocaleString(), 20, ' '));
System.out.println();
}
if (sourceDir.isDirectory()) {
// 代码执行到这里,说明sourceDir肯定是文件夹
File[] files = sourceDir.listFiles();
for (File file : files) {
// 拿到sourceDir里面的每个内容之后,继续调用自定义的方法
printAllSuffixFilePath(file, suffix);
}
}
}
/**
* 右侧补字符
*/
public static String padRight(String origin, int length, char ch) {
while (origin.length() < length) {
origin = origin + ch;
}
return origin;
}
}
简述IO流的分类以及输入流和输出流作用?
答:
①
按照数据的流向划分: 输入流和输出流
按照操作数据类型划分:字节流和字符流
将上述的两种划分方式进行结合划分:
- 字节输入流和字节输出流
- 字符输入流和字符输出流
② 作用:输入流负责读取数据,输出流负责写数据
请说明如下程序执行完毕以后结果并说明原因?
答:上述程序执行完毕以后,会在控制台输出Exception in thread "main" java.io.FileNotFoundException: itheima (拒绝访问。)异常信息。
因为it是一个文件夹,不是文件。数据不能写入到文件夹中。
如下两段程序:
上述程序是分别采用基本的字节输入和输出流和高效的字节输入和输出流将D:\a.txt文件中的内容复制到D:\b.txt文件中。如果a.txt文件的大小大于8192字节小于16384个字节,那么哪一种方式
复制文件的效率较高并说明原因?
答:
[基本的字节]输入和输出流复制文件的效率较高,
因为通过基本的字节输入和输入流在进行上述文件复制的时候,
在读取数据的时候只需要和操作系统交互一次。
[而使用高效]的字节输入和输出流复制文件的时候,
由于没有指定字符缓存区的大小,默认大小就是8192个字节。
而要读取的字节大小为16384个字节,因此需要和操作系统交互两次,所以效率较低。
Java中的字节流是可以操作任意类型的数据(音频、视频、文本...),请简述字符流出现的意义?
答:
一个[中文汉字]在计算机上进行存储的时候使用的是[多个字节]进行存储,
如果使用[字节流]来读取汉字,要读取到一个[完整的汉字]可能需要[读取多次]。
比较麻烦,为了简化对中文汉字的操作,Java给我们提供了[字符流]。
请将如下程序分别在idea和dos控制台进行执行,分析输出不同结果的原因?如何解决dos控制台结果的输出问题?
// 对"中国"进行编码
String s1 = "中国" ;
byte[] bytes = s1.getBytes();
// 对上述得到的字节数组进行编码
String s2 = new String(bytes , "UTF-8") ;
System.out.println(s2);
答:
① 上述程序在idea中执行可以正常输出中国。
原因:在进行编码的时候没有显示的指定使用的字符编码表,
那么此时默认使用的是平台(操作系统)所对应的字符编码表。
而现在大家使用的都是 windows中文系统,因此默认的编码表就是GBK。
但是在idea中运行程序的时候,添加了一个JVM参数-Dfile.encoding=UTF-8。
更改了平台默认的字符编码,所以不会出现乱码。
② 在dos控制台执行上述程序的时候会出现乱码。
因为平台默认的字符编码表为GBK,使用GBK进行编码,使用UTF-8进行解码。
字符编码表不一致此时就会出现乱码。
③ 解决dos控制台执行程序乱码问题:
可以在运行程序的时候添加一个JVM参数-Dfile.encoding=UTF-8。 如下所示
训练目标:掌握java中字节输入流和字节输出流的基本使用,以及理解其在实际开发中的应用
需求背景:为了保证磁盘文件数据的安全性,就需要对原始文件进行加密存储,再使用的时候再对其进行解密处理。加密解密原理:对原始文件中的每一个字节数据进行更改,然后将更改以后的
数据存储到新的文件中。
需求描述: 编写一个加密解密程序。
实现提示:
1、通过字节输入流读取原始文件中的每一个字节数据然后对其进行处理
2、通过字节输出流将处理以后的字节数据写入到另外一个文件中
3、对字节数据的处理方式可以使用异或运算符异或一个数
4、为了提高加解密的效率可以考虑使用高效的字节输入和输出流
代码实现:
public class Entry {
public static void main(String[] args) throws IOException {
// 加密
encryptAndDecryption("E:/a.mp4" , "E:/b.mp4");
// 解密
encryptAndDecryption("E:/b.mp4" , "E:/a.mp4");
}
// 加密和解密程序
public static void encryptAndDecryption(String souceFilePath , String destFilePath) throws IOException {
// 创建一个高效的字节输入流对象关联原始文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(souceFilePath));
// 创建一个高效的字节输出流对象关联目标文件
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
// 一次读取一个字节数据
int by = 0 ;
while((by = bis.read()) != -1) {
by ^= 2 ; // 一个数对另外一个数异或两次其值不变
bos.write(by);
}
// 释放资源
bos.close();
bis.close();
}
}
package com.Teacher10.demo01_KeHouLianXi.B.ti2;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
/*
所谓的加密,实际上就是将原始文件中的每个字节按照一个指定的方式进行运算,将运算得出的结果,再重新保存到一个新的文件中;这就是加密
所谓解密,就是在读取加密后的文件时,读到的每个字节数据,按照一个指定的方式还原成原来的数据,将运算得出的结果,进行展示;
采用抑或运算进行加密和解密;
*/
public class ti2 {
public static void main(String[] args) throws Exception {
//jiMa();
jieMi();
}
// 解密
private static void jieMi() throws Exception {
// 读加密后的文件
FileInputStream fin = new FileInputStream("day10_day11_IO\\src\\com\\Teacher10\\1_jiaMi.txt");
byte[] arr = new byte[1024];
int len ;
// 循环读数据
while ((len = fin.read(arr))!=-1){
// 本次循环,读到了len个有效数据
// 对len个有效数据,进行抑或运算
for (int i = 0; i
训练目标:掌握java中字节输入流和字节输出流的基本使用,以及理解其在实际开发中的应用
需求背景:二维码又称二维条码,常见的二维码为QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能
表示更多的数据类型。下方给大家展示的是一个个人信息的二维码:
使用微信扫描该二维码,可以得到二维码所承载数据,如下所示:
需求描述:在素材的code项目中指定位置补全代码,获取个人信息二维码保存到本地磁盘。
实现提示:
1、生成二维码的程序已经在素材文件中提供好了(qrcode.jar), 在dos控制台通过java -jar qrcode.jar
启动该程序。效果如下所示:
2、在code项目中,通过程序请求生成二维码程序获取字节输入流代码已经提供
3、保存二维码数据到本地文件,这个本地文件的后缀名可以为png
代码实现:见《答案/代码/code》
E:\IdeaProjects\object\javaSE102\day10_day11_IO\src\com\Teacher11
package com.Teacher10.demo01_KeHouLianXi.code;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
public class Entry {
public static void main(String[] args) throws Exception {
// 调用getCodeInputStream方法,传递用户姓名,请求二维码生成程序,得到字节输入流对象
InputStream inputStream = getCodeInputStream("张三");
// 补全代码
// 将上述的字节输入流转换成一个高效的字节输入流对象
BufferedInputStream bis = new BufferedInputStream(inputStream);
// 创建一个高效的字节输出流对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("name.png"));
// 一次读取一个字节数据获取二维码数据,将其保存到本地的name.png文件中
byte[] bytes = new byte[1024] ;
int len = 0 ;
while((len = bis.read(bytes)) != -1) {
bos.write(bytes , 0 , len);
}
// 释放资源
bos.close();
bis.close();
}
// 请求生成二维码程序
public static InputStream getCodeInputStream(String name) {
try {
String encode = URLEncoder.encode(name, "UTF-8");
URL url = new URL("http://localhost/qrcode/userInfo/" + encode);
URLConnection connection = url.openConnection();
InputStream inputStream = connection.getInputStream();
return inputStream ;
} catch (Exception e) {
e.printStackTrace();
}
return null ;
}
}
public class CharStreamDemo3 {
public static void main(String[] args) throws IOException {
//创建字符输出流的对象
//FileWriter fw = new FileWriter(new File("charstream\\a.txt"));
FileWriter fw = new FileWriter("day10_IO\\a.txt");
}
public class CharStreamDemo3 {
public static void main(String[] args) throws IOException {
//创建字符输出流的对象
//FileWriter fw = new FileWriter(new File("charstream\\a.txt"));
FileWriter fw = new FileWriter("day10_IO\\a.txt");
method1(fw);
//释放资源
fw.close();
}
private static void method1(FileWriter fw) throws IOException {
//void write(String str, int off, int len) 写一个字符串的一部分
String line = "程序员abc";
fw.write(line,0,2);
}
public class CharStreamDemo3 {
public static void main(String[] args) throws IOException {
//创建字符输出流的对象
//FileWriter fw = new FileWriter(new File("charstream\\a.txt"));
FileWriter fw = new FileWriter("day10_IO\\a.txt");
}
private static void method1(FileWriter fw) throws IOException {
//写出数据
//void write(int c) 写一个字符
fw.write(97);
fw.write(98);
fw.write(99);
}
Process finished with exit code 0
a.txt :abc
private static void method2(FileWriter fw) throws IOException {
//void write(char[] cbuf) 写出一个[字符数组]
char [] chars = {97,98,99,100,101};
fw.write(chars);
}
private static void method3(FileWriter fw) throws IOException {
//void write(char[] cbuf, int off, int len) 写出字符数组的一部分
char [] chars = {97,98,99,100,101};
fw.write(chars,0,3);
}
private static void method4(FileWriter fw) throws IOException {
//void write(String str) 写一个字符串 最常用的
String line = "程序员abc";
fw.write(line);
}
private static void method5(FileWriter fw) throws IOException {
//void write(String str, int off, int len) 写一个[字符串的一部分] 最常用的
String line = "程序员abc";
fw.write(line,0,2);
}
最常用的如下
package com.charstream.charstream1;
import java.io.FileWriter;
import java.io.IOException;
public class CharStreamDemo4 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("day10_IO\\a.txt");
fw.write("程序员");//如果文件不存在,就创建。但是要保证父级路径存在。如果文件存在就清空。
fw.write(97);//1,写出int类型的整数,实际写出的是整数在码表上对应的字母。 2,写出字符串数据,是把字符串本身原样写出。
fw.write("97");//
fw.close();// 2,写出字符串数据,是把字符串本身原样写出。
}
}
package com.charstream.charstream1;
import java.io.FileWriter;
import java.io.IOException;
public class CharStreamDemo5 {
public static void main(String[] args) throws IOException {
//flush()刷新流。刷新完毕之后,还可以继续写数据
//close()关闭流。释放资源。一旦关闭,就不能写数据
FileWriter fw = new FileWriter("day10_IO\\a.txt");
fw.write("程序员");
//fw.flush();刷新流。刷新完毕之后,还可以继续写数据
fw.write("666");
//fw.flush();刷新流。刷新完毕之后,还可以继续写数据
fw.close();//关闭流。释放资源。一旦关闭,就不能写数据
fw.write("aaa");//Stream closed
}
}
package com.charstream.charstream1;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamDemo6 {
public static void main(String[] args) throws IOException {
//创建字符输入流的对象
// FileReader fr = new FileReader(new File("charstream\\a.txt"));
FileReader fr = new FileReader("day10_IO\\a.txt");
//读取数据
//一次读取一个字符
int ch;
while((ch = fr.read()) != -1){
System.out.println((char) ch);
}
//释放资源
fr.close();
}
}
一次读取多个
package com.charstream.charstream1;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamDemo7 {
public static void main(String[] args) throws IOException {
//一次读取多个字符。
//创建对象
FileReader fr = new FileReader("day10_IO\\a.txt");
//创建一个数组
char [] chars = new char[1024];
int len;
//read方法还是读取,但是是一次读取多个字符
//他把读到的字符都存入到chars数组。
//返回值:表示本次读到了多少个字符。
while((len = fr.read(chars))!=-1){
System.out.println(new String(chars,0,len));
}
fr.close();
}
}
package com.charstream.charstream1;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class CharStreamDemo8 {
public static void main(String[] args) throws IOException {
//将键盘录入的用户名和密码保存到本地实现永久化存储
//要求:用户名独占一行,密码独占一行
//分析:
//1,实现键盘录入,把用户名和密码录入进来
Scanner sc = new Scanner(System.in);
System.out.println("请录入用户名");
String username = sc.next();
System.out.println("请录入密码");
String password = sc.next();
//2.分别把用户名和密码写到本地文件。
FileWriter fw = new FileWriter("day10_IO\\a.txt");
//将用户名和密码写到文件中
fw.write(username);
//表示写出一个回车换行符 windows \r\n MacOS \r Linux \n
fw.write("\r\n");
fw.write(password);
//刷新流
fw.flush();
//释放资源
fw.close();
}
}
//字符缓冲输入流
package com.charstream.charstream1;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamDemo9 {
public static void main(String[] args) throws IOException {
//字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("day10_IO\\a.txt"));
//读取数据
char [] chars = new char[1024];
int len;
while((len = br.read(chars)) != -1){
System.out.println(new String(chars,0,len));
}
br.close();
}
}
张明
123456
Process finished with exit code 0
//字符缓冲输出流
package com.charstream.charstream1;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class CharStreamDemo10 {
public static void main(String[] args) throws IOException {
//字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("day10_IO\\a.txt"));
//写出数据
//实际写出的是97对应的字符a
bw.write(97);
bw.write("\r\n");
//实际写出的是97 - 101 对应的字符 abcde
char [] chars = {97,98,99,100,101};
bw.write(chars);
bw.write("\r\n");
//实际写的是abc
bw.write(chars,0,3);
bw.write("\r\n");
//会把字符串的内容原样写出
bw.write("程序员");
bw.write("\r\n");
//会把字符串的一部分写出 abcde
String line = "abcdefg";
bw.write(line,0,5);
bw.flush();
bw.close();
}
}
Process finished with exit code 0
a.txt:
a
abcde
abc
程序员
abcde
写入一整行:
package com.charstream.charstream1;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class CharStreamDemo11 {
public static void main(String[] args) throws IOException {
//字符缓冲流的特有功能
//字符缓冲输出流BufferedWrite : newLine 跨平台的换行符
//创建对象
BufferedWriter bw = new BufferedWriter(new FileWriter("day10_IO\\a.txt"));
//写出数据
bw.write("程序员666");
//跨平台的回车换行
bw.newLine();
bw.write("abcdef");
//跨平台的回车换行
bw.newLine();
bw.write("-------------");
//刷新流
bw.flush();
//释放资源
bw.close();
}
}
读一整行:
package com.charstream.charstream1;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamDemo12 {
public static void main(String[] args) throws IOException {
//字符缓冲流的特有功能
//字符缓冲输入流BufferedReader: readLine 读一整行
//创建对象
BufferedReader br = new BufferedReader(new FileReader("day10_IO\\a.txt"));
//读取数据
String line1 = br.readLine();
String line2 = br.readLine();
String line3 = br.readLine();
//在之前,如果读不到数据,返回-1
//但是readLine如果读不到数据返回null
String line4 = br.readLine();
String line5 = br.readLine();
System.out.println(line1);
System.out.println(line2);
System.out.println(line3);
System.out.println(line4);
System.out.println(line5);
// 释放资源
br.close();
}
}
程序员666
abcdef
-------------
null
null
Process finished with exit code 0
//使用循环来进行改进
package com.charstream.charstream1;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamDemo13 {
public static void main(String[] args) throws IOException {
//字符缓冲流的特有功能
//字符缓冲输入流BufferedReader: readLine 读一整行
//创建对象
BufferedReader br = new BufferedReader(new FileReader("day10_IO\\a.txt"));
//使用循环来进行改进
String line;
//可以读取一整行数据。一直读,读到回车换行为止。
//但是他不会读取回车换行符。
while((line = br.readLine()) != null){
System.out.println(line);
}
//释放资源
br.close();
}
}
InputStreamReader是从字[节流]到[字符流]的桥梁:
它[读取字节],并[使用指定]的[charset(编码表)]将其[解码为字符]。
它使用的[字符集]可以由[名称指定],也可以被[明确指定],或者可以接受平台的[默认字符集]。
[charset]:指的是编码表
[字符集]:指的是编码表
每个调用InputStreamReader的read()方法之一可能会导致从底层字节输入流读取一个或多个字节。
为了使字节有效地转换为字符,可以从底层流读取比满足当前读取操作所需的更多字节。
为了最大的效率,请考虑在BufferedReader中包装一个InputStreamReader。 例如:
BufferedReader in
= new BufferedReader(new InputStreamReader(System.in));
OutputStreamWriter是从[字符流]到[字节流]的桥梁:
使用指定的[charset(编码表)]将写入的[字符编码]为[字节]。
它使用的[字符集(编码表)]可以由[名称]指定,
也可以被[明确]指定,
或者可以接受平台的默认[字符集(编码表)]。
每次调用write()方法都会使编码转换器在给定的字符上被调用。
所得到的字节在写入底层输出流之前累积在缓冲区中。
请注意,传递给write()方法的字符不会缓冲。
为了最大的效率,请考虑在BufferedWriter中包装一个OutputStreamWriter,以避免频繁的转换器调用。
例如:
Writer out
= new BufferedWriter(new OutputStreamWriter(System.out));
转换流-指定编码:
//这个方法直接读取会产生乱码
//因为文件是GBK码表
//而idea默认的是UTF-8编码格式.
//所以两者不一致,导致乱码
private static void method1() throws IOException {
FileReader fr = new FileReader("C:\\Users\\apple\\Desktop\\a.txt");
int ch;
while ((ch = fr.read())!=-1){
System.out.println((char) ch);
}
fr.close();
}
利用指定编码读写:InputStreamReader
private static void method2() throws IOException {
//如何解决乱码现象
//文件是什么码表,那么咱们就必须使用什么码表去读取.
//我们就要指定使用GBK码表去读取文件. [InputStreamReader] PK [FileReader]
InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\Users\\apple\\Desktop\\a.txt"),"gbk");
int ch;
while((ch = isr.read())!=-1){ //读取 read
System.out.println((char) ch);//char的转换
}
isr.close();
//[ OutputStreamWriter]
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("C:\\Users\\apple\\Desktop\\b.txt"),"UTF-8");
osw.write("我爱学习,谁也别打扰我"); //写入write
osw.close();
}
// 不会乱码
JDK11之后,就没有必要再需要用转换流进行指定编码读写了
private static void method3() throws IOException {
//在JDK11之后,字符流新推出了一个构造,也可以指定编码表
FileReader fr = new FileReader("C:\\Users\\apple\\Desktop\\a.txt", Charset.forName("gbk"));
int ch;
while ((ch = fr.read())!=-1){
System.out.println((char) ch);
}
fr.close();
}
对象转换流-操作流程
先看:只要是a.txt都可以看到姓名跟密码,数据是非常不安全的
package com.otheriomodule.convertedio;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class ConvertedDemo2 {
public static void main(String[] args) throws IOException {
User user = new User("zhangsan","qwer");
//需求:把这个用户信息保存到本地文件去.
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
bw.write(user.getUsername());
bw.newLine();
bw.write(user.getPassword());
bw.close();
}
}
package com.otheriomodule.convertedio;
import java.io.Serializable;
//如果想要这个类的对象能被序列化,那么这个类必须要实现一个接口.Serializable
//Serializable 接口的意义
//称之为是一个标记性接口,里面没有任何的抽象方法
//只要一个类实现了这个Serializable接口,那么就表示这个类的对象可以被序列化.
public class User implements Serializable {
//serialVersionUID 序列号
//如果我们自己没有定义,那么虚拟机会根据类中的信息会自动的计算出一个序列号.
//问题:如果我们修改了类中的信息.那么虚拟机会再次计算出一个序列号.
//第一步:把User对象序列化到本地. --- -5824992206458892149
//第二步:修改了javabean类. 导致 --- 类中的序列号 4900133124572371851
//第三步:把文件中的对象读到内存. 本地中的序列号和类中的序列号不一致了.
//解决?
//不让虚拟机帮我们自动计算,我们自己手动给出.而且这个值不要变.
private static final long serialVersionUID = 1L;
private String username;
private transient String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
package com.otheriomodule.convertedio;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ConvertedDemo3 {
public static void main(String[] args) throws IOException {
User user = new User("zhangsan","qwer");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
oos.writeObject(user);
oos.close();
}
}
转换流-对象反序列流 -指定编码-读ObjectInputStream-.readObject();
package com.otheriomodule.convertedio;
import java.io.*;
import java.util.ArrayList;
public class ConvertedDemo5 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//1.写对象
//2.修改javabean类
//3.读对象
//写对象 --- 序列化
//读对象 --- 反序列化
method2();
method1();
}
private static void method2() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
User o = (User) ois.readObject();
System.out.println(o);
ois.close();
}
private static void method1() throws IOException {
User user = new User("zhangsan","qwer");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
oos.writeObject(user);
oos.close();
}
}
package com.otheriomodule.convertedio;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ConvertedDemo4 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
User o = (User) ois.readObject();
System.out.println(o);
ois.close();
}
}
public class User implements Serializable {
//serialVersionUID 序列号 --反序列化流
//如果我们自己没有定义,那么[虚拟机]会根据类中的信息会自动的计算出一个序列号.
//问题:如果我们修改了类中的信息.那么虚拟机会再次计算出一个序列号.
//第一步:把User对象序列化到本地. --- -5824992206458892149
//第二步:修改了javabean类. 导致 --- 类中的序列号 4900133124572371851
//第三步:把文件中的对象读到内存. 本地中的序列号和类中的序列号不一致了.
//解决?
//不让虚拟机帮我们自动计算,我们自己手动给出.而且这个值不要变.
private static final long serialVersionUID = 1L;
package com.otheriomodule.convertedio;
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = 2L;
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.otheriomodule.convertedio;
import java.io.*;
import java.util.ArrayList;
public class ConvertedDemo7 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Student s1 = new Student("杜子腾",16);
Student s2 = new Student("张三",23);
Student s3 = new Student("李四",24);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
ArrayList list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3);
//我们往本地文件中写的就是一个集合
oos.writeObject(list);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
ArrayList list2 = (ArrayList) ois.readObject();
for (Student student : list2) {
System.out.println(student);
}
ois.close();
}
}
package com.otheriomodule.propertiesio;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo1 {
public static void main(String[] args) {
Properties prop = new Properties();
//增
prop.put("小龙女","尹志平");
prop.put("郭襄","杨过");
prop.put("黄蓉","欧阳克");
System.out.println(prop);
//删
//prop.remove("郭襄");
//System.out.println(prop);
//改
//put --- 如果键不存在,那么就添加,如果键存在,那么就覆盖.
prop.put("小龙女","杨过");
System.out.println(prop);
//查
//Object value = prop.get("黄蓉");
//System.out.println(value);
//遍历
Set
public static void main(String[] args) {
//Object setProperty(String key, String value) --- put
//设置集合的键和值,都是String类型,底层调用 Hashtable方法 put
Properties prop = new Properties();
prop.setProperty("江苏", "南京");
prop.setProperty("安徽", "南京");
prop.setProperty("山东", "济南"); //存
System.out.println(prop);
}
{山东=济南, 江苏=南京, 安徽=南京}
Process finished with exit code 0
//String getProperty(String key) --- get
//使用此属性列表中指定的键搜索属性
private static void method1(Properties prop) {
String value = prop.getProperty("江苏"); //取
System.out.println(value);
System.out.println("===================");
}
南京
===================
Process finished with exit code 0
//Set stringPropertyNames() --- keySet
//从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
private static void method2(Properties prop) {
Set keys = prop.stringPropertyNames(); //遍历
for (String key : keys) {
String value = prop.getProperty(key);
System.out.println(key + "=" + value);
}
}
山东=济南
江苏=南京
安徽=南京
Process finished with exit code 0
读取
package com.otheriomodule.propertiesio;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
public class PropertiesDemo3 {
public static void main(String[] args) throws IOException {
//void load(Reader reader) 将本地文件中的键值对数据读取到集合中
//void store(Writer writer, String comments) 将集合中的数据以键值对形式保存在本地
//读取
Properties prop = new Properties();
FileReader fr = new FileReader("prop.properties");
//调用完了load方法之后,文件中的键值对数据已经在集合中了.
prop.load(fr); //void load(Reader reader)
fr.close();
System.out.println(prop);
}
}
保存 写入
package com.otheriomodule.propertiesio;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
public class PropertiesDemo4 {
public static void main(String[] args) throws IOException {
//void load(Reader reader) 将本地文件中的键值对数据读取到集合中
//void store(Writer writer, String comments) 将集合中的数据以键值对形式保存在本地
Properties prop = new Properties();
prop.put("zhangsan","123");
prop.put("lisi","456");
prop.put("wangwu","789");
FileWriter fw = new FileWriter("prop.properties");
prop.store(fw,null);//void store(Writer writer, String comments)
fw.close();
}
}
如下程序执行完毕以后,a.txt文件中的内容是什么并说明原因?
答:
执行效果:在a.txt文件中没有任何内容
原因说明:使用[字符流]写数据并不是直接将数据写入到磁盘中,而是先写入到了[缓存区]中。
而代码中没有对缓存区进行[刷新]也没有[关闭流]对象,因此数据就[没有]被写入到[磁盘]中。
简述flush方法和close方法的区别?
答:
① flush方法表示[刷新缓存]区,调用完flush方法以后[流对象]还可以继续使用
② close方法[关闭流]对象,在[关闭之前]会执行[刷新缓存]区的操作,流对象一旦被关闭了,就不能在使用了。
请分析如下程序执行完毕以后a.txt文件的内容是什么并说明原因?如果需要在a.txt文件中保存所有数据应该怎么处理?
答:
① 上述程序执行完毕以后a.txt文件中的内容为:马克。
因为第二次在写数据的时候,创建了一个[新的流]对象,这种创建方式会[清空原有]文件中的内容。
② 要留所写的所有数据:在创建fw2对象的时候,使用如下方式:
FileWriter fw2 = new FileWriter("a.txt", true);
运行下述程序会出现什么错误?请说明出现该错误的原因以及如何解决该错误?
答:
① 运行上述程序会出现如下异常:Exception in thread "main" java.io.NotSerializableException: com.itheima.io.User
② 原因:使用[序列化流]对对象进行序列化操作的时候,要求[序列化对象]所对应的[类实现序列化]接口。
而User类并没有[实现序列化]接口。
③ 解决方案:当User类实现序列化接口。如果所示:
请分析产生如下错误的原因以及对应的解决方案?
Exception in thread "main" java.io.InvalidClassException: com.itheima.io.obj.User; local class incompatible: stream classdesc serialVersionUID = 4001622083751882644, local class serialVersionUID = 6175241864707791838
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:687)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1883)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1749)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2040)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1571)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at com.itheima.io.obj.Demo01.main(User.java:21)
答:
① 错误原因:序列化需要一个serialVersionUID(序列化ID), 修改完类文件了以后serialVersionUID与序列化之前不一致了,校验失败了,就抛出异常了。
② 解决方案:给对象生成一个固定serialVersionUID
具体实现步骤:
1. idea设置:setting ---> Inspections ---> 搜索serialVersionUID ---> 勾选"Serializable class without serialVersionUID"
2. 然后光标放在类明上,使用快捷键:alt + enter,此时会弹出如下对话框:
训练目标:掌握java中高效的字符流的基本使用,以及理解其在实际开发中的应用
需求描述:某公司年会需要搞抽奖活动以此感谢公司员工这一年的辛勤付出。要求当某一个员工已经被抽取到了,再抽取下一个奖项的时候该员工不能再次被抽到。请编写程序实现该抽奖活动。
程序的运行效果如下所示:
实现提示:
1、在提供的素材(lucky)项目中的指定位置补全代码实现功能
2、使用BufferedReader读取employee_names.txt文件中的数据,并将其存储到一个集合中
3、生成一个随机数,作为集合元素的索引
4、根据该索引从集合中获取一个员工姓名,并将该员工姓名从集合中移除掉
5、将集合中剩余的员工姓名通过BufferedWriter再一次写入到employee_names.txt文件中
代码实现:见《答案/代码/lucky》
package com.Teacher11.demo01_KeHouLianXi.day11_ti1;
import java.io.*;
import java.util.ArrayList;
import java.util.Random;
public class Entry {
public static void main(String[] args) throws IOException {
/*
2、使用BufferedReader读取employee_names.txt文件中的数据,并将其存储到一个集合中
3、生成一个随机数,作为集合元素的索引
4、根据该索引从集合中获取一个员工姓名,并将该员工姓名从集合中移除掉
5、将集合中剩余的员工姓名通过BufferedWriter再一次写入到employee_names.txt文件中
*/
BufferedReader br = new BufferedReader(new FileReader("E:\\IdeaProjects\\object\\javaSE102\\day10_day11_IO\\src\\com\\Teacher11\\demo01_KeHouLianXi\\day11_ti1\\user\\employee_names.txt"));
String s = null;
ArrayList list = new ArrayList<>();
// 循环读数据并添加到集合
while ((s=br.readLine())!=null){
if(s.trim().length()>0){
list.add(s);
}
}
br.close();
//3、生成一个随机数,作为集合元素的索引
Random r = new Random();
int i = r.nextInt(list.size());
// 4: 抽一个中奖的人
String s1 = list.remove(i);
System.out.println("恭喜:"+s1+" 中了特等奖...");
// 5、将集合中剩余的员工姓名通过BufferedWriter再一次写入到employee_names.txt文件中
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\IdeaProjects\\object\\javaSE102\\day10_day11_IO\\src\\com\\Teacher11\\demo01_KeHouLianXi\\day11_ti1\\user\\employee_names.txt"));
for (String s2 : list) {
bw.write(s2);
bw.newLine();
bw.flush();
}
bw.close();
System.out.println("完事");
}
}
训练目标:掌握java中Properties集合的使用,以及理解其在实际开发中的应用
需求背景:电子邮件的应用非常广泛,常见的如在某网站注册了一个账户,自动发送一封激活邮件,通过邮件找回密码,自动批量发送活动信息等。很显然这些应用不可能和我们自己平时发邮件
一样,先打开浏览器,登录邮箱,创建邮件再发送。而是通过程序实现邮件的发送。在素材文件中提供了一个项目prop,可以实现通过Java代码发送邮件。如下所示:
上述代码实现了:通过网易邮箱[email protected]向[email protected]发送了一份邮件。效果如下所示:
但是上述程序存在一定的弊端:硬编码。这样不利于后期代码的维护,比如要修改发件人、收件人、邮件主题、邮件正文等信息的时候都需要对代码进行修改。
需求描述:使用Properties集合对上发送邮件的代码进行优化,以提高代码的维护性。
实现提示:
1、上述程序中关于发件人和收件人是使用老师提供的账号。如果需要使用自己的账号来实现邮件的发送,请注册网易云邮箱,注册地址:163网易免费邮-你的专业电子邮局。注册完毕以后需要开通指定的
服务才可以实现邮件的发送。如下所示:
注意:保存好授权密码,程序中需要使用
。
2、上述发送邮件程序中可更改的参数:发件人邮箱账号信息、收件人收件账号、邮箱主题、邮箱正文
3、创建一个properties属性文件,将上述可更改的内容定义到该文件中
4、在程序中读取第三步创建的文件内容到一个Properties集合中
5、从Properties集合中获取参数信息更改原有程序
6、电脑需要联网
代码实现:见《答案/代码/prop》
Properties
[email protected]
password=ETQGDUCEZRPLTBPR
[email protected]
zt=打折钜惠啦啦啦
content=玛尔扎哈用户你好, 今天全场5折, 快来抢购, 错过今天再等一年。。。
html=text/html;charset=UTF-8
package com.Teacher11.demo01_KeHouLianXi.day11_ti2;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.FileReader;
import java.util.Properties;
public class Entry {
public static void main(String[] args) throws Exception {
// 自己准备一个properties集合读配置文件的信息 补全
Properties p = new Properties();//补全
FileReader fr = new FileReader("E:\IdeaProjects\object\javaSE102\day10_day11_IO\src\com\Teacher11\demo01_KeHouLianXi\day11_ti2\1.properties");
p.load(fr);//补全
fr.close();//补全
// 1. 创建参数配置, 用于连接邮件服务器的参数配置
Properties props = new Properties(); // 参数配置
props.setProperty("mail.transport.protocol", "smtp"); // 使用的协议(JavaMail规范要求)
props.setProperty("mail.smtp.host", "smtp.163.com"); // 发件人的邮箱的SMTP服务器地址
props.setProperty("mail.smtp.auth", "true"); // 需要请求认证
// 2. 创建一个Session对象,用于和发送邮件程序进行交互
Session session = Session.getDefaultInstance(props);
// 3. 创建一封邮件 补全
MimeMessage message = new MimeMessage(session) ;
message.setFrom(new InternetAddress(p.getProperty("from")));//补全
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(p.getProperty("to"))); //补全// 设置发件人邮箱地址
message.setSubject(p.getProperty("zt"));//补全 // 设置收件人邮箱地址 // 设置邮箱主题
message.setContent(p.getProperty("content"), p.getProperty("html")); //补全// 设置邮箱正文
// 4. 根据 Session 获取邮件传输对象
Transport transport = session.getTransport();
// 5、建立连接 补全
transport.connect(p.getProperty("from"), p.getProperty("password"));//补全
// 6. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
transport.sendMessage(message, message.getAllRecipients());
// 7. 关闭连接
transport.close();
}
}
训练目标:掌握java中高效的字符流和转换流的基本使用,以及理解其在实际开发中的应用
需求背景:网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序。通过程序请求指定的网页,获取网
页数据对应的字节输入流对象,然后通过该输入流读取网页数据,再次对网页数据进行筛选获取有价值的数据,然后再将数据存储起来用于后期做数据分析。
需求描述:在素材的server.jar程序中存在两个网页:1.html和2.html 。现需要将这两个网页中"西安黑马"就业薪资信息,保存到一个本地文件中。程序运行完毕以后,本地文件中的数据如下所
示
实现提示:
1、通过java -jar server.jar
运行server.jar程序,程序运行效果如下所示:
2、server.jar程序启动起来以后,可以直接通过浏览器访问该程序中的1.html和2.html查看页面内容,如下所示访问的是1.html页面中的内容:
查看2.html网页内容,在浏览器的地址栏输入该地址:http://localhost/html/2.html
3、通过程序访问server.jar程序中的网页代码已在素材crawler项目中提供好了
4、在素材crawler项目的指定位置补全代码实现功能
5、进行字符串中特定字符的替换可以考虑使用正则表达式
代码实现:见《答案/代码/crawler》
考察字符串处理
package com.Teacher11.demo01_KeHouLianXi.day11_ti3;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
public class Entry {
public static void main(String[] args) throws IOException {
// 调用getUrlData方法,获取http://localhost/html/1.html网页数据对应的字节输入流对象
InputStream inputStream1 = getUrlData("http://localhost/html/1.html");
// 补全代码
/*
1: 利用inputStream1包装成[字符缓冲流],
2: 一次读一行信息,判断当前行中是否包含 超连接,如果包含,则就是我们想要的内容
3: 当我们拿到想要的信息后,去除 和的内容即可
4: 将处理后的字符串数据写到硬盘
*/
wr(inputStream1,"E:\\IdeaProjects\\object\\javaSE102\\day10_day11_IO\\src\\com\\Teacher11\\demo01_KeHouLianXi\\day11_ti3\\1.txt");
// 调用getUrlData方法,获取http://localhost/html/2.html网页数据对应的字节输入流对象
InputStream inputStream2 = getUrlData("http://localhost/html/2.html");
// 补全代码
wr(inputStream2,"E:\\IdeaProjects\\object\\javaSE102\\day10_day11_IO\\src\\com\\Teacher11\\demo01_KeHouLianXi\\day11_ti3\\2.txt");
// 释放资源
inputStream1.close();
inputStream2.close();
}
private static void wr(InputStream inputStream1, String s) throws IOException {
//1: 利用inputStream1包装成[字符缓冲流],inputStream1[字节流]
InputStreamReader isr = new InputStreamReader(inputStream1,"utf-8");
BufferedReader br = new BufferedReader(isr);
// 2: 一次读一行信息,判断当前行中是否包含 超连接,如果包含,则就是我们想要的内容
BufferedWriter bw = new BufferedWriter(new FileWriter(s));
String line = null;
while ((line=br.readLine())!=null){
//判断当前行中是否包含 超连接,如果包含,则就是我们想要的内容
if(line.contains("西安")){
// 对字符串进程处理,去除 和
line=line.replaceAll("","");
line=line.replaceAll("","");
// System.out.println(line);
bw.write(line.trim());
bw.newLine();
bw.flush();
}
}
br.close();
bw.close();
}
// 通过程序向指定的网页发送请求,得到网页数据对应的字节输入流对象
public static InputStream getUrlData(String httpUrl) {
try {
URL url = new URL(httpUrl);
URLConnection connection = url.openConnection();
InputStream inputStream = connection.getInputStream();
return inputStream ;
} catch (Exception e) {
e.printStackTrace();
}
return null ;
}
}