File类:
File类位于java.io.File
类,File类是文件和目录路径名的抽象表示,主要是用于文件和目录的创建、查找和删除等操作
在 Java 中,File 类是 java.io 包中唯一代表磁盘文件本身的对象。File 类定义了一些与平台无关的方法来操作文件,File类主要用来获取或处理与磁盘文件相关的信息,像文件名、 文件路径、访问权限和修改日期等,还可以浏览子目录层次结构。
File 类表示处理文件和文件系统的相关信息。也就是说,File 类不具有从文件读取信息和向文件写入信息的功能,它仅描述文件本身的属性。
几个方法:
File(String pathname) 通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
File(String parent,String child) 根据指定的父路径和文件路径创建一个新File对象实例
File(File parent,String child) 根据指定的父路径对象和文件路径创建一个新的File对象实例
boolean createNewFile();指定路径不存在该文件时创建文件,返回true 否则false
boolean mkdir() 当指定的单击文件夹不存在时创建文件夹并返回true 否则false
boolean mkdirs() 但指定的多级文件夹在某一级文件夹不存在时,创建多级文件夹并返回true 否则false
boolean delete() 删除文件或者删除单级文件夹
删除文件夹,这个文件夹下面不能有其他的文件和文件夹
boolean exists() 判断指定路径的文件或文件夹是否为空
boolean isAbsolute() 判断当前路径是否是绝对路径
boolean isDirectory() 判断当前的目录是否存在
boolean isFile() 判断当前的目录是否是一个文件
补充:boolean isHidden() 判断当前路径是否是一隐藏文件
File getAbsoluteFile() 获取文件的绝对路径,返回File对象
String getAbsolutePath() 获取文件的绝对路径,返回路径的字符串
String getParent() 获取当前路径的父级路径,以字符串形式返回该父级路径
String getName() 获取文件或文件夹的名称
String getPath() 获取File对象中封装的路径
long lastModified() 以毫秒值返回最后修改时间
long length() 返回文件的字节数
boolean renameTo(File dest) 将当前File对象所指向的路径修改为指定File所指向的路径
String[] list(); 以字符串的形式返回当前路径下所有的文件和文件夹的名称
File[] listFile 以File对象的形式返回当前路径下的所有文件和文件夹名称
补充:Static File[] listRoots() 获取计算机中的所有盘符
递归:
-
以编程的角度来看,递归指的是方法定义中调用方法本身的现象
-
把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
-
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算
-
递归注意事项:
-
以编程的角度来看,递归指的是方法定义中调用方法本身的现象
-
把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
-
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算
流的概念
在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成。
程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。
在java.io包中操作文件内容的主要有两大类:字节流、字符流。两类都分为输入和输出操作。在字节流中输出数据主要是使用OutputStream完成,输入使的是InputStream,在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。(这四个都是抽象类)。
字节流
InputStream
与OutputStream
是两个抽象类,是字节流的基类,所有具体的字节流实现类都是分别继承了这两个类。
字节流主要是操作byte类型数据,以byte数组为准。
流读写操作流程
操作流程:
在Java中IO操作也是有相应步骤的,以文件操作为例,主要的操作流程如下:
a 使用File类打开一个文件
b 通过字节流或字符流的子类,指定输出的位置
c 进行读/写操作
d 关闭输入/输出
IO操作属于资源操作,一定要记得关闭。
字符流:
字符输入流Reader和writer是
主要方法,常用于处理纯文本数据,读写容易出现乱码的现象,在读写时,最好指定编码集为UTF-8
字符流与字节流区别:
字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的。
字节流在操作文件时,即使不关闭资源(close方法),文件也能输出,但是如果字符流不使用close方法的话,则不会输出任何内容,说明字符流用的是缓冲区,并且可以使用flush方法强制进行刷新缓冲区,这时才能在不close的情况下输出内容
那开发中究竟用字节流好还是用字符流好呢?
在所有的硬盘上保存文件或进行传输的时候都是以字节的方法进行的,包括图片也是按字节完成,而字符是只有在内存中才会形成的,所以使用字节的操作是最多的。
如果要java程序实现一个拷贝功能,应该选用字节流进行操作(可能拷贝的是图片),并且采用边读边写的方式(节省内存)。
字节缓冲流:
节缓冲流介绍
lBufferOutputStream:该类实现缓冲输出流。 通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
lBufferedInputStream:创建BufferedInputStream将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节
补充方法:
startsWith() 方法用于检测字符串是否以指定的前缀开始。
语法:
public boolean startsWith(String prefix, int toffset)
或
public boolean startsWith(String prefix)
参数
-
prefix -- 前缀。
-
toffset -- 字符串中开始查找的位置。
特殊流:
四大类:标准输入/输出流,字节/字符打印流
特殊流的知识点:
两大构造方法:
PrintWriter(String fileName) | 使用指定的文件名创建一个新的PrintWriter,而不需要自动执行刷新 |
PrintWriter(Writer out, boolean autoFlush) | 创建一个新的PrintWriter out:字符输出流 autoFlush: 一个布尔值,如果为真,则println , printf ,或format方法将刷新输出缓冲区 |
对象序列化
Java的对象序列化是将Java对象转换成字节序列,二进制流。
这些字节序列可以保存在磁盘,或通过网络传输。并且可以将这种二进制流恢复成原来的Java对象。
对象的序列化(Serialize)是将JAVA对象写入IO流。
反序列化(Deserialize)是从IO流中恢复该java对象。
为了对象支持序列化,必须让它的类是可序列化的(serializable)。类必须实现下面两个接口之一:
- Serializable
- Externalizable
Serializable是一个标记接口,无需实现任何方法。只表明该类的实例是可序列化的。 -
序列化 使用场景
当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
当你想用套接字在网络上传送对象的时候;
当你想通过RMI传输对象的时候; -
序列化优点
①将对象转为字节流存储到硬盘上,当JVM停机的话,字节流还会在硬盘上默默等待,等待下一次JVM的启动,把序列化的对象,通过反序列化为原来的对象,并且序列化的二进制序列能够减少存储空间(永久性保存对象)。
②序列化成字节流形式的对象可以进行网络传输(二进制形式),方便了网络传输。
③通过序列化可以在进程间传递对象。
-
序列化与反序列化注意点
①序列化时,只对对象的状态进行保存,而不管对象的方法;
②当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
③当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
④并非所有的对象都可以序列化,至于为什么不可以,有很多原因了,比如:
安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行RMI传输等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的;
资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现;
⑤声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,transient代表对象的临时数据。
⑥序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。为它赋予明确的值。显式地定义serialVersionUID有两种用途:
在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;
在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。
⑦Java有很多基础类已经实现了serializable接口,比如String,Vector等。但是也有一些没有实现serializable接口的;
⑧如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存!这是能用序列化解决深拷贝的重要原因;