import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Scanner; /* 已知文件 source.txt 中的内容如下 username=root, password= 1234, id=1, level= 10 username=adimin, mima= 1234 , id=2, level= 11 yonghu= xiaoming ,dengji= 12 ,password= 1234,id= 3 yonghu= xiaofang ,dengji= 11 ,password= 1235,id= 3 其中,username、yonghu 都表示用户名,password、mima都表示密码,level、dengji都表示等级 - 在桌面上的这个source.txt文件拷贝到项目 file\data.txt 中(注意:方式不限,可以是移动或拷贝!) - 读取文本中的数据,将每一行的数据封装成模型,存入 List<User> 中 - 去除集合中id重复的数据,只保留重复id的第一个数据 - 计算这些用户的平均等级、最高等级、最低等级 分析: 使用的技术点: IO流的读写 File的使用 缓冲流 字节流 字符流 高级部分的: Path Paths Files */ public class Demo2 { public static void main(String[] args) throws IOException { //- 在桌面上的这个source.txt文件拷贝到项目 file\data.txt 中(注意:方式不限,可以是移动或拷贝!) copyFile3("C:\\Users\\Administrator\\Desktop\\source.txt", "H:\\BigData\\SZBDjava_day0805\\src\\moning\\data.txt" ); //读取文本中的数据,将每一行的数据封装成模型,存入 List<User> 中 /* 1.创建模型类 2.读取数据,放入模型对象 3.将模型对象放入List集合 */ //第一种方法:通过字符流实现数据的读入 List<User>list=getData1(); System.out.println(list); //第二种方法: //第三种方法: //- 读取文本中的数据,将每一行的数据封装成模型,存入 List<User> 中 //- 去除集合中id重复的数据,只保留重复id的第一个数据 //- 计算这些用户的平均等级、最高等级、最低等级 } //- 在桌面上的这个source.txt文件拷贝到项目 file\data.txt 中(注意:方式不限,可以是移动或拷贝!) //第一种:使用renameto方法,只能移动,移动完成,源文件消失 //注意:要保证目标目录中没有新的文件名. public static void copyFile1(String src,String dst){ //创建文件 createFile1(dst); File srcFile = new File(src); File dstFile = new File(dst); //移动 srcFile.renameTo(dstFile) ; } //第二种:使用IO流实现文件的拷贝 public static void copyFile2(String src,String dst) { //创建文件 createFile1(dst); //将src中的数据读取到dst中 //使用最基本的字节流实现 //创建输入流输出流 InputStream inputStream = null; OutputStream outputStream = null; try { //将数据从src传入内存 //创建FileinputStream对象并关联了数据来源路径 inputStream = new FileInputStream(src); //将数据从内存传出到dst /* 注意点:当用流关联路径时, 1.可以使用绝对路径,也可以使用相对路径 这里默认识别的是当前工程路径 举例: outputStream = new FileOutputStream("haha.txt"); 识别路径:D:\ideaProgramU\SZBD2102Java_pro_03\haha.txt 2.如果当前的文件(data.txt)已经存在,会直接覆盖 如果不存在,自动创建一个叫data.txt的新的文件 3.一定要保证dst是真实存在的. 错误示范:直接报异常:FileNotFoundException outputStream = new FileOutputStream("r:/haha.txt"); */ outputStream = new FileOutputStream(dst); //完成读写过程 /* 一次读一个字节--read() 一次读多个字节--read(数组),数组中临时存储的是当前读到的字节 一次读所有字节--read(数组),一次将所有的字节都放入当前的临时数组 */ //使用一次读一个字节 /* read():在读取字节时每次读取的是当前指针指向的字节,读完后,会自动将指针后移一位 返回值:就是读到的字节,当读到末尾时,返回-1,证明读完了. */ // int num = 0; // while ((num = inputStream.read()) != -1){ // //System.out.print((char) num); // //write方法自己会自动进行转化 // outputStream.write(num); // } //一次读多个字节--read(数组),数组中临时存储的是当前读到的字节 // byte[] arr = new byte[5]; // int num = 0; // while ((num = inputStream.read(arr)) != -1){ // //System.out.print(new String(arr,0,num)); // outputStream.write(arr,0,num); // } //一次读取所有--注意:要求数据的量不能太大,<=1kb //获取所有字节个数 int number = inputStream.available(); byte[] arr = new byte[number]; inputStream.read(arr); outputStream.write(arr); //字节流只能识别字节,这里必须先转成字节. //outputStream.write("haha".getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null){ try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (outputStream != null){ try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } //使用try(){}catch结构可以简化代码,达到自动关闭流的目的. public static void copyFile22(String src,String dst) { //创建文件 createFile1(dst); //将src中的数据读取到dst中 //使用最基本的字节流实现 //创建输入流输出流 //InputStream inputStream = null; //OutputStream outputStream = null; //我们可以通过在try后面添加(),在()中创建流对象,好处:不再需要手动执行close关闭流,这里会自动关闭流 //注意:必须保证try后面()中的类都是实现了Closeable接口. try(InputStream inputStream = new FileInputStream(src); OutputStream outputStream = new FileOutputStream(dst);) { //将数据从src传入内存 //创建FileinputStream对象并关联了数据来源路径 //将数据从内存传出到dst /* 注意点:当用流关联路径时, 1.可以使用绝对路径,也可以使用相对路径 这里默认识别的是当前工程路径 举例: outputStream = new FileOutputStream("haha.txt"); 识别路径:D:\ideaProgramU\SZBD2102Java_pro_03\haha.txt 2.如果当前的文件(data.txt)已经存在,会直接覆盖 如果不存在,自动创建一个叫data.txt的新的文件 3.一定要保证dst是真实存在的. 错误示范:直接报异常:FileNotFoundException outputStream = new FileOutputStream("r:/haha.txt"); */ //完成读写过程 /* 一次读一个字节--read() 一次读多个字节--read(数组),数组中临时存储的是当前读到的字节 一次读所有字节--read(数组),一次将所有的字节都放入当前的临时数组 */ //使用一次读一个字节 /* read():在读取字节时每次读取的是当前指针指向的字节,读完后,会自动将指针后移一位 返回值:就是读到的字节,当读到末尾时,返回-1,证明读完了. */ int num = 0; while ((num = inputStream.read()) != -1){ //System.out.print((char) num); //write方法自己会自动进行转化 outputStream.write(num); } }catch(IOException e){ } } //第三种:使用Files(NIO方法) public static void copyFile3(String src,String dst){ //创建文件 createFile1(dst); try { Files.copy(Paths.get(src),Paths.get(dst)); } catch (IOException e) { e.printStackTrace(); } } //创建目录 //第一种:使用File的mkdir,mkdirs,createNewFile public static void createFile1(String dst){ /* createNewFile():只能用于创建文件 mkdir():只能用于创建单层目录 mkdirs():用于创建多层目录 */ //获取file目录 int index = dst.lastIndexOf("\\"); //"D:\\ideaProgramU\\SZBD2102Java_pro_03\\BD2102Java_day0805\\file" String str = dst.substring(0,index); //创建目录--file File file = new File(str); file.mkdir(); } //第一种:使用Files提供的createDirectory方法----NIO //当使用使用Files提供的createDirectory方法创建目录时,必须保证目录是不存在的,如果已经存在,会报异常:FileAlreadyExistsException public static void createFile2(String dst){ //获取file目录 int index = dst.lastIndexOf("\\"); //"D:\\ideaProgramU\\SZBD2102Java_pro_03\\BD2102Java_day0805\\file" String str = dst.substring(0,index); //创建目录--file //Files.createDirectory() 创建一层目录 //Files.createDirectories() 创建多层目录 //createDirectory方法的参数是一个Path类型的,Path是对路径的封装,是NIO中提供的工具类 //Paths:是对Path进行的再封装 try { Files.createDirectory(Paths.get(str)); } catch (IOException e) { e.printStackTrace(); } } //- 读取文本中的数据,将每一行的数据封装成模型,存入 List<User> 中 //第一种方法:通过字符流实现数据的读入 public static List<User> getData1(){ //创建一个集合存储数据 List<User> list=new ArrayList<>(); //创建字符流对象,将数据读入内存 try { Reader reader=new FileReader("H:\\BigData\\SZBDjava_day0805\\src\\moning\\data.txt"); //开始读取 //先有一个可变字符串,保存每一行的数据 StringBuffer stringBuffer=new StringBuffer(); int num=0; while ((num=reader.read())!=-1){ //在windows中,一班\r\n同时使用 if(num=='\r'){ continue; }else if(num=='\n'){ //说明当前行读完了 list.add(new User(stringBuffer.toString())); //清楚上一次的数据,重新存储数据 stringBuffer.delete(0,stringBuffer.length()); }else { stringBuffer.append((char)num); } } //将最后一行放入lsit中 list.add(new User(stringBuffer.toString())); } catch (IOException e) { e.printStackTrace(); } return list; } //第二种方法:使用scanner public static List<User> getData2(){ List<User> list=new ArrayList<>(); //使用Scanner。默认可以从键盘接收数据 //Scanner scanner=new Scanner(System.in); //scanner.next(); //System.in:是一个标准输入流,默认就是从键盘接受数据 //举例:使用Scanner从文件接受数据 Reader reader=null; try { reader=new FileReader("H:\\BigData\\SZBDjava_day0805\\src\\moning\\data.txt"); Scanner scanner1=new Scanner(reader); //next()方法默认结束符是空格 // String v=scanner1.next(); //nextLine默认读一行 String v=scanner1.nextLine(); list.add(new User(v)); System.out.println(v); } catch (FileNotFoundException e) { e.printStackTrace(); } return list; } //第三种方法: public static List<User> getData3(){ List<User> list=new ArrayList<>(); //创建缓冲流对象---没有读的能力,只能提高效率,所有我们要传入一个普通流 try( BufferedReader bufferedReader=new BufferedReader(new FileReader("H:\\BigData\\SZBDjava_day0805\\src\\moning\\data.txt")); ) { //第一种:一次读一个字符 //第二种:一次读多个字符 //第三种:一次读一行---readLine() //使用规则:当遇到换行符,停止读取 //返回值:就是我们当前行的数据---字符串 //注意点:不会读取换行符 //注意点:当数据读完时,默认返回null,我们就知道读完了。 String data=null; while ((data=bufferedReader.readLine())!=null){ list.add(new User(data)); } } catch (IOException e) { e.printStackTrace(); } return list; } //- 去除集合中id重复的数据,只保留重复id的第一个数据 //这里要使用选择排序 public static void distinst(List<User> list){ for (int i = 0; i < list.size()-1; i++) { for (int j = i; j < list.size()-1; j++) { //如果后面的元素与前面的元素id相同,去掉 if (list.get(i).getId()==list.get(j+1).getId()){ list.remove(j+1); j--; } } } } //- 计算这些用户的平均等级、最高等级、最低等级 public static void cal(List<User>list){ list.sort((o1,o2)->o1.getLevel()-o2.getLevel()); //遍历List int sum=0; for (User user : list) { sum+=user.getLevel(); } System.out.println("最低等级:"+list.get(0)); System.out.println("最高等级"+list.get(list.size()-1)); System.out.println("评价等级"+sum/list.size()); } //创建模型类 static class User{ private String username; private String password; private int id; private int level; public User(){}; public User(String str){ //对str进行切割 //切第一刀 , String[] strings =str.split(","); for (String pair : strings) { //第二刀 = String[] subStr=pair.split("="); //将值放入模型对象 String key=subStr[0].trim(); String value=subStr[1].trim(); if(key.equals("username")||key.equals("yonghu")){ this.username=value; }else if(key.matches("password|mima")){ this.password=value; }else if(key.matches("id")){ this.id=Integer.parseInt(value); }else if(key.matches("level|dengji")){ this.level=Integer.parseInt(value); } } } public User(String username, String password, int id, int level) { this.username = username; this.password = password; this.id = id; this.level = level; } 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; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + ", id=" + id + ", level=" + level + '}'; } } }