目录
2、缓冲字节输出流:BufferedOutputStream
字节流:
字节输入流:InputStream
说明:从方向来说,是一个输入流, 数据是从文件中流动到程序中(数据从其他设备到内存), 是为了读取文件中的数据的。 从数据单位来说, 这个流中流动的数据直接是字节的形式。
/** * 文件的读取 InputStream 一次读取一个字节 */ public class Demo9 { public static void main(String[] args) { try (InputStream inputStream = new FileInputStream("G:\\BigData2021资料\\file\\b\\b.txt")){ int num = 0; while ((num = inputStream.read())!=-1){ System.out.println(new String(arr,0,num)+" \nnum: "+num); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
/** * 文件的读取 InputStream 一次读取多个字节 */ public class Demo9 { //read(数组):一次可以读出多个字节,数组的作用:每次会将读出的字节临时放到这个数组中 public static void main(String[] args) { try (InputStream inputStream = new FileInputStream("G:\\file\\b\\b.txt")){ byte[] arr = new byte[20]; int num = 0; while ((num = inputStream.read(arr))!=-1){ System.out.println(new String(arr,0,num)+" \nnum: "+num); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
/** * 文件的读取 InputStream 一次读取全部的字节 */ public class Demo9 { //available()方法获取全部字节个数 public static void main(String[] args) { try (InputStream inputStream = new FileInputStream("G:\\BigData2021资料\\file\\b\\b.txt")){ int available = inputStream.available(); byte[] bytes = new byte[available]; inputStream.read(bytes)); System.out.println(new String(bytes)); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
说明: 以上是使用字节输入流读取数据的三种方式。
字节输出流:OutputStream
说明: 从方向上来分,是一个输出流,数据从程序中流动到文件中(数据从内存到其他设备),实现文件的写操作。 从流中流动的数据单位来分, 是一个字节流,流中流动的数据直接是字节的形式。
** * 文件的写入 */ public class Demo12 { public static void main(String[] args) { try (OutputStream outputStream = new FileOutputStream("G:\\file\\d\\d.txt", true)){ // 1. 实例化一个管道,连接文件和程序。 // 对于FileOutputStream来说,如果目标文件不存在,则会自动的创建,如果存在,会将原来的内容覆盖 // 当无法创建这个文件的时候(父级目录不存在)(\\b\\c\\d\\d.txt)(若b不存在或者d不存在),创建会失败,会触发FileNotFoundException 。 String message = "你好,浙江大学"; outputStream.write(message.getBytes()); outputStream.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
文件的拷贝:--- 利用两个字节流在实现
/** * 文件的拷贝 * * 思路: * 实现方式: 借助两个流来完成。 * 使用字节输入流输入, 循环读取原文件中的数据。 * 使用字节输出流, 将每次读取到的数据, 写入到目标文件中。 */ public class Demo13 { public static void main(String[] args) { boolean copy = copy("G:\\file\\source.txt", "G:\\file\\dddd\\ccc\\ttt.txt"); System.out.println(copy); } //实现拷贝的功能 public static boolean copy(String srcPath, String dstPath){ //判断目标路径上是否有文件的存在 File dst = new File(dstPath); if (!dst.exists()) { return false; } //实现文件的拷贝 try (InputStream inputStream = new FileInputStream(srcPath); OutputStream outputStream = new FileOutputStream(dst)) { //使用上述的第三种方式,一次读取全部字节 int available = inputStream.available(); byte[] array = new byte[available]; int length = 0; while ((length = inputStream.read(array)) != -1) { outputStream.write(array, 0, length); } outputStream.flush(); return true; } catch (IOException e) { e.printStackTrace(); return false; } } }
字符流:
字符输入流:Reader
说明:从方向来说, 是一个输入流, 数据是从文件中流动到程序中(数据从 其他设备到内存), 是为了读取文件中的数据的。 从数据单位来说, 这个流中流动的数据以 字节为单位的,不同的是在传输过程中加入了编码的操作,让我们的操作更方便。
/** * 字符输入流 Reader */ public class Demo14 { public static void main(String[] args) { try (Reader reader = new FileReader("G:\\file\\source.txt")){ // 1. 实例化一个字符数组 char[] array = new char[100]; // 2. 声明一个变量,用来记录每次读取到了多少个数据 int length = 0; // 3. 循环读取数据 while ((length = reader.read(array)) != -1) { String str = new String(array, 0, length); System.out.print(str); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
字符输出流:Writer
说明:从方向上来分, 是一个输出流, 数据从程序中流动到文件中(数据从内存到其 他设备), 实现文件的写操作。 从流中流动的数据单位来分, 是一个字符流, 流中流动的数 据是以字节为单位,不同的是在传输过程中加入了编码的操作,让我们的操作更方便。
public class Demo15 { public static void main(String[] args) throws IOException { // 1. 实例化相关的类 try (Writer writer = new FileWriter("G:\\file\\target", true)) { // 2. 将数据写入到输出流中 writer.write("hello, world"); // 3. 冲刷缓冲区 writer.flush(); } } }
文件的拷贝: -- 利用利用两个字符流来实现
private static void fileCopy2(String srcPath, String dstPath) { try (Reader reader = new FileReader(srcPath); Writer writer = new FileWriter(dstPath)) { // 循环读取源文件中的数据 char[] array = new char[100]; int length = 0; while ((length = reader.read(array)) != -1) { // 将读取到的数据写入到输出流 writer.write(array, 0, length); } writer.flush(); } catch (IOException e) { e.printStackTrace(); } }
案例一
拷贝的三个方法:
1、字节输入输出流(字符输入输出流)2、renameTo直接移动 3、利用NIO2上的 Files的静态方法copy()
从文件中的数据读取到模型的三个方法:
1、利用字符流实现(字节流也可以) 2、缓冲流(直接利用读取一行)3、使用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的第一个数据 - 计算这些用户的平均等级、最高等级、最低等级
package morning; import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Comparator; 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的第一个数据 * - 计算这些用户的平均等级、最高等级、最低等级 */ /* 此题知识点 : 目前拷贝方法的三个方法 1、字节输入输出流(字符输入输出流也可以) 2、renameto 直接移动 3、 利用NIO2上的 Files的静态方法 copy 将文件中的数据 读取到模型中的三个方法 1、 利用字符流实现(或者字节流实现也可以) 2、通过缓冲流实现 */ public class Demo3 { public static void main(String[] args) { // copyFile1("C:\\Users\\等待\\Desktop\\source.txt", "F:\\ideaProgram\\BigData2021ProThirdDay\\JavaDay3_27\\file\\data.txt"); copyFile2("C:\\Users\\等待\\Desktop\\source.txt", "F:\\ideaProgram\\BigData2021ProThirdDay\\JavaDay3_27\\file\\data.txt"); } //创建file目录 public static void createDocument(String dst){ //createNewFile 只能创建文件 //mkdir 是创建一层目录 只能创建目录 //mkdirs 是创建多层目录,包括一层 只能创建目录 int index = dst.lastIndexOf("\\"); //找到最后一个"\\"的下标 String sub = dst.substring(0, index); System.out.println(sub); //输出:F:\ideaProgram\BigData2021ProThirdDay\JavaDay3_27\file //使用file创建file目录 File file = new File(sub); if (!file.exists()){ file.mkdir(); } } //拷贝方法一:将source文件拷贝到项目的file的data中 public static void copyFile1(String src, String dst) { //先创建file文件夹 createDocument(dst); //创建字节输入流对象并关联文件 InputStream inputStream = null; OutputStream outputStream = null; int num = 0; try { inputStream = new FileInputStream(src); outputStream = new FileOutputStream(dst); while ((num = inputStream.read())!=-1){ outputStream.write(num); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { //因为inputString流对象不一定存在,所以为了执行效率,应该先判空 在关闭 if (inputStream != null){ try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (outputStream != null){ try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } //拷贝方法二:利用renameTo //只能移动,移动完成,源文件消失 public static void copyFile2(String src,String dst){ createDocument(dst); File file1 = new File(src); File file2 = new File(dst); file1.renameTo(file2); } //拷贝方法三,NIO2上的Files里面的方法 public static void copyFile3(String src,String dst){ createDocument(dst); int index = dst.lastIndexOf("\\"); String sub = dst.substring(0, index); System.out.println(sub); //使用file创建file目录 try { Files.createDirectory(Paths.get(sub)); Files.copy(Paths.get(src), Paths.get(dst)); } catch (IOException e) { e.printStackTrace(); } } //2.将内容读取到模型中 //第一种方法:字符流实现 public static List<User1> getData1() throws IOException { List<User1> list = new ArrayList<>(); //创建字符读入流,将数据读入内存 //可以使用相对路径,默认路径是当前工程 Reader reader = null; try { reader = new FileReader("JavaDay3_27\\file\\data.txt"); //用来临时装一行的数据 StringBuffer stringBuffer = new StringBuffer(); //使用一次读取一个字符的方法 int num = 0; while ((num = reader.read()) != -1) { if (num == '\n'){ list.add(new User1(stringBuffer.toString())); System.out.println(stringBuffer.toString()); stringBuffer.delete(0,stringBuffer.length()-1); }else { stringBuffer.append((char) num); } } //将最后一行数据放入list list.add(new User1(stringBuffer.toString())); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } reader.close(); return list; } //第二种方法:通过缓冲流实现 public static List<User1> getData2() throws IOException { /* 缓冲流:缓冲区,可以提高代码读写的效率,但是本身不能读或者写,辅助流工作的. 分类: 字符缓冲流: 字符读入缓冲流--BufferedReader 字符写出缓冲流--BufferedWriter 字节缓冲流: 字节输入缓冲流--BufferedInputStream 字节输出缓冲流--BufferedOutputStream 注意:只有字符缓冲流才有一次读一行的功能,字节缓冲流没有. */ List<User1> list = new ArrayList<>(); //读 Reader reader = new FileReader("JavaDay3_27\\file\\data.txt"); //将reader通过构造方法指给缓冲流 BufferedReader bufferedReader = new BufferedReader(reader); //一次读一个字符 //bufferedReader.read(); //一次读多个字符 //bufferedReader.read(new char[3]); //一次读一行 /* readLine()默认以换行符为一行的结束 注意:readLine读不到换行符 如果所有内容都读完,这个方法会返回null */ String line = null; while ((line = bufferedReader.readLine()) != null){ list.add(new User1(line)); } bufferedReader.close(); return list; } //第二种方法:通过Scanner public static List<User1> getData3() throws FileNotFoundException { List<User1> list = new ArrayList<>(); //System.in 这是一个标准字节输入流,默认从控制台接收数据 //Scanner scanner = new Scanner(new FileInputStream("Day3_27\\file\\data.txt")); Scanner scanner = new Scanner(new File("JavaDay3_27\\file\\data.txt")); //一次读取一行 while (scanner.hasNextLine()){ String line1 = scanner.nextLine(); boolean add = list.add(new User1(line1)); } scanner.close(); return list; } //3.去除集合中id重复的数据,只保留重复id的第一个数据 public static void distinct(List<User1> list){ for (int i = 0; i < list.size()-1; i++) { for (int j = 0; j < list.size()-1-i; j++) { if (list.get(i).getId() == list.get(j+1).getId()){ list.remove(j+1); j--; } } } } //4.计算这些用户的平均等级、最高等级、最低等级 //创建比较器对象,用于比较等级 static class ComWithLevel implements Comparator<User1> { @Override public int compare(User1 o1, User1 o2) { return o1.getLevel()-o2.getLevel(); } } public static void calculatorLevel(List<User1> list){ list.sort(new ComWithLevel()); int sum = 0; for (User1 user : list) { sum+=user.getLevel(); } System.out.println("平均等级:"+sum/list.size()); System.out.println("最大等级:"+list.get(list.size()-1).getLevel()); System.out.println("最小等级:"+list.get(0).getLevel()); } } class User1 { private String username; private String password; private int id; private int level; public User1() { } public User1(String line) { String[] strs = line.split(","); for (String str : strs) { String[] pair = str.split("="); String key = pair[0].trim(); String value = pair[1].trim(); if (key.matches("username|yonghu")){ this.username = value; }else if (key.matches("password|mima")){ this.password = value; }else if (key.matches("level|dengji")){ this.level = Integer.parseInt(value); }else if (key.matches("id")){ this.id = Integer.parseInt(value); } } } @Override public String toString() { return "User1{" + "username='" + username + '\'' + ", password='" + password + '\'' + ", id=" + id + ", 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; } public User1(String username, String password, int id, int level) { this.username = username; this.password = password; this.id = id; this.level = level; } }
缓冲流(推荐使用)
- 简单介绍:给普通的IO流套上一个缓冲区。所有使用缓冲流进行的读写操作,都是和缓冲区进行交互的,避免了频繁的IO操作。这样一来的好处就是可以提高读写的效率。实际上这个缓冲区就是一个数组。
- 缓冲流的作用:由原来的一个一个字节读取,变成放到缓冲流(可配置字节数)进行批量操作,这样和底层的硬盘操作频率变少,效率提高。可以将缓冲流比作是催化剂或高速的小车
- 注意点:缓冲流只是可以提高读写的能力,其本身并没有读写的能力,要想进行读写操作就必须借助于字符流或字节流来实现
常见的缓冲流:
1、缓冲字节输入流:BufferedInputSteram
/** * 缓冲字节流 */ public class Demo { public static void main(String[] args) { String src = "F:\\ideaProgram\\file\\source.txt"; int index = src.lastIndexOf("\\"); //获取F:\ideaProgram\file String path = src.substring(0, index); File file = new File(path); if (!file.exists()){ System.out.println("文件夹不存在,先创建文件夹,已创建"); file.mkdir(); } try(BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(src))) { byte[] array = new byte[1024]; int lenth = 0; while((lenth = bufferedInputStream.read(array))!=-1){ String message = new String(array,0,lenth); System.out.println(message); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
2、缓冲字节输出流:BufferedOutputStream
/** * 缓冲字节输出流 */ public class Demo1 { public static void main(String[] args) { String src = "F:\\ideaProgram\\file\\source.txt"; String dst = "F:\\ideaProgram\\file\\data.txt"; try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(dst)); BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(src))) { int count = bufferedInputStream.available(); byte[] bytes = new byte[count]; int length = 0; while ((length = bufferedInputStream.read(bytes)) != -1) { System.out.println("length = " + length); bufferedOutputStream.write(bytes, 0, length); } bufferedOutputStream.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
3、缓冲字符输入流:BufferedReader
/** * 缓冲字符流 */ public class Demo3 { public static void main(String[] args) { // 借助一个字符流,实例化一个缓冲字符输入流 try (BufferedReader bufferedReader = new BufferedReader(new FileReader("file\\day26\\src"))) { // 从流中读取数据 char[] array = new char[100]; //注意:这个地方 是字符流 不是字节流 所以需要的是字符数组而不是字节数组 int length = 0; while ((length = bufferedReader.read(array)) != -1) { System.out.print(new String(array, 0, length)); } } catch (IOException e) { e.printStackTrace(); } }
4、缓冲字符输出流:BufferedWriter
/** * 缓冲字符输出流 */ public class Demo3 { public static void main(String[] args) { // 借助一个字符输出流,实例化一个缓冲字符输出流对象 try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("file\\aaa.txt"))) { bufferedWriter.write("hello world"); bufferedWriter.flush(); } catch (IOException e) { e.printStackTrace(); } } }