文件到集合(改进版)
- 需求:把文本文件中的数据读取到集合中,兵遍历集合。要求:文件中每一行数据是一个学生对象的成员变量值 。如 itheima001,林青霞,30,西安
- 思路
- 定义学生类
- 创建字符缓冲输入流对象
- 创建ArrayList集合对象
- 调用字符缓冲输入流对象的方法读数据
- 把读取到底字符串数据用split()进行分割,得到一个字符串数组
- 创建学生对象
- 把字符串数组的每一个元素取出来对应的赋值给学生对象的成员变量值
- 把学生对象添加到集合
- 释放资源
- 遍历集合
- 学生类四个属性:sid name age address
- 主程序
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
public class FileToArrayListDemo {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("/home/ding/IdeaProjects/Study/src/com/itheima_02/file/students.txt"));
ArrayList<Student> array = new ArrayList<Student>();
String line;
while((line=br.readLine())!=null){
String[] strArray = line.split(",");
Student s = new Student();
s.setSid(strArray[0]);
s.setName(strArray[1]);
s.setAge(Integer.parseInt(strArray[2]));
s.setAddress(strArray[3]);
array.add(s);
}
br.close();
for ( Student s : array){
System.out.println(s.getSid()+","+s.getName()+","+s.getAge()+","+s.getAddress());
}
}
}
集合到文件(数据排序改进版)
- 在集合中的数据进行排序,然后写到文件。
- 需求:键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩)。要求按照成绩总分从高到低写入文本文件。
- 格式:姓名,语文成绩,数学成绩,英语成绩 举例:林青霞,98,99,100
- 思路:
- 定义学生类
- 创建TreeSet集合,通过比较器排序进行排序
- 键盘录入学生数据
- 创建学生对象,把键盘录入的数据对应赋值给学生对象的成员变量
- 把学生对象添加到TreeSet集合
- 创建字符缓冲输出流对象
- 遍历集合,得到每一个学生对象
- 把学生对象的数据拼接成指定格式的字符串
- 调用字符缓冲输出流对象的方法写数据
10.释放资源
- 学生类
public class Student {
private String name;
private int chinese;
private int math;
private int english;
public Student() {
}
public Student(String name, int chinese, int math, int english) {
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getEnglish() {
return english;
}
public void setEnglish(int english) {
this.english = english;
}
public int getSum(){
return this.chinese+this.math+this.english;
}
}
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
public class TreeSetToFileDemo {
public static void main(String[] args) throws IOException {
//创建TreeSet集合,通过比较器排序进行排序
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//成绩总分从高到低
int num = s2.getSum() - s1.getSum();
//次要条件
int num2 = num==0?s1.getChinese()-s2.getChinese():num;
int num3 = num2==0?s1.getMath()-s2.getMath():num2;
int num4 = num3==0?s1.getName().compareTo(s2.getName()):num3;
return num4;
}
});
//键盘录入学生数据
for (int i = 0; i < 5; i++) {
Scanner sc = new Scanner(System.in);
System.out.println("请录入第"+(i+1)+"个学生信息:");
System.out.println("姓名:");
String name = sc.nextLine();
System.out.println("语文成绩:");
int chinese = sc.nextInt();
System.out.println("数学成绩:");
int math = sc.nextInt();
System.out.println("英语成绩:");
int english = sc.nextInt();
//创建学生对象,把键盘录入的数据对应赋值给学生对象的成员变量
Student s = new Student();
s.setName(name);
s.setChinese(chinese);
s.setMath(math);
s.setEnglish(english);
//把学生对象添加到集合中
ts.add(s);
}
//创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("/home/ding/IdeaProjects/Study/src/com/itheima_02/file/ts.txt"));
//遍历集合,得到每一个学生对象
for(Student s : ts){
//把学生对象的数据拼接成指定格式的字符串
StringBuilder sb = new StringBuilder();
sb.append(s.getName()).append(",").append(s.getChinese()).append(",").append(s.getMath()).append(",").append(s.getEnglish()).append(",").append(s.getSum());
//调用字符缓冲输出流对象的方法写数据
bw.write(sb.toString());
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
}
}
复制单级文件夹
- 单级文件夹指的是该文件夹里面只有文件,没有文件夹。
- 思路:
- 创建数据源目录File对象
- 获取数据源目录File对象的名称
- 创建目的地目录File对象
- 判断目的地目录对应的File是否存在,如果不存在,就创建
- 获取数据源目录下所有文件到FIle数组
- 遍历File数组,得到每一个File对象,该File对象其实就是数据源文件
- 获取数据源文件File对象的名称
- 创建目的地文件File对象
- 复制文件,采用字节流复制文件
import java.io.*;
import static com.sun.deploy.cache.Cache.copyFile;
public class CopyFolderDemo {
public static void main(String[] args) throws IOException {
//创建数据源目录File对象
File srcFolder = new File("/home/ding/IdeaProjects/Study/src/com/itheima_02/file/JavaSE");
//获取数据源目录的名称
String srcFolderName = srcFolder.getName();
//创建目的地File对象
File destFolder = new File("/home/ding/IdeaProjects/Study/src/com/itheima_02/file/copyFolder",srcFolderName);
//判断目的地目录对应的File是否存在,如果不存在,就创建
if(destFolder.exists()){
destFolder.mkdir();
}
//获取数据源目录下所有文件到File数组
File[] listFiles = srcFolder.listFiles();
//遍历File数组,得到每一个File对象,该File对象,其实就是数据源文件
for(File srcFile : listFiles){
String srcFileName = srcFile.getName();
//创建目的地文件File对象
File destFile = new File(destFolder,srcFileName);
//复制文件
copyFile(srcFile,destFile);
}
}
private static void copyFile(File srcFile,File destFile) throws IOException{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
byte[] bys = new byte[1024];
int len;
while((len=bis.read(bys))!=-1){
bos.write(bys,0,len);
}
bos.close();
bis.close();
}
}
复制多级文件夹
- 思路:
- 创建数据源对象,路径是 /home/ding/IdeaProjects/Study/src/com/itcast
- 创建目的地File对象,路径是 /home/ding/itcast
- 写方法实现文件夹的复制,将来递归调用。参数为数据源File对象和目的地File对象。
- 判断数据源File是否是目录。如果是,在目的地下创建和数据源File名称一样的目录,获取数据源File下所有文件或者目录的File数组。遍历该File数组,得到每一个File对象。把该File作为数据源File对象,递归调用复制文件夹的方法。如果不是,说明是文件,直接复制,用字节流实现。
import java.io.*;
public class CopyFoldersDemo {
public static void main(String[] args) throws IOException{
//创建数据源对象,路径是 /home/ding/IdeaProjects/Study/src/com/itcast
File srcFile = new File("/home/ding/IdeaProjects/Study/src/com/itcast");
//创建目的地File对象,路径是 /home/ding/itcast
File destFile = new File("/home/ding/itcast");
//写方法实现文件夹的复制,将来递归调用。参数为数据源File对象和目的地File对象
copyFolder(srcFile,destFile);
}
//复制文件夹
private static void copyFolder(File srcFile, File destFile) throws IOException{
//判断数据源File是否是目录
if(srcFile.isDirectory()){
//在目的地下创建和数据源File名称一样的目录
String srcFileName = srcFile.getName();
File newFolder = new File(destFile,srcFileName);
if(!newFolder.exists()){
newFolder.mkdir();
}
//获取数据源File下所有文件或者目录的File数组
File[] fileArray = srcFile.listFiles();
//遍历该File数组,得到每一个File对象
for(File file : fileArray){
//把该File作为数据源File对象,递归调用复制文件夹的方法
copyFolder(file,newFolder);
}
}else{
//如果不是,说明是文件,直接复制,用字节流实现
File newFile = new File(destFile,srcFile.getName());
copyFile(srcFile,newFile)
}
}
//字节流缓冲复制文件
private static void copyFile(File srcFile, File destFile) throws IOException{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
byte[] bys = new byte[1024];
int len;
while((len = bis.read(bys))!=-1){
bos.write(bys,0,len);
}
bos.close();
bis.close();
}
}
复制文件到异常处理
- 来看这么一段源码,method1方法的目的是复制文件,现在报错是因为异常没有处理。前面我们的做法都是把异常抛出去 throws IOException ,这样做的目的是让我们得关注点在代码的执行- 而抛出处理并不是真正的处理,我们现在要在方法内部进行异常处理。我们采用try…catch…finally进行处理
try{
可能出现的异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}finally{
执行所有清除操作;
}
- 以下是复杂的方法
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyFileDemo {
public static void main(String[] args) {
}
private static void method1(){
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("fr.txt");
fw = new FileWriter("fw.txt");
char[] chs = new char[1024];
int len;
while ((len = fr.read()) != -1) {
fw.write(chs, 0, len);
}
} catch (IOException e){
e.printStackTrace();
} finally{
if(fw!=null) {
try {
fw.close();
} catch(IOException e){
e.printStackTrace();
}
}
if(fr!=null){
try {
fr.close();
} catch(IOException e){
e.printStackTrace();
}
}
}
}
}
- 接下来讲JDK7的改进方案,自动释放资源
try(定义流对象){
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码
}
private static void method3(){
try(FileReader fr = new FileReader("fr.txt");
FileWriter fw = new FileWriter("fw.txt");){
char[] chs = new char[1024];
int len;
while((len=fr.read())!=-1){
fw.write(chs,0,len);
}
} catch(IOException e){
e.printStackTrace();
}
}
- 在jdk9的时候又给了一个改进方案
定义输入流对象;
定义输出流对象;
try(输入流对象; 输出流对象){
可能出现异常的代码;
}catch (异常类名 变量名){
异常的处理代码;
}
public static void method4() throws IOException{
FileReader fr = new FileReader("fr.txt");
FileWriter fw = new FileWriter("fw.txt");
try(fr;fw){
char[] chs = new char[1024];
int len;
while((len=fr.read()) != -1){
fw.write(chs,0,len);
}
} catch (IOException e){
e.printStackTrace();
}
}
特殊操作流
标准输入输出流
- system类两个成员变量,in就是输入流,out就是输出流
- 标准输入流,该流已经打开,准备提供输入数据。通常,该流对应于键盘输入或由主机环境或用户指定的另一个输入源。
public static final InputStream in
- 标准输出流,此流已经打开并准备好接受输出数据。通常,此流对应于显示输出或由主机环境或用户指定的另一个输出目标。
public static final PrintStream out
- 执行以下代码
import java.io.IOException;
import java.io.InputStream;
public class SystemInDemo {
public static void main(String[] args) throws IOException {
InputStream is = System.in;
int by;
while((by=is.read())!=-1){
System.out.println((char)by);
}
}
}
- 控制台等待着我们输入数据
- 假如输入一个中文就出问题了,因为“中”这个汉字采用UTF-8编码他就是三个字节的。我们每读到一个数据,就把他强制转换到对应的字符,所以出现了对应三个字符。所以用字节流读数据是不方便的。
- - 现在他只有一个字节流,那能不能用字符流来读数据呢?如何把字节流转换为字符流呢?
- 用转换流就可以了
InputStream is = System.in;
InputStreamReader isr = new InputStreamReader(is);
- InputStreamReader类是一个字符流,他的构造方法可以接收一个InputStream类型的。
- 那么我们就可以使用这个字符流来读汉字了。但如果是多个汉字那怎么办呢?我们能不能用字符流一次读一行呢?可以,但是一次读取一行数据的方法是字符缓冲输入流的特有方法。
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
- 包装了System.in,实际上底层读的还是字节流。
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入一个字符串:");
String line = br.readLine();
System.out.println("你输入的字符串是:"+line);
System.out.println("请输入一个整数:");
int i = Integer.parseInt(br.readLine());
System.out.println("你输入的整数:"+i);
- 自己实现键盘录入数据太麻烦了,所以Java提供了一个类给我使用:Scanner。而Scanner底层包装的也是System.in。
标准输出流
- System.out生成的变量是PrintStream类的。PrintStream他可以方便的打印各种数据的值
PrintStream ps = System.out;
ps.print("hello");
ps.print(100);
- 使用ps.print的效果和使用System.out.println的效果。ps代表的就是System.out,他可以调这个方法。System.out他的本质是一个字节输出流
- 留意这里,System.out.println()可以调用,而System.out.print()不可以
- 带ln的他是可以没有参数的,不带ln他是必须有参数的。如果说PrintStream里面没有方法,System.out是不可以使用的。
- 输出语句的本质,是一个标准的输出流,PrintStream类有点方法,System.out都可以使用
PrintStream ps = System.out;