第二十三天 IO-打印流&序列化流&Properties&CommonsIO&流总结【悟空教程】

第二十三天 IO-打印流&序列化流&Properties&CommonsIO&流总结【悟空教程】

第23天 IO

第1章 流的复习总结

第2章 打印流

2.1 打印流的概述

打印流添加输出数据的功能,使它们能够方便地打印各种数据值表示形式.

打印流根据流的分类:

  • 字节打印流 PrintStream
  • 字符打印流 PrintWriter
  • 方法:

void print(String str): 输出任意类型的数据,

void println(String str): 输出任意类型的数据,自动写入换行操作

/*

* 需求:把指定的数据,写入到printFile.txt文件中

*

* 分析:

* 1,创建流

* 2,写数据

* 3,关闭流

*/

public class PrintWriterDemo {

public static void main(String[] args) throws IOException {

//创建流

//PrintWriter out = new PrintWriter(new FileWriter("printFile.txt"));

PrintWriter out = new PrintWriter("printFile.txt");

//2,写数据

for (int i=0; i<5; i++) {

out.println("helloWorld");

}

//3,关闭流

out.close();

}

}

2.2 打印流完成数据自动刷新

可以通过构造方法,完成文件数据的自动刷新功能,自动刷新适用部分方法,如println方法,平常使用的write方法不提供自动刷新

  • 构造方法:
    • 开启文件自动刷新写入功能

public PrintWriter(OutputStream out, boolean autoFlush)

public PrintWriter(Writer out, boolean autoFlush)

/*

* 分析:

* 1,创建流

* 2,写数据

*/

public class PrintWriterDemo2 {

public static void main(String[] args) throws IOException {

//创建流

PrintWriter out = new PrintWriter(new FileWriter("printFile.txt"), true);

//2,写数据

for (int i=0; i<5; i++) {

out.println("helloWorld");

}

//3,关闭流

out.close();

}

}

第3章 序列化流

3.1 序列化流概念

序列化流可以将对象进行序列化和反序列化。

用于从流中读取对象的操作流 ObjectInputStream称为反序列化流

用于向流中写入对象的操作流 ObjectOutputStream称为序列化流

注意:对象序列化时,对象的数据类型定义时一定要实现Serializable接口,从而实现可持久化。

3.2 序列化流

将一个对象以对象的形式存储到文件中。

ObjectOutputStream writeObject() 写出对象

public class ObjectStreamDemo {

public static void main(String[] args) throws IOException, ClassNotFoundException {

/*

* 将一个对象存储到持久化(硬盘)的设备上。

*/

writeObj();//对象的序列化。

}

public static void writeObj() throws IOException {

//1,明确存储对象的文件。

FileOutputStream fos = new FileOutputStream("aa\\obj.txt");

//2,给操作文件对象加入写入对象功能。

ObjectOutputStream oos = new ObjectOutputStream(fos);

//3,调用了写入对象的方法。

oos.writeObject(new Person("wangcai",20));

//关闭资源。

oos.close();

}

}

3.3 对象反序列化流

当把一个对象持久化存储起来之后,需要使用反序列化技术获取存储起来的对象

ObjectInputStream readObject() 读取对象

使用此ObjectInputStream对象就可以完成反序列化动作

public class ObjectStreamDemo {

public static void main(String[] args) throws IOException, ClassNotFoundException {

readObj();//对象的反序列化。

}

public static void readObj() throws IOException, ClassNotFoundException {

//1,定义流对象关联存储了对象文件。

FileInputStream fis = new FileInputStream("aa\\obj.txt");

//2,建立用于读取对象的功能对象。

ObjectInputStream ois = new ObjectInputStream(fis);

Person obj = (Person)ois.readObject();

System.out.println(obj.toString());

}

}

3.4 将用户信息存储到文件中与读取文件用户

3.4.1 用户实体类

import java.io.Serializable;

/*

*

* Serializable 接口

* 作用: 想要序列化,就必须实现这个 接口. 不用重写任何方法. 只是标记 一下.

*/

public class User implements Serializable{

String name ;

String psw ;

int age;

public User() {

super();

}

public User(String name, String psw) {

super();

this.name = name;

this.psw = psw;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getPsw() {

return psw;

}

public void setPsw(String psw) {

this.psw = psw;

}

@Override

public String toString() {

return "User [name=" + name + ", psw=" + psw + "]";

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + ((name == null) ? 0 : name.hashCode());

result = prime * result + ((psw == null) ? 0 : psw.hashCode());

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

User other = (User) obj;

if (name == null) {

if (other.name != null)

return false;

} else if (!name.equals(other.name))

return false;

if (psw == null) {

if (other.psw != null)

return false;

} else if (!psw.equals(other.psw))

return false;

return true;

}

}

3.4.2 序列化存储

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectOutputStream;

/*

* 序列化和反序列化

* 序列化: 从内存保存到硬盘

* 反序列化 : 从硬盘读取到内存 .

* 操作的数据都是对象 . 都是Object

*

*/

public class Demo {

public static void main(String[] args) throws IOException {

// 创建序列化 流对象

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.txt"));

User user = new User("老王", "laowang");//java.io.NotSerializableException: cn.javahelp_02.User

oos.writeObject(user);

oos.close();

}

}

3.4.3 反序列化读取

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.ObjectInputStream;

/*

* 读取序列化的信息, 反序列化.

*/

public class Demo2 {

public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {

// 创建反序列化 流 .

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.txt"));

Object obj = ois.readObject();

System.out.println(obj);

if (obj instanceof User) {

User u = (User) obj;

String name = u.getName();

System.out.println(name);

}

ois.close();

}

}

3.4.4 在创建对象读取(报读取文件结尾异常)思考:不知道里面存储多少元素,但是读到结尾就报异常,这样怎么办。

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.ObjectInputStream;

/*

* 读取序列化的信息, 反序列化.

*/

public class Demo2 {

public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {

// 创建反序列化 流 .

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.txt"));

Object obj = ois.readObject();

System.out.println(obj);

if (obj instanceof User) {

User u = (User) obj;

String name = u.getName();

System.out.println(name);

}

Object obj2 = ois.readObject(); //End Of File Exception 读取文件结尾异常

System.out.println(obj2);

ois.close();

}

}

3.4.5 集合序列化解决不知道存储元素数问题

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.util.ArrayList;

/*

* 把集合序列化.

*/

public class Demo3 {

public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {

ArrayList<User > arrayList = new ArrayList<>();

User user = new User("金莲","jinlian");

User user2 = new User("西门","daguanren");

User user3 = new User("大郎","cuibing");

arrayList.add(user);

arrayList.add(user2);

arrayList.add(user3);

//创建 序列化流

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user2.txt"));

oos.writeObject(arrayList);

oos.close();

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user2.txt"));

Object readObject = ois.readObject();

System.out.println(readObject);

// 强制 转换 在遍历 readObject --> ArrayList<User>

ArrayList<User> userList = (ArrayList<User>) readObject;

for (User u : userList) {

System.out.println(u.getName() +" -- "+ u.getPsw());

}

}

}

3.5 序列化接口

当一个对象要能被序列化,这个对象所属的类必须实现Serializable接口。否则会发生异常NotSerializableException异常。

同时当反序列化对象时,如果对象所属的class文件在序列化之后进行了修改,那么进行反序列化也会发生异常InvalidClassException。发生这个异常的原因如下:

  • 该类的序列版本号与从流中读取的类描述符的版本号不匹配
  • 该类包含未知数据类型
  • 该类没有可访问的无参数构造方法

Serializable标记接口。该接口给需要序列化的类,提供了一个序列版本号。serialVersionUID. 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

标记作用,当年的类没变,虽然添加了属性,但是可以

public class Person implements Serializable {

/*

* serialVersionUID = 1L

* 只是一个对象的标记. 防止 你的类升级了, 对象 与类的信息 不一致.

*/

//给类显示声明一个序列版本号。

private static final long serialVersionUID = 1L;

private String name;

private int age;

public Person() {

super();

}

public Person(String name, int age) {

super();

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 "Person [name=" + name + ", age=" + age + "]";

}

}

3.6 瞬态关键字transient

当一个类的对象需要被序列化时,某些属性不需要被序列化,这时不需要序列化的属性可以使用关键字transient修饰。只要被transient修饰了,序列化时这个属性就不会琲序列化了。

同时静态修饰也不会被序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。

public class Person implements Serializable {

/*

* 给类显示声明一个序列版本号。

*

*只要被transient修饰了,序列化时这个属性就不会琲序列化了。不想保存

*/

private static final long serialVersionUID = 1L;

private static String name;

private transient/*瞬态*/ int age;

public Person() {

super();

}

public Person(String name, int age) {

super();

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 "Person [name=" + name + ", age=" + age + "]";

}

}

第4章 Properties

4.1 概念及常用方法

Properties是双列集合的一种,是Hashtable的子类。属性集:key---value

该类没有泛型,通过setProperty / getProperty/ stringPropertyNames完成针对字符串的操作。

它是一个可以持久化的属性集。键值可以存储到集合中,也可以存储到持久化的设备(硬盘、U盘、光盘)上。包含IO相关方法:

  • load(InputStream) 把指定流所对应的文件中的数据,读取出来,保存到Properties集合中
  • load(Reader)
  • store(OutputStream,commonts)把集合中的数据,保存到指定的流所对应的文件中,参数commonts代表对描述信息
  • store(Writer,comments);

注意:使用字符流FileReader就可以完成文件中文的读取操作了

4.2 使用方法举例

/*

* Properties集合,它是唯一一个能与IO流交互的集合

*/

public class PropertiesDemo01 {

public static void main(String[] args) {

//创建集合对象

Properties prop = new Properties();

//添加元素到集合

//prop.put(key, value); //setProperty底层调用put方法

prop.setProperty("周迅", "张学友");

prop.setProperty("李小璐", "贾乃亮");

prop.setProperty("杨幂", "刘恺威");

//System.out.println(prop);//测试的使用

//遍历集合

Set<String> keys = prop.stringPropertyNames();

for (String key : keys) {

//通过键 找值

//prop.get(key)

String value = prop.getProperty(key);

System.out.println(key+"==" +value);

}

}

}

4.3 将配置文件中的数据存储到文件中

/**

* 需求:使用Properties集合,完成把集合内容存储到IO流所对应文件中的操作

*

* 分析:

* 1,创建Properties集合

* 2,添加元素到集合

* 3,创建流

* 4,通过store方法把集合中的数据存储到流所对应的文件中

* 5,关闭流

*/

public class PropertiesDemo02 {

public static void main(String[] args) throws IOException {

//1,创建Properties集合

Properties prop = new Properties();

//2,添加元素到集合

prop.setProperty("周迅", "张学友");

prop.setProperty("李小璐", "贾乃亮");

prop.setProperty("杨幂", "刘恺威");

//3,创建流

FileWriter out = new FileWriter("prop.properties");

//4,把集合中的数据存储到流所对应的文件中

prop.store(out, "save data");

//5,关闭流

out.close();

}

}

4.4 读取配置文件中的数据,同时更新数据,并保存

/*

* 需求:从属性集文件prop.properties 中取出数据,保存到集合中

* 分析:

* 1,创建集合

* 2,创建流对象

* 3,把流所对应文件中的数据 读取到集合中

* load(InputStream) 把指定流所对应的文件中的数据,读取出来,保存到Propertie集合中

load(Reader)

* 4,关闭流

* 5,显示集合中的数据

*/

public class PropertiesDemo03 {

public static void main(String[] args) throws IOException {

//1,创建集合

Properties prop = new Properties();

//2,创建流对象

FileInputStream in = new FileInputStream("prop.properties");

//FileReader in = new FileReader("prop.properties");

//3,把流所对应文件中的数据 读取到集合中

prop.load(in);

//4,关闭流

in.close();

//5,显示集合中的数据

System.out.println(prop);

}

}

第5章 CommonsIO

5.1 CommonsIO概述

除JDK开发者与我们使用JDK的人员以外,其他第三方组织或个人提供了大量开源免费的类库,供我们使用。Apache组织。CommonsIO是非常优秀的IO操作库,提供了大量简洁的IO操作方法。

5.2 使用方式(导入jar包)

1.解压commonsio压缩包

2.在eclipse项目中创建lib文件夹,并将commons-io.jar拷贝到lib文件夹

3.右键点击commons-io.jar,Build Path→Add to Build Path

4.完成

5.3 FilenameUtils

这个工具类是用来处理文件名的,他可以轻松解决不同操作系统文件名称规范不同的问题

  • 常用方法:

getExtension(String path):获取文件的扩展名;

getName():获取文件名;

isExtension(String fileName,String ext):判断fileName是否是ext后缀名;

import org.apache.commons.io.FilenameUtils;

/*

*

* Commons-IO 测试.

*

* FileNameUtils

*/

public class Demo {

public static void main(String[] args) {

String extension = FilenameUtils.getExtension("aa.txt");

System.out.println(extension);

boolean extension2 = FilenameUtils.isExtension("aa.png", "PNG");

System.out.println(extension2);

}

}

5.4 FileUtils

提供文件操作(移动文件,读取文件,检查文件是否存在等等)的方法。

  • 常用方法:

readFileToString(File file):读取文件内容,并返回一个String;

writeStringToFile(File file,String content):将内容content写入到file中;

copyDirectoryToDirectory(File srcDir,File destDir);文件夹复制 (带外层文件夹)

copyDirectory(File srcDir,File destDir);文件夹复制(不带外层文件夹)

copyFileToFile(File srcFile,File destFile);文件夹复制

/*

* 完成文件、文件夹的复制

*/

public class CommonsIODemo02 {

public static void main(String[] args) throws IOException {

//通过Commons-IO完成了文件复制的功能

FileUtils.copyFile(new File("D:\\test.avi"), new File("D:\\copy.avi"));

//通过Commons-IO完成了文件夹复制的功能

//D:\基础班 复制到 C:\\abc文件夹下

FileUtils.copyDirectoryToDirectory(new File("D:\\a"), new File("C:\\a"));

}

}

第6章 IO综合案例---文件管理器

6.1 IO综合案例---文件管理器

6.1.1 案例介绍与演示

此程序在DOS下实现:指定关键字检索文件;指定后缀名检索文件;复制文件/目录;

6.1.2 案例分析

1.基本功能1与基本功能2均为指定文件夹后的文件夹内容遍历

2.基本功能3可使用自定义方法,也可以使用第三方发Java包。

3.附加功能,请在功能1中统计出包含指定关键字的文件夹与文件的个数

6.1.3 案例实现

import java.io.File;

import java.io.IOException;

import java.util.Scanner;

import org.apache.commons.io.FileUtils;

/*

* 文件管理器

*

* 分析: 按照文档功能 实现

* 实现 : 1. 页面 操作项

*

* 2. 实现不同选项中的功能

*/

public class Demo {

static Scanner sc = new Scanner(System.in);

public static void main(String[] args) {

while (true) {

System.out.println("文件管理器_控制台版");

System.out.print("(1)指定关键字检索文件\t");

System.out.print("(2)指定后缀名检索文件\t");

System.out.print("(3)复制文件/目录\t");

System.out.println("(4)退出");

System.out.println("请选择操作项: ");

String opt = sc.nextLine();

switch (opt) {

case "1": // 指定关键字检索文件\t

System.out.println("文件检索,请输入目录....");

// 输入目录

String dirPath = sc.nextLine(); // 目录的路径

// 创建 File 对象

File srcDir = new File(dirPath);

if (!srcDir.exists()) {

System.out.println("对不起 , 目录并不存在");

break;

}

// 简单的判断 ,是文件 就跳出

if (srcDir.isFile()) {

System.out.println("对不起 , 请输入目录, 不要输入文件名称");

break;

}

System.out.println("请输入关键字...");

// 输入关键字

String key = sc.nextLine();

findFileByKey(srcDir, key);

break;

case "2": // 指定后缀名 检索文件

System.out.println("文件检索,请输入目录....");

// 输入目录

String dir2 = sc.nextLine();

System.out.println("请输入后缀名...");

// 输入关键字

String ext = sc.nextLine();

findFileByExt(dir2, ext); // 请参照 1 实现

break;

case "3":

System.out.println("请输入源文件/ 目录");

String src = sc.nextLine();

System.out.println("请输入目标位置");

String dest = sc.nextLine();

// 把路径变成File 对象

File srcFile = new File(src);

// 判断

if (!srcFile.exists()) {

System.out.println("输入有源 路径有误 !!!");

break;

}

File destFile = new File(dest);

copyFile(srcFile, destFile);

break;

case "4":

System.out.println("退出");

System.exit(0);

break;

default:

System.out.println("操作输入有误!!!");

break;

}

}

}

private static void copyFile(File srcFile, File destFile) {

// 判断 . src 是文件

if (srcFile.isFile()) {

try {

FileUtils.copyFile(srcFile, destFile);

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

} else {

// src 是文件夹

try {

FileUtils.copyDirectoryToDirectory(srcFile, destFile);

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

private static void findFileByExt(String dir2, String ext) {

System.out.println("扩展名 ....找到了");

}

private static void findFileByKey(File dir, String key) {

System.out.println("关键字.... 找到了");

// 遍历 文件夹

File[] listFiles = dir.listFiles();

for (File file : listFiles) { // file 是 dir下一级的所有 文件或者文件夹.

// 如果 文件 , 是否包含关键字.

if (file.isFile()) {

if (file.getName().contains(key)) {

// 包含 关键字 ,输出绝对路径

System.out.println(file.getAbsolutePath());

}

} else {

// 如果文件夹 , 调用自己 .

findFileByKey(file, key); // 注意: file 是 你要遍历的文件夹了.

}

}

}

}

6.2 键盘录入3个学生信息(学号,姓名,年龄,居住城市)存入集合。然后遍历集合把每一个学生信息存入文本文件(每一个学生信息为一行,自己定义分割标记)

  • 定义学生类

public class Student {

//学号

private String id;

//姓名

private String name;

//年龄

private String age;

//居住地

private String address;

public Student() {

}

public Student(String id, String name, String age, String address) {

this.id = id;

this.name = name;

this.age = age;

this.address = address;

}

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAge() {

return age;

}

public void setAge(String age) {

this.age = age;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

}

public class Demo01ArrayListToFile {

public static void main(String[] args) throws IOException {

//创建集合对象

ArrayList<Student> list = new ArrayList<Student>();

//写方法实现键盘录入学生信息,并把学生对象作为元素添加到集合

addStudent(list);

addStudent(list);

addStudent(list);

//创建输出缓冲流对象

BufferedWriter bw = new BufferedWriter(new FileWriter("array.txt"));

//遍历集合,得到每一个学生信息,并把学生信息按照一定的格式写入文本文件

for(int x=0; x<list.size(); x++) {

Student s = list.get(x);

//heima001,向问天,30,北京

StringBuilder builder = new StringBuilder();

builder.append(s.getId()).append(",").append(s.getName()).append(",").append(s.getAge()).append(",").append(s.getAddress());

bw.write(builder.toString());

bw.newLine();

bw.flush();

}

//释放资源

bw.close();

}

//添加学生

public static void addStudent(ArrayList<Student> list) {

//创建键盘录入对象

Scanner sc = new Scanner(System.in);

//为了让id能够被访问到,我们就把id定义在了循环的外面

String id;

//为了让代码能够回到这里,用循环

while(true) {

System.out.println("请输入学生学号:");

id = sc.nextLine();

//判断学号有没有被人占用

//定义标记

boolean flag = false;

//遍历集合,得到每一个学生

for(int x=0; x<list.size(); x++) {

Student s = list.get(x);

//获取该学生的学号,和键盘录入的学号进行比较

if(s.getId().equals(id)) {

flag = true; //说明学号被占用了

break;

}

}

if(flag) {

System.out.println("你输入的学号已经被占用,请重新输入");

}else {

break; //结束循环

}

}

System.out.println("请输入学生姓名:");

String name = sc.nextLine();

System.out.println("请输入学生年龄:");

String age = sc.nextLine();

System.out.println("请输入学生居住地:");

String address = sc.nextLine();

//创建学生对象

Student s = new Student();

s.setId(id);

s.setName(name);

s.setAge(age);

s.setAddress(address);

//把学生对象作为元素添加到集合

list.add(s);

//给出提示

System.out.println("添加学生成功");

}

}

6.3 把上一题的文本文件中的学生信息读取出来存储到集合中,然后遍历集合,在控制台输出

public class Demo02FileToArrayList {

public static void main(String[] args) throws IOException {

//创建输入缓冲流对象

BufferedReader br = new BufferedReader(new FileReader("array.txt"));

//创建集合对象

ArrayList<Student> list = new ArrayList<Student>();

//读取文件数据,并把数据按照一定的格式进行分割赋值给学生对象,然后把学生对象作为元素存储到集合

String line;

while((line=br.readLine())!=null) {

//分割字符串

String[] strArray = line.split(",");

//创建学生对象并赋值

Student s = new Student();

s.setId(strArray[0]);

s.setName(strArray[1]);

s.setAge(strArray[2]);

s.setAddress(strArray[3]);

//把学生对象作为元素存储到集合

list.add(s);

}

//释放资源

br.close();

//遍历集合

System.out.println("学号\t\t姓名\t年龄\t居住地");

for(int x=0; x<list.size(); x++) {

Student s = list.get(x);

System.out.println(s.getId()+"\t"+s.getName()+"\t"+s.getAge()+"\t"+s.getAddress());

}

}

}

6.4 学生管理系统IO版

  • 定义学生类

public class Student {

//学号

private String id;

//姓名

private String name;

//年龄

private String age;

//居住地

private String address;

public Student() {

}

public Student(String id, String name, String age, String address) {

this.id = id;

this.name = name;

this.age = age;

this.address = address;

}

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAge() {

return age;

}

public void setAge(String age) {

this.age = age;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

}

  • 学生管理系统IO版本代码实现

public class StudentManager {

public static void main(String[] args) throws IOException{

//定义文件路径

String fileName = "students.txt";

//为了让程序能够回到这里来,我们使用循环

while(true) {

//这是学生管理系统的主界面

System.out.println("--------欢迎来到学生管理系统--------");

System.out.println("1 查看所有学生");

System.out.println("2 添加学生");

System.out.println("3 删除学生");

System.out.println("4 修改学生");

System.out.println("5 退出");

System.out.println("请输入你的选择:");

//创建键盘录入对象

Scanner sc = new Scanner(System.in);

String choiceString = sc.nextLine();

//用switch语句实现选择

switch(choiceString) {

case "1":

//查看所有学生

findAllStudent(fileName);

break;

case "2":

//添加学生

addStudent(fileName);

break;

case "3":

//删除学生

deleteStudent(fileName);

break;

case "4":

//修改学生

updateStudent(fileName);

break;

case "5":

default:

System.out.println("谢谢你的使用");

System.exit(0); //JVM退出

break;

}

}

}

//从文件中读数据到集合

public static void readData(String fileName,ArrayList<Student> list) throws IOException {

//创建输入缓冲流对象

BufferedReader br = new BufferedReader(new FileReader(fileName));

String line;

while((line=br.readLine())!=null) {

String[] datas = line.split(",");

Student s = new Student();

s.setId(datas[0]);

s.setName(datas[1]);

s.setAge(datas[2]);

s.setAddress(datas[3]);

list.add(s);

}

br.close();

}

//把集合中的数据写入文件

public static void writeData(String fileName,ArrayList<Student> list) throws IOException {

//创建输出缓冲流对象

BufferedWriter bw = new BufferedWriter(new FileWriter(fileName));

for(int x=0; x<list.size(); x++) {

Student s = list.get(x);

StringBuilder sb = new StringBuilder();

sb.append(s.getId()).append(",").append(s.getName()).append(",").append(s.getAge()).append(",").append(s.getAddress());

bw.write(sb.toString());

bw.newLine();

bw.flush();

}

bw.close();

}

//修改学生

public static void updateStudent(String fileName) throws IOException {

//创建集合对象

ArrayList<Student> list = new ArrayList<Student>();

//从文件中把数据读取到集合中

readData(fileName, list);

//修改学生的思路:键盘录入一个学号,到集合中去查找,看是否有学生使用的是该学号,如果有就修改该学生

//创建键盘录入对象

Scanner sc = new Scanner(System.in);

System.out.println("请输入你要修改的学生的学号:");

String id = sc.nextLine();

//定义一个索引

int index = -1;

//遍历集合

for(int x=0; x<list.size(); x++) {

//获取每一个学生对象

Student s = list.get(x);

//拿学生对象的学号和键盘录入的学号进行比较

if(s.getId().equals(id)) {

index = x;

break;

}

}

if(index == -1) {

System.out.println("不好意思,你要修改的学号对应的学生信息不存在,请回去重新你的选择");

}else {

System.out.println("请输入学生新姓名:");

String name = sc.nextLine();

System.out.println("请输入学生新年龄:");

String age = sc.nextLine();

System.out.println("请输入学生新居住地:");

String address = sc.nextLine();

//创建学生对象

Student s = new Student();

s.setId(id);

s.setName(name);

s.setAge(age);

s.setAddress(address);

//修改集合中的学生对象

list.set(index, s);

//把集合中的数据重新写回到文件

writeData(fileName, list);

//给出提示

System.out.println("修改学生成功");

}

}

//删除学生

public static void deleteStudent(String fileName) throws IOException {

//创建集合对象

ArrayList<Student> list = new ArrayList<Student>();

//从文件中把数据读取到集合中

readData(fileName, list);

//删除学生的思路:键盘录入一个学号,到集合中去查找,看是否有学生使用的是该学号,如果有就删除该学生

//创建键盘录入对象

Scanner sc = new Scanner(System.in);

System.out.println("请输入你要删除的学生的学号:");

String id = sc.nextLine();

//我们必须给出学号不存在的时候的提示

//定义一个索引

int index = -1;

//遍历集合

for(int x=0; x<list.size(); x++) {

//获取到每一个学生对象

Student s = list.get(x);

//拿这个学生对象的学号和键盘录入的学号进行比较

if(s.getId().equals(id)) {

index = x;

break;

}

}

if(index == -1) {

System.out.println("不好意思,你要删除的学号对应的学生信息不存在,请回去重新你的选择");

}else {

list.remove(index);

//把集合中的数据重新写回到文件

writeData(fileName, list);

System.out.println("删除学生成功");

}

}

//添加学生

public static void addStudent(String fileName) throws IOException {

//创建集合对象

ArrayList<Student> list = new ArrayList<Student>();

//从文件中把数据读取到集合中

readData(fileName, list);

//创建键盘录入对象

Scanner sc = new Scanner(System.in);

//为了让id能够被访问到,我们就把id定义在了循环的外面

String id;

//为了让代码能够回到这里,用循环

while(true) {

System.out.println("请输入学生学号:");

id = sc.nextLine();

//判断学号有没有被人占用

//定义标记

boolean flag = false;

//遍历集合,得到每一个学生

for(int x=0; x<list.size(); x++) {

Student s = list.get(x);

//获取该学生的学号,和键盘录入的学号进行比较

if(s.getId().equals(id)) {

flag = true; //说明学号被占用了

break;

}

}

if(flag) {

System.out.println("你输入的学号已经被占用,请重新输入");

}else {

break; //结束循环

}

}

System.out.println("请输入学生姓名:");

String name = sc.nextLine();

System.out.println("请输入学生年龄:");

String age = sc.nextLine();

System.out.println("请输入学生居住地:");

String address = sc.nextLine();

//创建学生对象

Student s = new Student();

s.setId(id);

s.setName(name);

s.setAge(age);

s.setAddress(address);

//把学生对象作为元素添加到集合

list.add(s);

//把集合中的数据重新写回到文件

writeData(fileName, list);

//给出提示

System.out.println("添加学生成功");

}

//查看所有学生

public static void findAllStudent(String fileName) throws IOException {

//创建集合对象

ArrayList<Student> list = new ArrayList<Student>();

//从文件中把数据读取到集合中

readData(fileName, list);

//首先来判断集合中是否有数据,如果没有数据,就给出提示,并让该方法不继续往下执行

if(list.size() == 0) {

System.out.println("不好意思,目前没有学生信息可供查询,请回去重新选择你的操作");

return;

}

//\t 其实就是一个tab键的位置

System.out.println("学号\t\t姓名\t年龄\t居住地");

for(int x=0; x<list.size(); x++) {

Student s = list.get(x);

System.out.println(s.getId()+"\t"+s.getName()+"\t"+s.getAge()+"\t"+s.getAddress());

}

}

}

第7章 IO总结

  • 字节流
    • 字节输入流 InputStream
      • FileInputStream 操作文件的字节输入流
      • BufferedInputStream高效的字节输入流
      • ObjectInputStream 反序列化流
    • 字节输出流 OutputStram
      • FileOutputStream 操作文件的字节输出流
      • BufferedOutputStream 高效的字节输出流
      • ObjectOuputStream 序列化流
      • PrintStream 字节打印流
  • 字符流
    • 字符输入流 Reader
      • FileReader 操作文件的字符输入流
      • BufferedReader 高效的字符输入流
      • InputStreamReader 输入操作的转换流(把字节流封装成字符流)
    • 字符输出流 Writer
      • FileWriter 操作文件的字符输出流
      • BufferedWriter 高效的字符输出流
      • OutputStreamWriter 输出操作的转换流(把字节流封装成字符流)
      • PrintWriter 字符打印流
  • 方法:
    • 读数据方法:
      • read() 一次读一个字节或字符的方法
      • read(byte[] char[]) 一次读一个数组数据的方法
      • readLine() 一次读一行字符串的方法(BufferedReader类特有方法)
      • readObject() 从流中读取对象(ObjectInputStream特有方法)
    • 写数据方法:
      • write(int) 一次写一个字节或字符到文件中
      • write(byte[] char[]) 一次写一个数组数据到文件中
      • write(String) 一次写一个字符串内容到文件中
      • writeObject(Object ) 写对象到流中(ObjectOutputStream类特有方法)
      • newLine() 写一个换行符号(BufferedWriter类特有方法)
  • 向文件中写入数据的过程
    • 1.创建输出流对象
    • 2.写数据到文件
    • 3.关闭输出流
  • 从文件中读数据的过程
    • 1.创建输入流对象
    • 2.从文件中读数据
    • 3.关闭输入流
  • 文件复制的过程
    • 1.创建输入流(数据源)
    • 2.创建输出流(目的地)
    • 3.从输入流中读数据
    • 4.通过输出流,把数据写入目的地
    • 5.关闭流
  • File类
    • 方法
      • 获取文件名称 getName()
      • 获取文件绝对路径 getAbsolutePath()
      • 获取文件大小 length()
      • 获取当前文件夹中所有File对象 File[] listFiles()
      • 判断是否为文件 isFile()
      • 判断是否为文件夹 isDirectory()
      • 创建文件夹 mkdir() mkdirs()
      • 创建文件 createNewFile()
  • 异常
    • try..catch…finally捕获
    • throws 声明异常
    • throw 抛出异常对象
  • 异常的分类
    • 编译期异常 Exception
      • 运行期异常 RuntimeException
  • 注意:
    • 编译期异常,必须处理,不然无法编译通过
    • 运行期异常,程序运行过程中,产生的异常信息
  • Properties:Map集合的一种,它是Hashtable集合的子集合,它键与值都是String类型,它是唯一能与IO流结合使用的集合
    • 方法
      • load( InputStream in ) 从流所对应的文件中,读数据到集合中
      • load( Reader in ) 从流所对应的文件中,读数据到集合中
      • store( OutputStream out , String message ) 把集合中的数据,写入到流所对应的文件中
      • store( Writer out , String message) 把集合中的数据,写入到流所对应的文件中
  • 实现文件内容的自动追加
    • 构造方法
      • FileOutputStream(File file, boolean append)
      • FileOutputStream(String fileName, boolean append)
      • FileWriter(File, boolean append)
      • FileWriter(String fileName, boolean append)
  • 实现文件内容的自动刷新
    • 构造方法
      • PrintWriter(OutputStream out, boolean autoFlush)
      • PrintWriter(Writer out, boolean autoFlush)
  • Commons-IO
    • 方法
      • readFileToString(File file):读取文件内容,并返回一个String;
      • writeStringToFile(File file,String content):将内容content写入到file中;
      • copyDirectoryToDirectory(File srcDir,File destDir);文件夹复制
      • copyFileToDirectory (File srcFile,File destFile);文件复制

第8章 本日自习作业:

8.1 知识点相关题

8.1.1 打印流:PrintStream和PrintWriter

题目:

1) 定义类Test3,定义main()方法,按以下要求编写代码:

  • 构造一个PrintStream字节打印流,指向某个文件;
  • 使用out.println方法向文件中打印一句话;
  • 关闭流;
  • 运行程序,查看新文件;
  • 将打印方式改为:字符打印流 PrintWriter;

8.1.2 字对象的序列化和反序列化

题目:

定义类Student,属性 String name,int age提供get set方法, 满参构造方法,toString(),

根据第一题中的学生信息:

实现对象的序列化将60分以下的学生对象写到文件student.txt中

实现对象的反序列化,读取student.txt文件,获取学生对象信息.打印在控制台.

1:使用带刷新的打印流操作,完成文本打印到控制台

2:完成对象序列化到任意文件,修改代码中该类的某个属性访问权限,由私有化改为公共修饰,再从文件中读取该对象,打印对象内容

3:使用properties的方法将集合内容存储到文件中并重新读取

4:使用CommonsIO完成文件三个以上方法的调用

5:复习所有IO类,以普通输入输出流为主

6:完成课上最后综合案例case2和附加功能

7:查漏补缺面向对象、集合、IO相关知识点

8.2 代码题

8.2.1 通过CommonsIO完成文件和文件夹的复制.

答案:

public class copy {

    public static void main(String[] args) throws IOException {

//封装路径

File file1 = new File("C:\\a.txt");

File file2 = new File("D:\\a.txt");

//复制文件

FileUtils.copyFile(file1,file2);

//复制文件夹

FileUtils.copyDirectoryToDirectory(new File("C:\\文件夹"), new File("D:\\文件夹"));

    }

}

原文发布于微信公众号 - Java帮帮(javahelp)

原文发表时间:2018-06-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏LanceToBigData

JavaWeb(四)EL表达式

前言   前面详细的说明了什么是JSP和它的一些元素,这篇给大家介绍一下的是EL表达式。 用EL表达式,能更好的使用JSP中的各种内置对象和作用域。   楼主...

36170
来自专栏SDNLAB

【一课专栏】解构2 - 明察YangInstanceIdentifier

屈原《离骚》中云:“路漫漫其修远兮,吾将上下而求索”,其实,学习软件编程,学习SDN技术也是一个路漫漫,上下求索的过程。

29620
来自专栏公众号_薛勤的博客

Eclipse MAT内存分析工具(Memory Analyzer Tool)

MAT是Memory Analyzer的简称,它是一款功能强大的Java堆内存分析器。可以用于查找内存泄露以及查看内存消耗情况。MAT是基于Eclipse开发的...

1.5K20
来自专栏Java技术栈

干货:排名前 16 的 Java 工具类!

在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类。以下工具类、方法按使用流行度排名,参考数据来源于Github...

54650
来自专栏java相关

【PL/SQL编程基础】

13740
来自专栏编程

Python入门白皮书#P01 Lists

文档: 我们以Google Python Exercises作为练习素材。 参考对应的文档 https://developers.google.com/edu/...

20660
来自专栏hbbliyong

[Java]读取文件方法大全

1、按字节读取文件内容 2、按字符读取文件内容 3、按行读取文件内容 4、随机读取文件内容  public class ReadFromFile {     /...

38660
来自专栏debugeeker的专栏

《coredump问题原理探究》Linux x86版5.3节C风格数据结构内存布局之数组

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/detai...

8210
来自专栏非著名程序员

Java 反射基础(下)

? 投稿作者:芮成兵/csdn 原文链接: http://blog.csdn.net/My_TrueLove/article/details/51306921...

26460
来自专栏信安之路

利用Java反射和类加载机制绕过JSP后门检测

JSP 后门,一般是指文件名以 .jsp 等后缀结尾的,可运行于 Java servlet 及相关容器和组件内的通用 JSP 脚本。

38100

扫码关注云+社区

领取腾讯云代金券