1.File
(1).File(String pathName)
Java.io.File用于表示文件(目录),也就是说可以通过File类在程序中操作硬盘上文件和目录。
File类只用于表示文件(目录)的信息(名称、大小等),不能对文件进行访问。
构造方法:
File(String pathname)
通过给定路径名字字符串转换成抽象的路径名来创建一个新File实例
抽象路径应尽量使用相对路径,并且目录的层级分隔符不要直接写“/”或”\”,应使用File.separator这个常量表示,以避免不同系统带来的差异。
/**
* File.separator表示在不同的系统的目录层级分隔符
* 为了忽略平台差异性,我们在写路径时应当使用该常量
* "."表示当前项目的根目录
*/
注: File不能访问文件内容
File file = new File("."+File.separator+"demo.txt");
File类对象的方法
方法 |
说明 |
boolean exists() |
判断当前File所表示的文件或目录是否真实存在 |
long length() |
获取当前文件在所占用的字节量 |
boolean canRead() |
判断该文件是否可有可读 |
boolean canWrite() |
判断该文件是否可写 |
boolean canExecute() |
判断文件是否可执行 |
long lastModified() |
获取当前文件(目录)最后修改时间 |
boolean isFile() |
判断当前File对象是否为一个文件 |
boolean createNewFile() |
创建该文件 |
boolean delete() |
删除该文件(目录) |
boolean mkdir() |
创建该目录(该目录所在的父级必须存在) |
boolean mkdirs() |
在创建当前目录时,会自动创建所有不存在的父级目录 |
boolean isDirectory() |
判断当前File对象是否为一个目录 |
listFiles()
File的listFiles()方法用于返回一个抽象路径名数组,这些路径名表示此次目录中的子项(文件或目录)。
File[] listFiles() 返回值:该目录下的文件或目录。如果目录为空,那么数组也为空。如果抽象路径名不表示一个目录,或者发生I/O错误,则返回null。
listFiles方法支持文件过滤器,实现FileFilter接口,要实现抽象方法:
boolean accept(File f)该方法要求我们定义过滤条件
public class FileDemo2 {
public static void main(String[] args) {
File dir = new File(".");
if(dir.isDirectory()){
//创建过滤器实例
FileFilter filter = new MyFilter();
//使用过滤器过滤子项
File[] subs = dir.listFiles(filter);
}
}
}
class MyFilter implements FileFilter{
public boolean accept(File file) {
return file.getName().startsWith(".");
}
}
File getParent() 获取当前文件(目录)所在的父目录
创建文件时,先判断当前文件所在的目录是否存在若不存在,会抛出异常
(2).RandomAccessFile类
Java提供了一个可以对文件随机访问的操作(读/写)的类。该类为RandomAccessFile,该类的读写是基于指针操作。
RandomAccessFile总是在当前指针的位置读写字节。
RandomAccessFile在对文件进行随机访问操作时有两个模式,分别是只读模式(只读取文件数据),和读写模式(对文件数据进行读写)。
在创建RandomAccessFile时,其提供的构造方法要求我们传入访问模式:
RandomAccessFile(File ,String mode)
RandomAccessFile(String filename ,String mode)
其中构造方法第一参数是需要访问的文件,第二个参数是访问模式
r: “r”表示只读
rw: “rw”表示读写
在读写数据时,若想提高读写效率,就必须减少读写次数。
void write(int n) 写出给定int值的”低8位“(一个int值有4个字节共32位)只写一个字节。
int read() 从当前文件中读取一个字节,将该字节存入返回的int值中,int值的”低8为“有效。(若返回值是-1,则说明读取到了文件的末尾,EOF end of file,注:如果写入了-1,在读取的时候,会读到255)。
public void close() 关闭这个流
批量写:
void write(byte[] d) 根据当前指针所在位置处连续写出给定数组中的所有字节。
void write(byte[] d, int offset , int len) 根据当前指针所在位置处连续写出给定数组中的部分字节,这个部分是从数组的offset处开始,连续len个字节。
注:这个字节数组,下一次从目标文件中读取数据时,若目标文件中剩余的数据大小大于字节数组d的大小,则该字节数组元素会被全部覆盖完(更新完),若目标文件中剩余数据大小比字节数组d的长度小,则不能全部覆盖更新整个字节数组,剩余的数据有多大,就更新多大长度的字节数组(前半部分),字节数组中没有覆盖更新的部分(后半部分),还是上次读到的数据。所有要用write(byte[] d, int offset , int len)
批量读:
int read(byte[] buf) 一次尝试从文件中读取buf数组的length个字节并从该数组的第一个位置,处起存放实际读取到的字节。返回值为实际取到的字节数。
向文件中写入基本类型数据
RandomAccessFile raf = new RandomAccessFile("raf.dat","rw");
int num = Integer.MAX_VALUE;
raf.writeInt(num);
查看RandomAccessFile的指针位置RAF总是根据当前指针所指向的位置读或者写操作的,并且每次读写后,指针自动向后移动
long getFilepointer() 获取当前raf的指针位置。
void seek(long position) 若想从文件的某个地方读取字节,需要先将指针移到这个位置(若用同一个raf)。
int skipBytes(int n) 该方法尝试跳过n个字节,返回值为实际跳过的字节数,只能向后跳。
2.IO基本操作
输入:是一个从外界进入到程序的方向,通常我们需要”读取“外界的数据,使用输入。所以输入是用来读取数据的。
输出:是一个从程序发送到外界的方向,通常我们需要”写出“数据到外界,使用输出。所以输出是用来写出数据的。
节点流与处理流
按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流
节点流:可以从或向一个特定的地方(节点)读写数据。通常节点流也称之为低级流。
处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。
处理流的构造方法总是要带一个其他流对象做参数。通常也称为高级流或过滤流。
流的链接:一个流对象经过其他流的多次包装,称之流的链接。
(1).IS和OS(inputStream、outputStream)字节流
OutputStream和InputStream是抽象类,不能直接实例化,是所有字节输入流和输出流的父类。
InputStream是所有字节输入流的父类,常用方法如下:
int read() 读取一个字节,以int 形式返回,该int值的”低8位“有效,若返回值为-1,则表示EOF(end of file)到了文件末尾。
int read(byte[] d) 尝试最多读取给定数组的length个字节并存入该数组,返回值是实际取到的字节量。
OutputStram是所有字节输出流的父类,常用方法如下:
void write(int d) 写出一个字节,写的是给定的int的”低8位“
void write(byte[] d) 将给定字节数组中的所有字节全部写出。
a.文件输入输出流
FileInputStream,重写FIS对象
继承于InputStram是文件的字节输入流,以字节为单位将数据读入到程序中
构造方法:
FileIutputStream(File file) 创建一个向指定File对象表示的文件中读入数据的文件输入流。
FileIutputStream(String filename)创建一个向具有指定名称的文件中读入数据的文件输入流。
FileOutputstream,重写FOS对象(重写模式)
是文件的字节输出流,以字节为单位将数据写入文件
构造方法:
FileOutputStream(File file) 创建一个向指定File对象表示的文件中写出数据的文件输出流。
FileOutputStream(String filename)创建一个向具有指定名称的文件中写出数据的文件输出流。
注:若指定的文件已经有内容了,那么当使用FOS对其写入数据时,会将该文件中原有的数据全部清除。
FileOutputStream(String str, boolean append)第二个参数指定是否进行追加写操作,若不追加,当前文件中的所有内容都会被清除,然后重写数据。要注意的是这一点和RandomAccessFile不同;若第二个参数为true,则在进行写操作时,则会在该文件之前的内容中追加内容。
FileOutputStream(String str) 类似于FileOutputSteam(String str, boolean false) 写操作时清除之前的内容。
FileInputSteram类似
b.BufferedOutputStream和BufferedInputStream
BOS基本原理
在向硬件设备做写操作时,增大写出次数无疑会降低写出效率,为此我们可以使用缓冲输出流来一次性批量写出若干数据减少写出次数来提高写出效率
BufferedOutputStream 缓冲输出流内部维护着一个缓冲区,每当我们向该流写数据时,都会先将数据存入缓冲区,当缓冲区已满时,缓冲流会将数据一次性全部写出。
BufferedInputStream 缓冲输入流
注:关闭流时,只关闭最外层的流
BufferedOutputStream的void flush() 无论缓冲区是否被装满,强制将当前缓冲流中的缓冲区中的数据全部写出。
若调用了close()方法,则该方法会首先调用flush();若强调数据的及时性,不管数据有多短,都要马上写入,则要调用flush()(不等buffer装满,直接去写入)
若:将int值的数据保存到硬盘上,要经历2个步骤,
I. 将int值转换为一组字节;
II.将这组字节写入到硬盘长期保存;
上面这一过程,涉及到两个概念
序列化:将一个特定的数据结构转换为一组字节的过程,称之为,序列化。
持久化:将数据写入到硬盘上进行长久保存的过程。称之为,持久化。
序列化与反序列化:用于传输和保存。
注:transient 当一个类实现了Serializable,这个类可以被序列化,而这个类的某些属性不需要被序列化(例如:密码)后持久化到硬盘,就可以用transient来修饰。
c.ObjectOutputStream和ObjectInputStream
用于对象序列化,高级流
ObjectOutputStream 用于对象的序列化,高级流。
void writeObject(Object 0) 可以将给定对象转换为一组字节后写出。
注:该对象对应的类一定要实现Serializable接口。
public static void main(String[] args) throws IOException{
List<String> list = new ArrayList<String>();
list.add("家住在北京");
list.add("汉族");
list.add("其他信息");
Person person = new Person("张三",22,'男',2000,list);
FileOutputStream fos = new FileOutputStream("person.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
/*
* void writeObject(Object 0)
* ObjectOutputStream提供的方法,可以将给定对象
* 转换为一组字节后写出
*/
oos.writeObject(person);
oos.close();
}
ObjectInputStream 用于对象的反序列化,高级流
public static void main(String[] args) throws ClassNotFoundException, IOException{
FileInputStream fis = new FileInputStream("person.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
Person p = (Person)ois.readObject();
System.out.println(p);
ois.close();
}
注:
/**
* version 1.0
* 当类的属性增加或修改了,若版本号不变那么反序列时会
* 尽可能兼容现有的版本;若版本号发生了变化,那么反序列化
* 时会发生异常。
*/
private static final long serialVersionUID = 1L;
(2).字符流
Reader是字符输入流的父类
Writer是字符输出流的父类
字符流是以字符(char)为单位读写数据。一次处理一个Unicode。
字符流的底层仍然是基本的字节流
Reader常用方法
int read() 读取一个字符,返回的int值”低16位“有效
int read(char[] chs) 从该流中读取一个字符数组的length个字符存入该数组,返回值为实际读取到的字符量。
Writer常用方法
void Write(int c) 写出一个字符,写出给定int值”低16位“表示的字符
void write(char[] chs) 将给定字符数组中所写的字符写出
void write(String str) 将给定的字符串写出
void Write(char[] chs, int offset, int len) 将给定的字符数组从offset处开始连续的len个字符写出
字符转换流原理
InputStreamReader 字符输入流
使用该流可以设置字符集,并按照指定的字符集从流中按照该编码将字节数据转换为字符并读取。
OutputStreamWriter 字符输出流
使用该流可以设置字符集,并按照指定的字符集将字符转换为对应字节后通过该流写出。
PrintWriter 缓冲字符输出流
创建PW对象
PrintWriter是具有自动行刷新的缓冲字符输出流。提供了比较丰富的构造方法:
PrintWriter(File file)
PrintWriter(String fileName)
PrintWriter(OutputStream out)
PrintWriter(OutputStream out,boolean autoFlush)
PrintWriter(Writer writer)
PrintWtiter(Writer writer,boolean autoFlush)
其中参数为OutputStream与Writer的构造方法提供了一个可以传入boolean值参数,该参数用于表示PrintWriter是否具有自动行刷新。
public static void main(String[] args) throws FileNotFoundException, Exception{
FileOutputStream fos = new FileOutputStream("pw.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
/**
* 创建具有自动行刷新的PrintWriter后
* 每当我们用println方法写出字符后,都会自动flush,
* 但一定要清楚:这无疑会增加写出次数而降低写出效率
*/
PrintWriter pw = new PrintWriter(osw,true);
pw.println("我爱北京天安门");
pw.println("快使用双节棍");
pw.close();
}
构建BufferedReader
BufferedReader是缓冲字符输入流,其内部提供了缓冲区,可以提高读取效率
构造方法:
BufferedReader(Reader reader)
可以以行为单位读取字符串
public static void main(String[] args) throws Exception{
FileInputStream fis = new FileInputStream("pw.txt");
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
BufferedReader br = new BufferedReader(isr);
/*
* String readLine()
* 一次读取以行字符串,该方法会判断读取到换行符为止,将之前的
* 一行字符串返回
* 若该方法返回的字符串味null,说明没有数据可读了
*/
String str = null;
while((str=br.readLine()) != null){
System.out.println(str);
}
}