IO流进阶
一、缓冲流
1.1概述
缓冲流也称为高效流、或者高级流。之前学习的字节流可以称为原始流。
作用:缓冲流自带缓冲区(底层中自动创建了一个8K的字节数组)、可以提高原始字节流、字符流读写数据的性能。
1.2 分类
缓冲流分为四种
- 字节缓冲输入流:BufferedInputStream
- 字节缓冲输出流:BufferedOutputStream
- 字符缓冲输入流:BufferedReader
- 字符缓冲输出流:BufferedWriter
1.3 字节缓冲流
性能优化原理:
- 字节缓冲输入流自带一个8KB缓冲池,以后我们直接从缓冲池读取数据(底层实现将内容读入到缓冲池),读数据性能较好。
- 字节缓冲输出流自带一个8KB缓冲池,数据就直接写入到缓冲池中(底层实现将缓冲池的内容写入到目的地),写数据性能极高了。
字节缓冲流
- 字节缓冲输入流:BufferedInputStream,提高字节输入流读数据的性能,读写功能(使用方法)上并无变化。
- 字节缓冲输出流:BufferedOutputStream,提高字节输出流写数据的性能,读写功能(使用方法)上并无变化。
注意:**高级的缓冲流是用来包装低级的缓冲流,当需要追加文件内容时,需要在低级缓冲流上设置成追加,不是在高级缓冲流上设置;**当要使用缓冲流特有的方法时,需要使用子类去引用。
//底层源码,可以看到到默认给了一个DEFAULT_BUFFER_SIZE,这是底层创建的字符数组(缓冲区),为8192大小
public BufferedInputStream(InputStream in) {
this(in, DEFAULT_BUFFER_SIZE);
}
构造器 | 说明 |
---|---|
public BufferedInputStream(InputStream is) | 可以将低级的字节输入流包装成高级的缓冲字节输入流管道,从而提高字节输入流读数据的性能。 |
public BufferedOutputStream(OutputStream os) | 可以将低级的字节输出流包装成高级的缓冲字节输出流,从而提高字节输出流写数据的性能 |
try (
//低级的字节输入流
InputStream is = new FileInputStream("D:\\练习目录\\原地址\\ideaIU-2021.1.1.exe");
//包装成高级字节输出流
InputStream bis = new BufferedInputStream(is);
//低级的字节输出流
OutputStream os = new FileOutputStream("D:\\练习目录\\目的地址\\ideaIU-2021.1.1.exe");
//包装成高级的字节输出流
BufferedOutputStream bos = new BufferedOutputStream(os);
) {
int b;
//这里读和写必须使用高级缓冲输入输出流
while ((b = bis.read()) != -1)
bos.write(b);
} catch (Exception e) {
e.printStackTrace();
}
1.4 字节缓冲流的性能分析
建议使用字节缓冲输入流、字节缓冲输出流,结合字节数组的方式,目前来看是性能最优的组合。
分别使用不同的方式复制大视频观察性能情况
public static void main(String[] args) {
//这里我们拷贝一个700MB的文件
lowInput();//一个字节读写 性能很差,读写慢
lowInputArr();//3.608s 一个字节数组读写 性能很好,读写很快
heigh();//7.867s 缓冲流一个字节读写 性能好,读写快
heighArr();//0.842s 缓冲流一个数组读写 性能非常好 读写非常快
}
//高级的缓冲流一个数组读取
public static void heighArr(){
long start = System.currentTimeMillis();
try(
InputStream is = new FileInputStream("D:\\练习目录\\目的地址\\ideaIU-2021.1.1.exe");
InputStream bis = new BufferedInputStream(is);
OutputStream os = new FileOutputStream("D:\\练习目录\\目的地址\\4.exe");
OutputStream bos = new BufferedOutputStream(os);
){
//字节数组1024
byte[] bArr = new byte[1024];
while(bis.read(bArr)!=-1)
bos.write(bArr);
}catch (Exception e){
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("缓冲流一个数组读取:" + (end - start));
}
//高级的缓冲流一个字节读取
public static void heigh(){
long start = System.currentTimeMillis();
try(
InputStream is = new FileInputStream("D:\\练习目录\\目的地址\\ideaIU-2021.1.1.exe");
//包装成缓冲输入流(这里采用父类引用指向子类对象 多态)
InputStream bis = new BufferedInputStream(is);
OutputStream os = new FileOutputStream("D:\\练习目录\\目的地址\\3.exe");
//包装成高级的缓冲输出流
OutputStream bos = new BufferedOutputStream(os);
){
int b;
while ((b = bis.read()) != -1)
bos.write(b);
}catch (Exception e){
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("缓冲流一个字节读取耗时:" + (end-start)/1000.0);
}
//低级一个字节数组输入输出
public static void lowInputArr(){
long start = System.currentTimeMillis();
try(
InputStream is = new FileInputStream("D:\\练习目录\\目的地址\\ideaIU-2021.1.1.exe");
OutputStream os = new FileOutputStream("D:\\练习目录\\目的地址\\2.exe")
){
byte[] bArr = new byte[1024];
while (is.read(bArr) != -1)
os.write(bArr);
}catch (Exception e){
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("低级一个字节数组耗时:" + (end-start)/1000.0);
}
//一个字节输入输出
public static void lowInput() {
long start = System.currentTimeMillis();
try (
//字节输入输出流
InputStream is = new FileInputStream("D:\\练习目录\\目的地址\\ideaIU-2021.1.1.exe");
OutputStream os = new FileOutputStream("D:\\练习目录\\目的地址\\1.exe")
) {
int b;
while ((b = is.read()) != -1)
os.write(b);
} catch (Exception e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("低级一个字节读取耗时:" + (start - end / 1000.0));
}
1.5 字符缓冲流
字符缓冲输入流:BufferedReader。
- 作用:提高字符输入流读数据的性能,除此之外多了按照行读取数据的功能。(按行读时不会换行,需要我们自己写换行)
字符缓冲输出流:BufferedWriter。
- 作用:提高字符输出流写数据性能,除此之外多了一个换行的功能。
输入构造器 | 说明 |
---|---|
public BufferedReader(Reader r) | 可以将低级的字符输入流包装成高级的缓冲字符输入流管道,从而提高字符输入流读数据的性能 |
新增方法 | 说明 |
public String readLine() | 读取一行数据返回,如果没有可读的,就返回null |
输出构造器 | 说明 |
public BufferedWriter(Writer w) | 可以把低级的字符输出流包装成高级的缓冲字符输出流,从而提高字符输出流写数据的性能 |
新增方法 | 说明 |
public void newLine() | 换行 |
//读写文本文件的经典写法(常用写法)
try(
BufferedReader brd = new BufferedReader(new FileReader("TestModule\\src\\lzm\\Test1\\1.txt"));
BufferedWriter bwt = new BufferedWriter(new FileWriter("TestModule\\src\\lzm\\Test1\\2.txt"))
){
//读取一行临时存放的位置
String line = "";
while ((line = brd.readLine()) != null) {
bwt.write(line);
//换行
bwt.newLine();
}
}catch (Exception e){
e.printStackTrace();
}
1.6 练习
使用字符缓冲流将以下内容按顺序恢复到一个新文件中
一、我是第一行
十一、我是第十一行
九、我是第九行
五、我是第五行
三、我是第三行
四、我是第四行
八、我是第八行
六、我是第六行
二、我是第二行
十、我是第十行
七、我是第七行
分析:
- 定义一个缓存字符输入流管道与源文件接通
- 定义一个List集合存储读取的每行数据
- 定义一个循环按照行读取数据,存入到List集合中去
- 对List集合中的每行数据按照首字符编号升序排序
- 定义一个缓存字符输出管道与目标文件接通
- 遍历List集合中的每个元素,用缓冲字符输出流管道写出并换行
//将指定路径下的文本内容按照其序号排序
public static void main(String[] args) {
try(
//一、创建字符输入流对象和字符输出流对象
Reader rd = new FileReader("TestModule\\src\\lzm\\Test1\\练习.txt");
Writer wt = new FileWriter("TestModule\\src\\lzm\\Test1\\1.txt");
//包装成高级的缓冲输入输出流对象
//此处如果想要使用子类的独特方法,就需要使用子类引用指向子类对象
BufferedReader brd = new BufferedReader(rd);
BufferedWriter bwt = new BufferedWriter(wt);
) {
//二、创建集合存放文本中的每一行内容(按行存,所以用到读一行的方法)
List<String> list = new ArrayList<>();
//四、使用集合制定一个排序的规则(让list集合根据这个规则来排序)
List<String> sortRule = new ArrayList<>();
//五、将一二三...按顺序存放到规则集合中
Collections.addAll(sortRule,"一","二","三","四","五","六","七","八","九","十","十一");
String line = "";
//三、每次读取一行放到集合中
while ((line = brd.readLine()) != null) {
list.add(line);
}
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//六、根据规则排序
//思路:取出list集合中的每行第一个字符(因为这个字符是顺序),然后找出第一个字符在规则集合中的索引位置,然后根据两个索引位置就能比对出大小
//substring用来截取字符串某一段
//indexOf获取此时判断的第一个字符对象的索引值
return sortRule.indexOf(o1.substring(0,o1.indexOf("、"))) - sortRule.indexOf(o2.substring(0,o2.indexOf("、")));
}
});
//七、遍历排序好的集合,将每一行写到指定文件中
//记得换行
for (String s : list) {
bwt.write(s);
bwt.newLine();
}
} catch (Exception e) {
e.printStackTrace();
}
}
二、转换流
2.1 乱码问题
什么时候会乱码?
- 当读的文件和写的文件编码一致时不会乱码。
- 当读内容的文件和写内容的文件编码格式不一致时,会导致乱码问题。
//使用相同编码读取不同编码的文件内容
try(
BufferedReader brd = new BufferedReader(new FileReader("TestModule\\src\\lzm\\Test1\\1.txt"));
) {
//因为文件1.txt编码为gbk所以当你使用默认的utf编码读取时会乱码,所以写到utf文件时也会乱码
System.out.println(brd.readLine());//һ�����ǵ�һ��
} catch (Exception e) {
e.printStackTrace();
}
2.2 字符输入转换流
如何解决乱码问题呢?
- 使用字符输入转换流
- 可以提取文件(GBK)的原始字节流,字节流不会存在问题
- 根据原始字节流以指定编码转换成字符输入流,这样字符输入流中的字符就不会乱码
字符输入转换流
- InputStreamReader:可以将原始字节流按照指定编码转换成字符输入流
构造器 | 说明 |
---|---|
public InputStreamReader(InputStream is) | 可以把原始的字节流按照代码默认编码转换成字符输入流。几乎不用,与默认的FileReader一样。 |
public InputStreamReader(InputStream is,String charset) | 可以把原始的字节流按照指定编码转换成字符输入流,这样字符流中的字符就不乱码了。(重点) |
try(
//创建字符输入转换流(将字节输入流转换为字符输入流)
Reader isrd = new InputStreamReader(new FileInputStream("TestModule\\src\\lzm\\Test1\\1.txt"),"GBK");
//将字符输入流包装成缓冲字符输入流
BufferedReader brd = new BufferedReader(isrd)
){
System.out.println(brd.readLine());//一、我是第一行
}catch (Exception e){
e.printStackTrace();
}
2.3 字符输出转换流
如何控制写出去的字符编码,也就是按照指定编码写到文件中?
- 可以把字符以指定编码获取字节后再使用字节输出流写出去
- 例如:“我爱中国”.getBytes(编码格式)
- 也可以使用字符输出转换流实现
字符输出转换流
- OutputStreamWriter:可以将字节输出流按照指定编码转换成字符输出流,从而指定写出去的字符编码格式
构造器 | 说明 |
---|---|
public OutputStreamWriter(OutputStream os) | 可以把原始的字节输出流安札奥代码默认编码转换成字符输出流,几乎不用 |
public OutputStreamWriter(OutputStream os,String charset) | 可以把原始的字节输出流按照指定编码转换成字符输出流(重点) |
try(
//将字节流包装成高级缓冲字节流,再将缓冲字节流转换成字符流
Reader rdb = new InputStreamReader(new BufferedInputStream(new FileInputStream("TestModule\\src\\lzm\\Test1\\1.txt")),"GBK");
Writer wtb = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("TestModule\\src\\lzm\\Test1\\2.txt")),"utf-8");
//将字符流包装成缓冲字符流
BufferedReader brdb = new BufferedReader(rdb);
BufferedWriter bwtb = new BufferedWriter(wtb);
){
//此处因为1.txt是gbk编码,所以字节输入流指定编码然后转换成字符流
//若输出的文件是utf-8编码,可将字节输出流指定编码然后转换为字符流,也可不指定,因为默认是utf-8
String line = "";
while ((line = brdb.readLine()) != null) {
bwtb.write(line);
bwtb.newLine();
}
}catch (Exception e){
e.printStackTrace();
}
三、序列化对象
3.1 对象序列化
作用:以内存为基准,把内存中的对象存储到磁盘文件中去,称为对象序列化。
注意:
- 对象序列化必须实现序列化接口Serializable
使用的是对象字节输入流:ObjectOutputStream
构造器 | 说明 |
---|---|
public ObjectOutputStream(OutputStream out) | 把低级字节输出流包装成高级的对象字节输出流 |
方法名称 | 说明 |
public final void writeObject(Object obj) | 把对象写出去到对象序列化流的文件夹中 |
//主方法
public static void main(String[] args) {
Student s = new Student("张三",15,"火星130号");
try(
//因为我们要使用特有的writeObject方法,所以不能用父类引用
ObjectOutputStream oop = new ObjectOutputStream(new FileOutputStream("TestModule\\src\\lzm\\Test1\\obj.txt"))
){
//括号中为对象
oop.writeObject(s);
}catch (Exception e){
e.printStackTrace();
}
}
//对象类
//对象序列化需要实现序列化接口,该接口相当于提示JVM虚拟机,底层去实现对象序列化
public class Student implements Serializable {
private String name;
private int age ;
private String site;
public Student() {
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", site='" + site + '\'' +
'}';
}
public Student(String name, int age, String site) {
this.name = name;
this.age = age;
this.site = site;
}
//此处省略getter和setter方法
}
3.2 对象反序列化
作用:以内存为基准,把存储到磁盘文件中的对象数据恢复到内存中的对象,称为对象反序列化。
使用的是对象字节输入流:ObjectInputStream
构造器 | 说明 |
---|---|
public ObjectInputStream(InputStream out) | 把低级字节输入流包装成高级的对象字节输入流 |
特有方法 | 说明 |
public Object readObject() | 把存储到磁盘文件中的对象数据恢复到内存中的,返回值为对象 |
try(
//这里将刚刚序列化的对象文件地址变成反序列化的地址,将其恢复到内存
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("TestModule\\src\\lzm\\Test1\\obj.txt"))
){
//此处因为我们直到文件中存放的对象是Student所以我们直接强制转换即可
Student s = (Student) (ois.readObject());
//因为重写了toString方法
System.out.println(s);//Student{name='张三', age=15, site='火星130号'}
}catch (Exception e){
e.printStackTrace();
}
3.3 注意事项
- 对象如果要序列化,对象类必须实现Serializable接口
- transient修饰的成员变量不参与序列化
- 序列化的版本号与反序列化的版本号必须一致才不会报错(例子:当一个类的序列化版本号为1,然后序列化保存到了文件中,此时如果类中修改了一个字段,那么当你用反序列化将文件时,会报错java.io.InvalidClassException,此时需要重新序列化对象然后再反序列化)
private static final long serialVersionUID = 1;
四、打印流
4.1 PrintStream、PrintWriter
作用:打印流可以实现方便、高效的打印数据到文件中去。打印流一般指:PrintStream,PrintWrite两个类。
可以实现打印什么数据就是什么数据,例如打印整数97就是97.
PrintStream和PrintWriter的区别?
- 打印数据功能一模一样,都是使用方便,性能高效(优势)
- PrintWriter继承自字符输出流Writer,支持写字符数据出去
- PrintStream继承自字节输出流OutputStream,支持写字节数据的方法
PrintStream | |
---|---|
构造器 | 说明 |
public PrintStream(OutputStream os) | 打印流直接通向字节输出流管道 |
public PrintStream(File f) | 打印流直接通向文件对象 |
public PrintStream(String filepath) | 打印流直接通向文件路径 |
**public **void print(**任意类型 **) | 打印任意类型数据出去 |
PrintWriter | |
构造器 | 说明 |
public PrintWriter(OutputStream os) | 打印流直接通向字节输出流管道 |
public PrintWriter(Writer w) | 打印流直接通向字符输出流管道 |
public PrintWriter(File f) | 打印流直接通向文件对象 |
public PrintWriter(String filepath) | 打印流直接通向文件路径 |
方法 | 说明 |
public void print(任意类型) | 打印任意类型数据出去 |
try(
//创建打印流对象
// PrintStream ps = new PrintStream("TestModule\\src\\lzm\\Test1\\1.txt");
//打印流想要追加数据
PrintStream ps = new PrintStream(new FileOutputStream("TestModule\\src\\lzm\\Test1\\1.txt",true))
) {
//写什么打印什么
ps.println(111);
ps.println('a');
ps.println("我写什么就打印什么");
} catch (Exception e) {
e.printStackTrace();
}
4.2 输出语句的重定向
属于打印流的一种应用,可以把输出语句的打印位置改到文件中。
System.out.println中out就进行输出重定向将数据打印到控制台
//将输出语句的打印位置改为文件地址
PrintStream ps = new PrintStream("文件地址");
System.setOut(ps);
try (
//指定输出流的文件
PrintStream ps = new PrintStream(new FileOutputStream("TestModule\\src\\lzm\\Test1\\1.txt",true));
) {
System.out.println("我打印控制台");
System.out.println("我打印控制台");
System.setOut(ps);
System.out.println("我打印输出流文件中");
System.out.println("我打印输出流文件中");
} catch (Exception e) {
e.printStackTrace();
}
五、Properties
Properties属性集对象
- 其实就是一个Map集合,但是我们一般不会当集合使用,因为HashMap更好用。
Properties的核心作用
- Properties代表的是一个属性文件,可以把自己对象中的键值对信息存放到一个属性文件中去
- 属性文件:后缀为.properties结尾的文件,里面的内容都是key=value,后续做系统配置信息用。
5.1 常用API
- Properties和IO流结合使用
构造器 | 说明 |
---|---|
void load(InputStream inStream) | 从输入字节流读取属性列表(键和值对) |
void load(Reader reader) | 从输入字符流读取属性列表(键和值对) |
void store(OutputStream out,String comments) | 将此属性列表(键和值)写入此Properties表中,以适合于load(InputStream)方法的格式写入输入字节流 |
void store(Writer writer,Sting comments) | 将此属性列表(键和值)写入Properties表中,以适合使用load(Reader)方法的格式写入输出字符流 |
void Object setProperty(String key,String value) | 保存键值对(put) |
public String getProperty(String key) | 使用此属性列表中指定的键搜索属性值(get) |
public Set stringPropertyNames() | 所有键的名称的集合(keySet()) |
Properties ppt = new Properties();
try {
//将Properties键值对保存到文件
// ppt.store(new FileWriter("TestModule\\src\\lzm\\Test1\\1.txt"),"我是心得,可写可不写");
//#\u6211\u662F\u5FC3\u5F97\uFF0C\u53EF\u5199\u53EF\u4E0D\u5199
//#Fri Sep 30 08:45:14 CST 2022
//李四=5201314
//张三=123456
//王五=666666
//加载Properties键值对
ppt.load(new FileReader("TestModule\\src\\lzm\\Test1\\1.txt"));
//{李四=5201314, 张三=123456, 王五=666666}
System.out.println(ppt);
} catch (IOException e) {
e.printStackTrace();
}
六、IO框架
6.1 commons-io概述
- commons-io是apache开元基金组织提供的一组有关IO操作的类库,可以提高IO功能开发的效率
- commons-io工具包提供了很多有关io操作的类。有两个主要的类FileUtils,IOUtils
FiileUtils主要方法 | |
---|---|
String readFileToString(File file,String encoding) | 读取文件的数据,返回字符串,可以指定读时的字符编码 |
void copyFile(File srcFile,File destFile) | 复制文件(源文件对象,目的文件对象) |
void copyDirectoryToDirectory(File srcDir,File destDir) | 复制文件夹(源文件夹对象,目的文件夹对象) |
6.2 使用步骤
- 在项目中创建一个文件夹:lib
- 将commons-io-2.6.jar文件复制到lib文件夹
- 在jar文件上右击—>Add as Library —>点击OK
- 在类中导入包使用即可
try{
//复制文件
// IOUtils.copy(new FileInputStream("D:\\练习目录\\原地址\\基础班\\9.20自习练习题1.docx"),
// new FileOutputStream("D:\\练习目录\\原地址\\9.20自习练习题2.docx"));
//复制文件到指定文件夹下
// FileUtils.copyFileToDirectory(new File("D:\\练习目录\\原地址\\基础班\\9.20自习练习题1.docx"),
// new File("D:\\练习目录\\原地址\\"));
//复制文件夹(非空也能复制)
// FileUtils.copyDirectoryToDirectory(new File("D:\\练习目录\\原地址"),new File("D:\\练习目录\\目的地址\\"));
//删除文件夹(非空文件夹也能删除)
// FileUtils.deleteDirectory(new File("D:\\练习目录\\目的地址"));
//JDK新增功能
Files.copy(Path.of("D:\\练习目录\\原地址\\基础班\\9.20自习练习题1.docx"),new FileOutputStream("D:\\练习目录\\原地址\\基础班\\9.20自习练习题2.docx"));
}catch (Exception e){
e.printStackTrace();
}
七、练习
7.1 点名器
有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要齐通过程序实现随机点名器
//有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要齐通过程序实现随机点名器
try(
//建立一个缓冲字符输入流管道与源文件接通
BufferedReader brd = new BufferedReader(new FileReader("TestModule\\src\\lzm\\Test1\\1.txt"));
) {
//line临时存储一行字符串
String line = "";
//创建一个List集合用来存放每一行的名字
List<String> list = new ArrayList();
//遍历并存放到集合中
while ((line = brd.readLine()) != null){
list.add(line);
}
//随机数生成,生成的最大值是集合元素的个数
Random rd = new Random();
int num = rd.nextInt(list.size());
//打印集合的随机数位置的名称
System.out.println(list.get(num));
}catch (Exception e){
e.printStackTrace();
}
7.2 点名器升级版
有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要求通过程序实现随机点名器。第三次必定是张三同学
//有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要求通过程序实现随机点名器。第三次必定是张三同学
try(
//建立一个缓冲字符输入流管道与源文件接通
BufferedReader brd = new BufferedReader(new FileReader("TestModule\\src\\lzm\\Test1\\1.txt"));
) {
//line临时存储一行字符串
String line = "";
//创建一个List集合用来存放每一行的名字
List<String> list = new ArrayList();
//遍历并存放到集合中
while ((line = brd.readLine()) != null){
list.add(line);
}
//随机数生成,生成的最大值是集合元素的个数
Random rd = new Random();
//计数,随机索引位置
int count = 1,index;
while(count<20){
//当第三次点名时,就去寻找张三所在的索引位置并赋值给index
if (count%3==0){
index = list.indexOf("张三");
}else{
index = rd.nextInt(list.size());
}
//打印集合的随机数位置的名称
System.out.println(list.get(index));
count++;
}
}catch (Exception e){
e.printStackTrace();
}
7.3 登录案例
写一个登录小案例
- 将正确的用户名和密码手动保存在本地userinfo.txt文件中。
- 保存为:username=zhangsan&password=123
- 让用户键盘录入用户名和密码
- 比较用户录入的和正确的用户名密码是否一致
- 如果一致则打印登陆成功
- 如果不一致则打印登陆失败
try (
//建立一个缓冲字符输入流管道与源文件接通
BufferedReader brd = new BufferedReader(new FileReader("TestModule\\src\\lzm\\Test1\\1.txt"));
) {
//将文件中每一行用户名和密码存入集合中
String line = "";
List list = new ArrayList();
while ((line = brd.readLine()) != null){
list.add(line);
}
Scanner sc = new Scanner(System.in);
System.out.print("用户名:");
String username = sc.next();
System.out.print("密码:");
String password = sc.next();
boolean flag = false;
//在输入的用户名和密码中添加共同的标识(username=用户名&password=密码)
String login = "username=" +username + "&password=" + password;
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals(login)) {
flag = true;
break;
}
}
if (flag == false){
System.out.println("登录失败");
}else{
System.out.println("登录成功");
}
} catch (Exception e) {
e.printStackTrace();
}
7.4 自动登录案例
①将正确的用户名和密码手动保存在本地的userinfo.txt文件中。
②保存格式为:username=zhangsan&password=123
③让用户键盘录入用户名和密码
④比较用户录入的和正确的用户名密码是否一致
⑤如果一致则打印登陆成功,并将用户录入的数据保存到本地cookie.txt文件中。
保存格式为:username=zhangsan
password=123
⑤如果不一致则打印登陆失败
再次运行时,则从本地cookie.txt自动登录