05IO流

File文件或目录的抽象

对文件进行操作,首先建文件对象
且文件对象也可以用做字节流的参数

File file=new File(“D:\”);
文件和目录可以通过File封装成对象

	对于File,其封装的并不是一个真正的文件,只是文件的路径,可存在可不存在,之后通过具体的操作把这个路径转化为具体的存在
构造:
	File(String pathname)	通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
	File(String parent, String child)	从父路径名字符串和子路径名字符串创建新的 File实例。
	File(File parent, String child)	从父抽象路径名和子路径名字符串创建新的 File实例。 
	注意:父路径和子路径就是把一个完整的路径进行了拆分(以目录进行拆分),最终会进行拼接

转义符:

	\ 更改当前内容的含义,只能更改转义符后第一个字母
	例如:n默认为字母  \n表示换行
	例如:""默认表示字符串  \":"表示为字符
	例如:\默认表示转义符   \\:前一个转义符把后一个转义符含义为修改为字符

file对象的方法

//当抽象路径所指内容不存在时,创建一个空的文件
//当抽象路径所指内容存在时,不创建
file.createnewFile()

//当抽象路径所指内容不存在时,创建一个空的文件
//当抽象路径所指内容存在时,不创建
//public boolean mkdir()
file.mkdir()
mkdir只能创建单级目录不能创建多级目录
//public boolean mkdirs()
boolean mkdirs=file.mkdirs();
//创建由此抽象路径命名的目录,包括任何必须但不存在父目录
mkdirs可以创建多级目录,也可以创建单级目录

抽象路径是内容,由具体的操作来决定
路径不能通过名称来判断是目录还是文件

IO字节流

IO:输入Input 输出Output
流:抽象的概念,表示数据传输
IO流:设备与设备之间的数据传输

IO流的分类
流向分类:输入流和输出流
数据类型分类
	字节流:字节输入输出流
	字符流:字符输入输出流
	注意:能用记事本打开,并且记事本中的内容可以看懂,使用字节使用字符都可以
		 如果内容是看不懂的,就使用字节流
		 如果不知道使用什么流,直接使用字节流

字节输出流FileOutputStream

FileOutputStream fos = new FileOutputStream("");

使用步骤:
	1.创建对象(1.调用基层系统创建空文件 2.创建流的对象 3.让对象指向文件)
	3.写数据(write())
	2.关闭资源(减少底层系统的消耗,避免了在操作当前文件时,还有别的程序操作当前文件)

写数据的三种方法
	write(int b)	将指定的字节写入文件,一次写一个字节
	write(byte[] b)	将指定的字节数组写入文件,一次写一个字节数组
	write(byte[] b,int off,int len)	将指定的字节数组,从偏移量off开始写入文件,一次写len个字节,一次写数组的一部分
注意:字节可以为int可以char
	 off理解为索引或下标
	 len从off开始写入几个字节
构造:
	FileOutputStream(String name) 调用底层系统创建空文件  默认调用下面一个构造 只不过append默认为false
	FileOutputStream(String name,boolean append)  append为true表示追加
	FileOutputStream(File file)
	FileOutputStream(File file,boolean append)

字节输入流FileInputStream

FileInputStream ios = new FileInputStream("");

使用步骤:
	1.创建对象(1.抽象路径所指文件必须存在 2.创建流的对象 3.让对象指向文件)
	3.写数据(read())
	2.关闭资源(减少底层系统的消耗,避免了在操作当前文件时,还有别的程序操作当前文件)
读数据的三种方式
	int read() 读取一个字节  得到的返回值是字节
	int read(byte[] b) 按照一个字节数组读取数据,返回值为读取的字节个数
	注意:如果数组长度大于文件中内容,所得到的返回值为读取的字节个数
	int read(byte[] b,int off,int len) 按照一个字节数组的一部分去读取数据,返回值为读取的字节个数
	注意:off决定读取得到字节存储位置
		如果获取数组中的一部分,通过read的返回值(就是读取的内容个数)
        
循环读取写法:没有读取导数据时,返回值为-1
	int i;
	while((i=fis.read())!=-1){
		Syste.out.println(new String(bytes,0,i));
	}
	注意:换行符占两个字节
	windows中换行符默认是\r\n
	linux中换行符默认是\n
	mac中换行符默认是\r
	idea能识别所有换行符,windwos中使用idea识别换行符使用\r\n

##编码集

常用编码集:ASCII GBK Uniconde
Uniconde统一的万国码,有UTF-8,-16...常用UTF-8
乱码出现的问题:编码和解码所用的编码集不同
编码:
	byte[] getBytes():使用平台的默认字符编码集将String存储字节数组
	byte[] getBytes(String chareName):使用指定的编码集String存储字节数组
解码:
	String(byte[] bytes):通过默认字符集解码指定的数组来构造新的String
	String(byte[] bytes,String chareName):通过指定字符集解码指定的数组来构造新的String

注意:编码和解码所随用的编码集要保持一直,不然会出现乱码问题
UTF-8使用3个字节表示字符
GBK使用两个字节表示字符
windows默认编码格式为GBK

##缓冲流
为什么使用缓冲流?
避免底层系统的多次调用

BufferedOutputStream(OutputStream):

BufferedOutputStream fos=new BufferedOutputStream(new FileOutputStream(""));

字节输出缓冲流
注意:缓冲流默认拥有缓冲区,默认大小为8192
	写入数据时,首先先写入缓冲区,在写入到文件
	什么情况下缓冲区中的数据会写入到文件?
		1.调用了close或flush
		2.写入的数据大小超出了缓冲区的大小(缓冲区满了会把写入到文件中,然后把当前缓冲区清空用于接收下面的数据)

BUfferedInputStream(InputStream):

字节输入缓冲流

BufferedInputStream ios=new BufferedInputStream(new FileInputStream(""));

IO字符流

为什么使用字符流?
1.字节流操作中文时,会出现乱码的情况(可能会把中文拆分进行读取)
2.需要关注解码和编码的过程

字符流
Read:这个抽象类表示字符输入流的所有类的父类
Write:这个抽象类表示字符输出流的所有类的父类
OutputStreamWrite:文件字符输出流(具体的字符输出流实现类)
	OutputStreamWrite(OutputStream out)创建文件字节输出流写入文件
write(String s)
write(String s,int off,int len)
注意:底层还是字节流

OutputStreamWrite

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(""))
OutputStreamWrite构造:
OutputStreamWriter(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter。
OutputStreamWriter(OutputStream out, Charset cs) 创建一个使用给定字符集的OutputStreamWriter。
OutputStreamWrite写数据的方法:
void write(int c) 写一个字符
void write(char[] cbuf) 写一个字符数组
void write(char[] cbuf,int off,int len) 写一个字符数组的一部分
void write(String str) 写一个字符串
void write(String str,int off,in len) 写一个字符串的一部分

InputStreamReader

InputStreamReader isr = new InputStreamReader(new FileInputStream(""))
InputStreamReader构造:
InputStreamReader(InputStream in)创建一个使用默认字符集的InputStreamReader。
InputStreamReader(InputStream in, Charset cs)创建一个使用给定字符集的InputStreamReader。
InputStreamReader读取数据的方法:
void read() 读一个字符
void read(char[] cbuf,int offset,int len)将字符读入数组的一部分

字符流的便捷方式

FileWriter fw = new FileWriter("");
FileReader fr = new FileReader("");
使用FileWrite和FIleReader
构造:
FileWrite(String filename);
FileReader(String filename);
注意:FileWrite和FIleReader只能使用平台默认的字符集

字符缓冲输出流""中是字节流目录或对象

BufferedWriter bw = new BufferedWriter(new FileWriter(""))
BufferedWriter bw = new BufferedWriter(new OutputStreamWrite(""))

方法:
newLine():表示换行符(不需要在关心使用的换行符是什么)

字符缓冲输入流""中是字节流目录或对象

BufferedReader br = new BufferedReader(new FileReader(""))
BufferedReader br = new BufferedReader(new InputSteamReader(""))
方法:
readLine():表示读取一行数据,不会读取换行符

对象流:

底层还是字节流
对象序列化:把对象信息持久化到文件之中,或者网络中进行数据传输
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(""))
对象反序列化:把文件中的对象信息持久化到对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(""))

序列化接口Serializable:起到了标识的作用,标识当前类可以进行序列化或反序列化没有方法或字段
类中没有自定义UID:序列化之后,如果一个类的结构发生改变,反序列化时,会出现会出现InvalidClassException:

 因为当序列化运行时检测到类中的以下问题之一时抛出。 
	1.类的串行版本与从流中读取的类描述符的类型不匹配 
	2.该类包含未知的数据类型 
	3.该类没有可访问的无参数构造函数 

UID:序列化时,系统默认分配的相关联的版本号(默认情况下,类的结构发生改变时,UID也会发生改变)

	序列化的类可以自定义UID(会把系统默认分配的UID覆盖)
	如果序列化的类自定义UID之后,如果UID没有发生改变,类结构发生改变时,不会出现1的问题

成员变量如何不被序列化?

给该成员加上一个transient关键字修饰,标识了该成员不参与序列化,(值为系统分配的默认值)
以下是代码实现: ```java import java.io.*; public class Example05 { public static void main(String[] args) { long startTime = System.currentTimeMillis(); // 记录开始时间 String sourcePath = "source/IO流.avi"; String targetPath = "target/IO流.avi"; byte[] buffer = new byte[1024]; // 缓冲区大小为 1KB try ( BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourcePath)); // 缓冲字节输入流 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetPath)); // 缓冲字节输出流 ) { int len; while ((len = bis.read(buffer)) != -1) { // 从输入流中读取数据到缓冲区中 bos.write(buffer, 0, len); // 将缓冲区中的数据写入到输出流中 } } catch (IOException e) { e.printStackTrace(); } long endTime = System.currentTimeMillis(); // 记录结束时间 System.out.println("文件拷贝完成,总耗时:" + (endTime - startTime) + "ms"); } } ``` 代码注释中已经解释了每一步的实现原理,说明如下: 1. 使用 BufferedInputStream 和 BufferedOutputStream 包装 FileInputStream 和 FileOutputStream,以实现缓冲读写文件的功能。 2. 定义一个字节数组作为缓冲区,缓冲输入流读取数据到缓冲区中,缓冲输出流从缓冲区中写出数据到目标文件中。 3. 使用 while 循环不断从输入流中读取数据到缓冲区中,直到读取到文件末尾(返回值为 -1),然后再将缓冲区中的数据写出到目标文件中。 4. 在 try-with-resources 语句中使用自动关闭流资源的方式,无需手动关闭流。 5. 记录开始和结束时间,计算文件拷贝总耗时并输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值