3、IO流
(1)前提需求: 读写文件内部的内容,上传,下载
(2)流: 管道 数据以先入先出的方式进行流动,数据源--数据-->目的地
(3)io包: 一系列io相关类 File...
(4)流的分类:
①按照流向分:
输入流,输出流
(以大脑为中心,以程序为中心,明确数据源和目的地,能够确定输入还是输出)
②按照操作单元分;
字节流 : 万能流,任意内容都能转为字节,字符流 : 只能传输纯文本的内容
③按照功能分:
节点流 : 真实做读入写出的流,功能流 : 增强节点流的功能,加强性能
分类之间是相辅相成的
(5)字节流:
①字节输入流 InputStream
文件字节输入流 FileInputStream
功能: 节点流 流向分:输入流 操作单元:字节流
功能: 读入read() 关闭close
②字节输出流 OutputStream
public class Class001_IO { public static void main(String[] args) throws IOException { //FileInputStream(File file) 通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的 File对象 file命名。 File src = new File("D://test2.txt"); //数据源 //创建流 InputStream is = new FileInputStream(src); //读入数据 int read() 从此输入流中读取一个字节的数据。 读到文件末尾返回-1 int num = is.read(); //处理数据 System.out.println((char)num); System.out.println((char)(is.read())); System.out.println((char)(is.read())); System.out.println(is.read()); //关闭流 is.close(); } }
③read() 从此输入流中读取一个字节的数据。 读到文件末尾返回-1
每次读取一个字节,重复通过循环读入,可以简化代码结构
public class Class002_IO { public static void main(String[] args) throws IOException { //创建流 //FileInputStream (String name) 通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的路径名 name命名。 InputStream is = new FileInputStream("D://test2.txt"); //读入数据 int num = -1; while((num=is.read())!=-1){ //处理数据 System.out.println((char)num); } //关闭流 is.close(); } }
④public byte[] readAllBytes() throws IOException
从输入流中读取所有剩余字节。 此方法将阻塞,直到读取了所有剩余字节并检测到流结束,或者抛出异常。 此方法不会关闭输入流。
当此流到达流的末尾时,此方法的进一步调用将返回空字节数组,请注意,此方法适用于方便将所有字节读入字节数组的简单情况。 它不用于读取包含大量数据的输入流。起始版本: java9
public class Class004_IO { public static void main(String[] args) throws IOException { //1.构建流 InputStream is = new FileInputStream("D://test2.txt"); //2.读入所有数据 byte[] arr = is.readAllBytes(); //3.处理数据 System.out.println(new String(arr)); //4.关闭 is.close(); } }
(6)字节输出流
①OutputStream 此抽象类是表示输出字节流的所有类的超类。
②FileOutputStream : 文件输出流,将数据写出到指定文件中
③注意:如果目的地文件不存在,系统会自动创建
输出流如果目的地文件存在,内容默认覆盖,设置追加
(7)文件拷贝,数据源--> 读入---> 程序 --> 写出 --> 目的地
步骤:①创建流(输入 输出)②准备小汽车 字节数组③读入-->写出④刷出⑤关闭(后打开的先关闭)
public class Class006_CopyFile { public static void main(String[] args){ //1.创建流(输入 输出) //作用域提升,为了能够在finally中使用 InputStream is = null; OutputStream os = null; try { is = new FileInputStream("D://test.txt"); os = new FileOutputStream("D://dest.txt"); //2.准备小汽车 字节数组 byte[] car = new byte[1024]; //3.读入-->写出 int len = -1; //记录每次读入到字节数组中数据的个数 while((len=is.read(car))!=-1){ //读入多少字节数据写出多少字节数据 os.write(car,0,len); } //4.刷出 os.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { //5.关闭(后打开的先关闭) //预防空指针异常出现 if(os!=null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if(is!=null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
(8)字符输入流 : 只能读写纯文本数据
①输入流 : Reader 字符输入流的父类FileReader 文件字符输入流read(),read(char[]),close()
②输出流 : Writer
public class Class001_IO { public static void main(String[] args) throws IOException { //1.创建流 //FileReader(String fileName) //FileReader(File file) Reader rd = new FileReader("D://test.txt"); //2.读入 //char ch = (char)(rd.read()); //小汽车 char[] car = new char[1024]; //循环读入 int len = -1; while((len = rd.read(car))!=-1){ //3.处理数据 System.out.println(new String(car,0,len)); } //4.关闭 rd.close(); } }
③输出流 : Writer 字符输出流抽象父类,FileWriter 文件字符输出流write(),flush(),close()
public class Class002_IO { public static void main(String[] args) throws IOException { //1.创建流 /* //FileWriter(File file) //FileWriter(String fileName) //FileWriter(File file, boolean append) //FileWriter(String fileName, boolean append) */
Writer rt = new FileWriter("D://test.txt",true); //2.准备数据 String msg = "今天也要加油鸭!!!"; //3.写出 rt.write(msg); //4.刷出 rt.flush(); //5.关闭 rt.close(); } }
④字符流实现文件拷贝,注意: 只能为纯文本文件
1、拷贝文件夹 :
(1)判断要拷贝的文件是文件还是文件夹
是文件: 调用工具类实现文件拷贝
是文件夹: 创建文件夹,遍历数据源文件夹,获取到所有的子文件然后重复
public static void main(String[] args) {
copyDir("D://DDD","D://haha");
}
//拷贝文件夹
public static void copyDir(String src,String dest){
copyDir(src!=null?new File(src):null,dest!=null?new File(dest):null);
}
public static void copyDir(File src, File dest){
if(src==null || dest==null){
throw new NullPointerException();
}
if(!src.exists()){
System.out.println("数据源不存在!!!");
return;
}
//拷问文件夹|文件
copyDetail(src,dest);
}
//实现拷贝细节
public static void copyDetail(File src,File dest){
//拼接完整目的地路径
dest = new File(dest,src.getName()); //D:\haha\hehe\DDD
//文件
if(src.isFile()){
//如果目的地路径不存在
if(!dest.getParentFile().exists()){
dest.getParentFile().mkdirs();
}
//文件拷贝
CopyFileUtils.copyFile(src,dest);
}else if (src.isDirectory()){
//文件夹
//创建不存在的目的地路径
dest.mkdirs();
//遍历数据源
File[] arr = src.listFiles();
for(File file:arr){ //D:\DDD\a.txt
copyDetail(file,dest); ////D:\haha\hehe\DDD
}
}
}
}
(2)按照功能分:
①节点流 : 真实做读入写出②功能流 : 加强性能③功能流都要包裹节点流使用
④缓冲流 : 功能流⑤作用: 提高读写效率
⑥字节节点流:
FileInputStream 文件流 | ByteArrayInputStream 字节数组流
FileOutputStream | ByteArrayOutputStream
⑤字节缓冲流 : 字节流功能流的一种
BufferedInputStream 字节输入缓冲流
BufferedOutputStream 字节输出缓冲流
⑥无新增功能,可以发生多态
⑦字符节点流
FileReader,FileWriter
⑧字符缓冲流
BufferedReader,BufferedWriter
存在新增方法: 不能发生多态
readLine(),newLine()
public class Class001_Buffered { public static void main(String[] args) throws IOException { //1.创建流 InputStream is = new BufferedInputStream(new FileInputStream("D://test.txt")); OutputStream os = new BufferedOutputStream(new FileOutputStream("D://heihei.txt")); //2.拷贝 byte[] car = new byte[1024]; int len = -1; while((len=is.read(car))!=-1){ os.write(car,0,len); } //3.刷出 os.flush(); //4.关闭 os.close(); is.close(); } }
2、基本数据类型流|Data流
(1)功能: 功能流 操作单元: 字节流
(2)作用: 保留数据已经数据类型(基本数据类型+String)
DataInputStream,新增功能: readXxx()
DataOutputStream,新增功能: writeXxx()
(3)注意:①读入与写出的顺序要保持一致②java.io.EOFException : 读入的文件不是源文件
public class Class001_Data { public static void main(String[] args) throws IOException { readFromFile("D:/d.txt"); } //读入 public static void readFromFile(String path) throws IOException { //1.创建流 DataInputStream is = new DataInputStream(new BufferedInputStream(new FileInputStream(path))); //2.读入 int i = is.readInt(); boolean flag = is.readBoolean(); char ch = is.readChar(); String s = is.readUTF(); //3.处理数据 System.out.println(i); System.out.println(flag); System.out.println(ch); System.out.println(s); //4.关闭 is.close(); } //写出 public static void writeToFile(String path) throws IOException { //1.创建输出流 DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path))); //2.准备数据 int i = 1; boolean flag = false; char ch = 'c'; String str = "哈哈"; //3.写出 out.writeInt(i); out.writeBoolean(flag); out.writeChar(ch); out.writeUTF(str); //4.刷出 out.flush(); //5.关闭 out.close(); } }
3、Object 流| 对象流 | 引用数据类型流
(1)作用: 读写对象数据|引用数据类型的数据(包含基本数据类型)
ObjectInputStream 反序列化输入流,新增功能: readObject()
ObjectOutputStream 序列化输出流,新增功能: writeObject(Object obj)
(2)序列化: 将对象数据转换一个可存储或者可传输的状态过程
(3)特性:
①先序列化后反序列化
②不能所有的类型都能序列化 java.io.Serializable
③不是所有的属性都需要序列化
④静态的内容不会序列化
⑤如果父类实现序列化,子类没有实现,可以序列化所有的成员
⑥如果子类实现序列化,父类实现,只能序列化子类成员
(4)通过序列号控制版本不一致问题:
①实现Serializable接口的类型默认生成序列号,序列号会根据成员的修改做更新 serialVersionUID = -5204947308809070324
②控制版本的统一问题: 控制类型修改之前与之后序列不变
③通过工具生成序列号: a.实现Serializable接口 b.setting设置 c.选中类名->alt+enter->生成序列号
public class Class001_Object { public static void main(String[] args) throws IOException, ClassNotFoundException { //writeToFile("D://e.txt"); readFile("D://e.txt"); } //反序列化 public static void readFile(String path) throws IOException, ClassNotFoundException { //1.输入流 ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(path))); //2.读入 User obj1 = (User) in.readObject(); int[] arr = (int[]) in.readObject(); //3.处理数据 System.out.println(obj1); System.out.println(Arrays.toString(arr)); //4.关闭 in.close(); } //序列化输出 public static void writeToFile(String path) throws IOException { //1.输出流 ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(path))); //2.数据 User user = new User("zhangsan",18,"123"); int[] arr = {1,2,3,4}; //3.写出 out.writeObject(user); out.writeObject(arr); //4.刷出 out.flush(); //5.关闭 out.close(); //修饰user对象的成员,静态 user.username = "lisi"; user.password = "4321"; } } class User implements Serializable{ private static final long serialVersionUID = -5204947308809070324L; public String username; //transient 修饰的字段不会序列化 public transient int age; public static String password; //成员的修改: 新增的成员 public int vip; public int id; //用户编号 public User() { } public User(String username, int age, String password) { this.username = username; this.age = age; this.password = password; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", age=" + age + ", password='" + password + '\'' + '}'; } }
(1)CommonsIO 是apache的一个开源的工具包,封装了IO操作的相关类,使用Commons IO可以很方便的读写文件,url源代码等。
(2)使用第三方组件的方式|步骤:
①下载源码资源,找到核心jar包
②项目下新建文件夹lib,放入jar包
③commons-IO 需要加入classpath 的第三方 jar 包内的 class 文件才能在项目中使用,选中jar包右键->add as lib...
public class Class001_CommonsIO { public static void main(String[] args) throws IOException { //1.创建File对象 File src = new File("D://a.txt"); File dest = FileUtils.getFile("D://f.txt"); //FilenameUtils //isExtension(String fileName, String text) // 判断fileName是否是text后缀名 //FilenameUtils.getBaseName(String filename) // 去除目录和后缀后的文件名 System.out.println(FilenameUtils.getBaseName("D://DDD/haha.txt"));; System.out.println(FilenameUtils.getName("D://DDD/haha.txt"));; System.out.println(FilenameUtils.isExtension("D://DDD/haha.txt","txt"));; //FileUtils //FileUtils.copyFile(File srcFile, File destFile)` // 复制文件 FileUtils.copyFile(src,dest); // **复制文件夹** //FileUtils.copyDirectory(File srcDir, File destDir)` // 复制文件夹(文件夹里面的文件内容也会复制) FileUtils.copyDirectory(new File("D://DDD"), new File("D://hehe/DDD")); //FileUtils.copyDirectory(File srcDir, File destDir, FileFilter filter)` // 复制文件夹,带有文件过滤功能 FileUtils.copyDirectory(new File("D://DDD"), new File("D://houhou/DDD"), FileFilterUtils.fileFileFilter()); //**把字符串写入文件** //`FileUtils.writeStringToFile(File file, String data, String encoding)` // 字符串以指定的编码写到文件 //`FileUtils.writeStringToFile(File file, String data, String encoding, boolean append)`// 指定知否追加 FileUtils.writeStringToFile(src,"yyds!!!!","UTF-8",true); } }