14、java——IO流
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:hahaheheDDD
//文件
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:DDDa.txt
copyDetail(file,dest); ////D:hahaheheDDD
}
}
}
}
(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);
}
}