IO学习总结

目录

一、File类

1.构造方法:

2.方法:

2.1创建:

2.2删除:

2.3获取:

2.4判断:

2.5获取:

2.5修改:

3.字段:

4.文件夹遍历:

5.文件过滤:(了解)接口FileFilter

 6.相对和绝对路径:

二、IO流概述

1.OutputStream(字节流--输出流)抽象类

 1.1方法:

2.FileOutputStream---常用

 3.异常

4.InputStream字节输入流---常用

4.1方法:

5.FileinputStream

5.1构造器:

 5.2方法:

5.2.1 Read()

5.2.2read​(byte[] b)

6. 字符输出writer-------(OutputStream字节输出)

6.1构造方法:

6.2方法:

 7.Filewriter-------(字节输出FileOutputStream)

构造方法: 

8.字符流Reader读取输入)-----inputStream(字节流)

8.1构造方法:

8.2方法:

9.FileReader字符输入--------------FileInputStram(字节输入)

10. Flush刷新管道

 11.转换流InputStreamReader和OutputStreanmReader

11.1InputStreamReader(读取):字节输入转字符输入

11.2 OutputStreanmReader:字节输出转字符输出

12. Print与BufferedReader

12.1Print字符打印流

12.2字节流也可以转换为打印

12.3BufferedReader缓存读取流

 13.收集异常日志

14.Properties文件类

 15.序列化和反序列化技术:

15.1 ObjectOutputStream和ObjectInputStream

 15.2SeriaLizable(序列化接口--标记)

16. Try-with-resources

15.3 部分属性的序列化和反序列化:

4种方式:

15.3.3.writerObject和readObject两方法,实现Serializble类里

 15.3.4Externalizable实现序列化:

16. Serializable VS Externalizable


一、File类

表示文件和目录路径名的抽象表示。

文件夹:

文件(名):

路径:路径表示文件夹:C:\Users\Administrator\Desktop\java笔记

也可以表示具体的文件:C:\Users\Administrator\Desktop\Hellow Word.docx

1.构造方法:

可实例化(new对象)

构造器

描述

File​(File parent , String child)

从父抽象路径名和子路径名字符串创建新的 File实例。

File​(String pathname)

通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。

File​(String

parent , String child)

从父路径名字符串和子路径名字符串创建新的 File实例。

File​(URI uri)

通过将给定的 file: URI转换为抽象路径名来创建新的 File实例。

 File​(String pathname):参数:文件路径--此对象只表示文件路径

File​(File parent , String child):文件路径对象下创建

File​(String parent , String child):文件路径创建

区别:

File parent:把路径封装成了对象

String parent :路径用字符串表达

2.方法:

2.1创建:

创建文件

boolean

createNewFile()

当且仅当具有此名称的文件尚不存在时,以原子方式创建由此抽象路径名命名的新空文件。

True,指定文件不存在并创建成功,false指定文件存在没有创建

如果磁盘受保护拒接访问,会抛出异常IO异常(受监测的)

1:使用编译器时用管理员身份运行

2:如果1不能解决换其他盘

创建文件夹

boolean

mkdir()

创建此抽象路径名指定的目录。

 创建的是最后一个haha,但是最后一个haha,没有其父haha,创建是失败的(中间的文件夹不存在)-------------------------------------即指定创建的文件夹的目录中间有些不存在

boolean

mkdirs()

创建此抽象路径名指定的目录,包括任何必需但不存在的父目录。

 创建的是最后一个haha,但是最后一个haha,没有其父haha,中间的文件夹不存在,创建时会自动补齐不存在的文件夹

2.2删除:

boolean

delete()

删除此抽象路径名表示的文件或目录

 表示删除路径下的内容可能是文件可能是文件夹具体看创建的file对象表示什么

2.3获取:

String

getAbsolutePath()

返回此抽象路径名的绝对路径名字符串。

返回绝对路径字符串

String

getName()

返回此抽象路径名表示的文件或目录的名称。

返回文件名

String

getParent()

返回此抽象路径名父项的路径名字符串,如果此路径名未指定父目录,则返回 null 。

 

返回null则表示到了盘符最开始,------D盘

File

getParentFile()

返回此抽象路径名父项的抽象路径名,如果此路径名未指定父目录,则返回 null 。

long

length()

返回此抽象路径名表示的文件的长度。

 表示文件的长度(文件大小)以字节为单位,最大只能获取2g的文件大小,因为返回值类型long使用4个字节大小来表示,最大为2的31次方也就是2G的大小

2.4判断:

boolean

exists()

测试此抽象路径名表示的文件或目录是否存在。

是否是文件或文件夹

boolean

isDirectory()

测试此抽象路径名表示的文件是否为目录。

是否是文件夹

boolean

isFile()

测试此抽象路径名表示的文件是否为普通文件。

是否是文件

2.5获取:

String[]

list()

返回一个字符串数组,用于命名此抽象路径名表示的目录中的文件和目录。

获取文件夹里所有文件------所有文件指文件or文件夹返回一个String类型的数组---以路径形式存在

File[]

listFiles()

返回一个抽象路径名数组,表示此抽象路径名表示的目录中的文件。

 获取此路径下文件夹里所有文件------所有文件指文件or文件夹返回一个file类型的数组一对象为单位存储

File[]

listFiles​(FileFilter filter)

返回一个抽象路径名数组,表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。

获取传进来的,文件夹里的所有对象,返回一个数组

2.5修改:

boolean

renameTo​(File dest)

重命名此抽象路径名表示的文件

RenameTo:表示某个文件从所在路径目录下,剪切到 ,指定目录下并改名

注意是剪切!谁调用谁是被剪切的。参数表现新的地方新的名字即新路径

3.字段:

在不同系统中,表示文件路径的符号不一样,Java统一了。

static String

pathSeparator

与系统相关的路径分隔符,为方便起见,表示为字符串。 分号 ;

static char

pathSeparatorChar

与系统相关的路径分隔符。

static String

separator

系统相关的默认名称分隔符,为方便起见,表示为字符串。斜杠\

static char

separatorChar

系统相关的默认名称分隔符。

如何使用?都是静态的

4.文件夹遍历:

需要传入一个FIle数组类型

通过上面的方法可得到

判断这个数组不是空的,且有内容(大小)

遍历这个数组

判断是否是文件

 是文件:

 判断文件名是不是以.avi结尾的,是输出,文件所在的路径字符串

不是文件:

 创建一个新数组,把不是文件的文件夹,通过listFiles()获取到里面的所有文件(可能有文件也可能有文件夹),递归调用自己------过滤不是文件的

 

 如果是文件,也是以.avi结尾的,判断其大小。100*1024*1024  100KB

1*1024 = KB

1*1024*1024 = MB

5.文件过滤:(了解)接口FileFilter

String[]

list​(FilenameFilter filter)

返回一个字符串数组,用于命名由此抽象路径名表示的目录中的文件和目录,以满足指定的过滤器。

File[]

listFiles​(FileFilter filter)

返回一个抽象路径名数组,表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。

FileFilter:是一接口需要被实现

使用方式类似于Comparable比较器

通过Flie对象获取文件中的内容时,加入一个过滤器对象,在过滤器对象里描述过滤规则

1.写一个类去实现过滤器,类里面重写抽象方法

 2.创建过滤器(多态的形式)

 

 3.通过文件获取文件夹

 此方法返回file所有文件,包括文件夹和文件

4.走过滤器,怎么走?

传入过滤器,返回到数组里的就是过滤后的

 总结:

通过一个类去实现过滤器,并重写过滤规则。然后创建过滤器,通过过滤器的方法

List和listfiles,参数里传入过滤器,即可达到过滤的效果,返回过滤后的file[]

注意只是获取,而非过滤删除。需要其他操作后续判断调用其他方法

也可以使用匿名内部类使用一次的话

创建对象的时候以接口名创建,并在对象后面重写方法

 

还可以参考Compatator:

在需要传入过滤器的地方重写,new 一个过滤器并重写方法

 6.相对和绝对路径:

绝对路径:从盘符号开始是一个完整的路径例如: c://a.txt有盘符

相对路径:相对?----在JAVA代码中是相对于项目目录路径,这是一个不完整的便捷路径,在JAVA开发中很常用。

 例如:a.txt

盘符在哪?在你使用的程序包里

 

在项目文件夹里

 

 

 创建的时候不加盘符,就是创建在你项目下的

相当于这里创建

二、IO流概述

什么是IO流?

In流入

Out就出

例如:复制从某个盘到另一个盘

下载文件到电脑中。

都是数据在传输,可以将这种数据传输的操作,看做数据的流动,从C盘到D盘,

按照流动的方向分为输入Input和输出Output

Input:输入到电脑

Output:从电脑输出

电脑只是举例的基点

c盘到d盘,具体分析,c是流出,d是流入,是相对的。

体现在数据流动

Java中io操作主要指的是java.io包下的一些常用类的使用,通过这些类,对数据进行读取(输入流input),写出输出output

IO流分类

按照流的方向:输入流和输出流

按照流动的数据类型分:字节流和字符流

字节流:(主要划分以类的结构划分)

--输入流:顶级的父类 inputStream

--输出流:顶级的父类outoutStream

字符流:(也是来自于字节流,不过是被处理后的)

--输入流:顶级的父类reader

--输出流:顶级的父类writer

1.OutputStream(字节流--输出流)抽象类

一切皆字节:计算机中的任何数据都是以字节存储的(文本、图片、视频、音乐等等)都是以二进制的形式存储的。

在数据传输时,也都是以二进制存储的。

任何流,在传输时,底层都是二进制。

 1.1方法:

    • voidclose()

      关闭此输出流并释放与此流关联的所有系统资源。

      voidflush()

      刷新此输出流并强制写出任何缓冲的输出字节。

      static OutputStreamnullOutputStream()

      返回一个新的 OutputStream ,它丢弃所有字节。

      voidwrite​(byte[] b)

      b.length字节从指定的字节数组写入此输出流。

      voidwrite​(byte[] b, int off, int len)

      将从偏移量 off开始的指定字节数组中的 len字节写入此输出流。

      abstract voidwrite​(int b)

      将指定的字节写入此输出流。

 Close:每次使用完流都要使用这个方法

write​(byte[] b, int off, int len),将从偏移量 off开始的指定字节数组中的 len字节写入此输出流。 

从某个下标开始写多少个,而不是从某个下标开始到某个下标结束

 public abstract void write​(int b) throws IOException

将指定的字节写入此输出流。 write的一般合同是将一个字节写入输出流。 要写入的字节是参数b的八个低位。 b的24个高位被忽略。

OutputStream子类必须提供此方法的实现

要写入的字节是参数b的八个低位b的24个高位被忽略

int = 4个字节b = 32bit

1个字节b = 8个比特位bit

 

前面是被忽略的只看后面8位 最大是  二进制 11111111   十进制 255  即int不能超过255

  其子类无论哪一个写数据 就这3个write方法写完要关闭他!

2.FileOutputStream---常用

OutputStream的子类可实例化,但是还是用到其子类

文件输出流是用于将数据写入File或FileDescriptor的输出流。

每一个fileoutputStream对象就表示向某个文件的输出流管道

构造方法:

构造器

描述

FileOutputStream​(File file)

创建文件输出流以写入由指定的 File对象表示的文件。

FileOutputStream​(FileDescriptor fdObj)

建要写入指定文件描述符的文件输出流,该文件描述符表示与文件系统中实际文件的现有连接。

FileOutputStream​(File file, boolean append)

创建文件输出流以写入由指定的 File对象表示的文件。

FileOutputStream​(String name)

创建文件输出流以写入具有指定名称的文件。

FileOutputStream​(String name, boolean append)

创建文件输出流以写入具有指定名称的文件。 

常用的有4个2组

红色:file传入文件对象来建立这个输出流

蓝色:String传入文件路径来建立

boolean append:true表示是否接着原来的写,false表示清空后在写,运行2次

第一次添加后,在运行添加,默认清空

运行一次:

如果一个对象,添加2次是接着的直到关闭前都是append追加的

运行两次:

第二次不会接着第一次的写,只有true,才会表示追加上一次执行的写
字节流写的是byte字节,byte[]数组

方法:3个write方法

 3.异常

文件没有(虽然会自己创建但是会有权限不允许的时候)

 属于IOexception子类

65输出的是A------65是byte类型而不是Int

记住记住要关闭流

流关闭以后就不要再去写了,否则会报IO异常

4.InputStream字节输入流---常用

4.1方法:

abstract int

read()

从输入流中读取下一个数据字节。

int

read​(byte[] b)

从输入流中读取一些字节数并将它们存储到缓冲区数组 b 。

 返回-1读完了 范围0-255子类fileinputStream

5.FileinputStream

5.1构造器:

FileInputStream​(File file)

通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的 File对象 file命名。

FileInputStream​(FileDescriptor fdObj)

使用文件描述符 fdObj创建 FileInputStream ,该文件描述符表示与文件系统中实际文件的现有连接。

FileInputStream​(String name)

通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的路径名 name命名。

 5.2方法:

int

read()

从此输入流中读取一个字节的数据。

int

read​(byte[] b)

从此输入流 b.length最多 b.length字节的数据读 b.length字节数组。

int

read​(byte[] b, int off, int len)

从此输入流 len最多 len字节的数据读入一个字节数组。

long

skip​(long n)

跳过并从输入流中丢弃 n字节的数据。

返回值是int,用byte表示需要强转过来 不然读取的就是int类型

 

Char + 数字 输出  数字对应ascii表里的字符

Byte + 数字 输出  数字

Char + 字符 输出 字符

Byte + 字符 输出 字符对应asci表里的数字

Char 输出字符 byte输出数字

字节流读取的是byte字节,需要转成字符char

5.2.1 Read()

 第一次读第一个第二次读第二会自动读取下一个,超过长度会依旧循环只是读取不到返回-1

(不像迭代器,先判断)是个死循环!

怎么解决死循环?加入判断,在不考虑知道文件长度通过length()方法,记得关闭流!

5.2.2read​(byte[] b)

 参数是表示返回到byte数组

但是此方法每次读10个最后一次,自己补了4个qrst

为什么?

每一次读取,放在同一个数组里,相当于读取之后复制过去,而最后一次只有4个,也就只复制了前6个!

例如:有时候下载文件都会大一些,就是因为每一次读取不有关注实际读取的量有一小丢丢是旧数据

怎么办?

返回值是int,表示读取的数量(大小) -1表示读完了、

6. 字符输出writer-------(OutputStream字节输出)

 由于字节读取文字,是拼接的存在读取一半的情况

所有需要字符流

本质上也是字节流,只是把他封装了,不会出现一半的情况

只用于操作文字

6.1构造方法:

protected

Writer()

创建一个新的字符流编写器,其关键部分将在编写器本身上同步。

protected

Writer​(Object lock)

创建一个新的字符流编写器,其关键部分将在给定对象上同步。

6.2方法:

void

write​(char[] cbuf)

写一个字符数组。

abstract void

write​(char[] cbuf, int off, int len)

写一个字符数组的一部分。

void

write​(int c)

写一个字符。

void

write​(String str)

写一个字符串。

void

write​(String str, int off, int len)

写一个字符串的一部分。

 7.Filewriter-------(字节输出FileOutputStream)

构造方法: 

FileWriter​(File file, boolean append)

在给出要写入的 FileWriter下构造 File ,并使用平台的 default charset构造一个布尔值,指示是否附加写入的数据。

 

 上面提到的append都是参数

Append()方法----追加一段文字(运行2次,不是基于源文件的内容追加)

 方法的调用会返回调用方法的对象

 强转,返回的是其父类writer

true

 所以:

 

 追加的原因也在,对象继续调用方法

8.字符流Reader读取输入)-----inputStream(字节流)

8.1构造方法:

protected

Reader()

创建一个新的字符流阅读器,其关键部分将在阅读器本身上同步。

protected

Reader​(Object lock)

创建一个新的字符流阅读器,其关键部分将在给定对象上同步。

8.2方法:

abstract void

close()

关闭流并释放与其关联的所有系统资源。

int

read()

读一个字符。

int

read​(char[] cbuf)

将字符读入数组。

Int -1 表示尾部没有内容了,否则则是数据大小长度

9.FileReader字符输入--------------FileInputStram(字节输入)

Reader的子类filereader

 

 可以通过循环输出读取完所有文字

 读取数组

 

10. Flush刷新管道

字节不需要!

字符输出时以字符为单位输出(由字节包装),如果是半个字符就缓存起来,

从内存到硬盘有一个缓存(从流入in到流出out)

字符输出会加flush()强制把缓存的内容输出.

缓存:UTF-8编码下的中文并非两个字节,是三个字节计算机是以字节储存,字符输出要读满一个文字的3个字节,在输出。不同的编码所占字节不一样。不满3个字节,会缓存起来。

 在关闭时会自己调用一次刷新即cloes()方法

 11.转换流InputStreamReader和OutputStreanmReader

字节流‘装饰’为字符流:使用了装饰者设计模式。

11.1InputStreamReader(读取):字节输入转字符输入

构造方法:

参数1:1参:需要转换的字节流

 参数2:两参:指定编码名称

11.2 OutputStreanmReader:字节输出转字符输出

字节输出转字符输出写出

12. Print与BufferedReader

12.1Print字符打印流

 向指定文件输出

12.2字节流也可以转换为打印

 以后往某个位置输出字符,建议转为打印流

12.3BufferedReader缓存读取流

在网上读取文本,

1把字节转成字符流在去读取,

2也可以创建字符流去读取

3缓冲读取流:将字符输入流转换为带有缓冲可以一次读取一行的缓冲字符读取流。只能用于字符流,字节流不可以!

 本来是一个一个字符读取,通过缓存字符流,有个缓存,一行一行的读取

 ReadLin()

多了一个读取一行的字符串方法,返回读取到的内容,null表示没有内容

之前只有一次读一个字符,或者读一个Byte数组,返回数组长度,-1表示没有内容

 13.收集异常日志

 打印字符流,没有append(参数里没有true)-----程序停止在启动会清空

14.Properties文件类

在把程序的内存保存到文件时,格式很难把控,所以会用到Properties类

后续还会有:XML,JSON

也属于Map集合体系下的内容

自己做了扩展。与IO有关
因为属于Map集合存储格式也是一对键值!

所以可以当做集合使用,不过是文件其添加与删除查找与Map集合方法一样。

用来与流建立关系。

文件里每一行都是一个建值对,

Load(一参)

传入一个字符流或字节流,输入

把properties文件内容加载成程序中的Map集合


 

Store(两参)

把Map集合变成properties文件并按照其格式进行存储

参数:properties文件集合,String表注释

 1.创建了一个properties对象,其存储格式以Map集合一样一对键值对

2创建了字符输出流

格式:

#表示注释,参数里的String

存储的是以键=值的形式

因为Java使用Unicode表不允许使用中文

包括键值对也不建议是中文

为什么?

Properties继承自Hashtable ,所以put和putAll方法可以应用于Properties对象。 强烈建议不要使用它们,因为它们允许调用者插入其键或值不是Strings 。 应该使用setProperty方法。 如果在包含非String键或值的“受损” Properties对象上调用store或save方法,则调用将失败。 同样,如果在包含非String密钥的“受损” Properties对象上调用,则对propertyNames或list方法的调用将失败。

 15.序列化和反序列化技术:

序列化:简单来说,就是把对象写入文件

反序列化:把对象从文件中读取到程序

------

在内存里创建对象,对象被垃圾回收就没了,就算是静态的程序关闭也就没了。

那能不能把对象存在文件里面,下次运行把对象拿过来?

序列化:就是把程序中的对象,以文件的形式存储。按照对象在内存中的字节序列存储的,是一堆乱码。指把Java对象转换为字节序列的过程。

反序列化:把对象从文件中读取回来是反序列化,指把字节序列恢复为Java对象的过

程。

通过序列化和反序列化实现网络传输、本地存储的目的。

场景:

安卓手机直接给服务器发一个对象,服务器拿过去就能使用。

服务器与服务器之间用对象交流会更方便。--分布式

但是在未来可能会被官方取消,因为从出现到现在官方收到了很多关于它的bug,准备不在使用。

----------------

 如何使用?

15.1 ObjectOutputStream和ObjectInputStream

 ObjectOutputStream序列化(输出)

 

 这样会出bug

 

BOOK不能序列化异常,为什么?

官方有时候不想让所有的类进行序列化,就决定所有的类都不能被序列化。想要它能序列化,就加一个标记实现一个接口 SeriaLizable

 15.2SeriaLizable(序列化接口--标记)

 标记接口,没有提供任何抽象方法

 序列化之后对象在文件中存储

 反序列化:

 在读取文件中的对象时,如果程序不存在或不匹配,读取这的个类是会抛出异常的,

readObject()读取后会返回一个Object对象

抛出的异常

 

 完整:

 

 同时接收的Object对象可以强转为book,得到Book对应的一个属性

注意: 

 1:Book里可能也有其他类

 

 Book里包含了没有实现Serializable接口的Person,同样会报错,book和其属性都要实现这个接口。

 2:如果文件存的不是一个对象,而是一个对象的集合,读取的也是集合。

16. Try-with-resources

 这里的关闭不合理。为什么?

在输出前语句前的2行代码出现异常直接跳到了catch,并没有走close()

会想到finally,但是finally不能访问try语句块里创建的对象

 可能会写成这样:但是很麻烦

----------------------------------------------------------------------------------------------------------------------------- 

JDK1.7

可以在try(创建对象){}catch{},finally里的内容就会自动执行,自己会关闭流

 Try()的括号里创建对象的类需要实现两个接口

里面有抽象方法,在执行时自动调用其实现类重写方法

但还是有不合理,如果这个new 的字符读取流对象是参数,是没办法关闭

 JDK9进行了优化

 

补:SeriaLizable  ID(序列化接口ID--标记)

在标记的实体类,如果序列化的A版本只有3个属性。

在系统升级为B版本时,需要添加新的属性此时直接添加是反序列化不出来的,系统不能运行,或者反序列化失败。

没有定义SerializableID或者SerializableID不一样了都会导致这个问题

怎么解决?

SeriaLizable  ID

 

主要是让你这个对象有唯一的标识!就是说序列化和反序列话后要保持版本一致

15.3 部分属性的序列化和反序列化:

4种方式:

15.3.1.transient修饰词不参与序列化,在序列化的过程中

15.3.2.反序列化后类中static型变量的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的

在序列化完成后修改static变量,反序列化出来的值是取的JVM的更改后的static变量。

所以static 修饰的变量,是不参与序列化的

15.3.3.writerObject和readObject两方法,实现Serializble类里

 

 

 这两个方法,如果写了,在序列化和反序列化是自己会调用。需要序列化的就写在里面

 15.3.4Externalizable实现序列化:

通过实现Eexternalizable接口。

Externalizable继承自Serializable,使用Externalizable接口需要实现readExternal方法和

writeExternal方法来实现序列化和反序列化

实现接口:

方法重写

16. Serializable VS Externalizable

Externalizable必须重写其抽象方法,并且实现Externalizable接口

而writerObject和readObject实现Sernalizable接口,不一定要重写方法

---------------------------------------------------------------------------------------------------------------------------------

得多敲敲Demo才能记住。

Go for it

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值