将JAVA中的文件相关的API进行整理:
- File
- RandomAccessFile
- FileInputStream、FileOutputStream
- BufferedInputStream、BufferedOutputStream
- ObjectInputStream、ObjectOutputStream
- InputStreamReader、OutputStreamWriter
- BufferedReader、BufferedWriter
- PrintWriter
字节流(低级流):以XXStream结尾的为字节流
字符流(高级流):以XXReader或XXWriter结尾的
File
java.io.File
File的每一个实例都可以用来表示文件系统中的一个文件或者目录。
使用File可以:
1.访问文件或目录的属性(名字、大小、修改时间等)。
2.操作文件或目录(创建、删除)。
3.访问一个目录的子项,但是不能读写数据。
使用File时的路径尽量选取相对路径,不同系统的路径方式不同,相对路径可以做到跨平台,
eclipse(2019)的“./”是当前项目工程所在的目录。
File相关的API
// 创建file对象
File file = new File("./a.txt");
// 获取文件名称
String name = file.getName();
// 获取文件路径
String path = file.getPath();
// 读取大小(字节数)
long len = file.length();
// 可读 可写
boolean canRead = file.canRead();
boolean canWrite = file.canWrite();
// 文件是否隐藏
boolean ih = file.isHidden();
// 获取file的父路径
String pPath = file.getParent();
// 获取父目录的file对象
File file1 = file.getParentFile();
// 判断文件是否存在
boolean exists = file.exists();
// 判断file对象是文件还是目录
boolean dirboo = file.isDirectory();
// 创建文件
if(!exists)
file.createNewFile();
// 创建单级文件夹
if(!exists)
file.mkdir();
// 创建多级目录
if(!exists)
file.mkdirs();
// 删除文件
file.delete();
// 获取文件下的所有文件对象
File files[] = file.listFiles();
// listFiles重载方法,指定文件过滤器,将满足过滤条件的子项返回,不满足则忽略.
files = file.listFiles(new FileFilter() {
public boolean accept(File file) {
return file.getName().endsWith(".java");
}
});
/*
* 删除文件夹,和删除文件一样(前提是空文件夹)
* 删除多级目录:
* 由于delete()方法删除目录时要求必须是一个空目录.
* 那么实际情况中,我们需要先将需要删除目录清空才可以删除
* 删除给定的file表示的文件或目录,使用递归调用:方法内部调用自己的方法的现象,
* 称为递归调用.递归现象必须在一个分支中控制.
*/
public static void delete(File file) {
if(file.isDirectory()) {
File [] files = file.listFiles();
for(int i = 0; i < files.length; i++) {
FileDemo.delete(files[i]);
}
}
file.delete();
}
RandomAccessFile:
java.io.RandomAccessFile
该类设计用来专门读写文件数据。基于指针进行读写,即总是在指针当前位置读或写字节。RAF有两种常用创建模式:
“r”:只读模式,"rw":读写模式。
注意:使用此对象不论对文件内容进行读还是写操作,指针都会移动,如果要向某个文件进行先写,后读操作,中间写完成后,必须seek(0)(将指针移到文件开头)。
/*
* RAF常用创建的构造方法
* new RandomAccessFile(File file, String mode);
* new RandomAccessFile(String path, String mode);
* mode:操作模式,只读或者读写
*/
RandomAccessFile raf = new RandomAccessFile("a.txt", "rw");
RandomAccessFile raf1 = new RandomAccessFile(new File("b.txt"), "rw");
// 写一个字节,将给定的int值对应二进制的低八位写入文件
raf.write(97);// a
// 读一个字节,并以int形式返回,若返回值为-1,则表示读取到文件的末尾了.
int len = raf.read();
// 读取一行
String str = raf.readLine();
/*
* 提高每次读写的数据量,减少实际读写的次数,可以提高读写效率
* 对于硬盘而言,随机读写效率是缺点.但是硬盘块读写效率还是可以的.
* 随机读写:单字节读写
* 块读写:一组一组字节读写
* int len = read(byte[] bytes);
* raf2.write(bytes, 0, len);
*/
byte bytes[] = new byte[1024];
len = 0;
while((len = raf.read(bytes)) != -1) {
raf1.write(bytes, 0, len);
}
/*
* 写出字符串操作:
* 在相对路径中,"./"可以不写,不写也默认是当前项目中
* String 提供的方法: byte bytes[] = string.geBytes();
* 将当前字符串(string)按照系统默认字符集转换为一组字节
* bytes = string.getBytes("UTF-8");
* 将当前字符串按照指定字符集转换为一组字节,因为按照系统默认
* 字符集转换会导致跨平台时出现乱码问题.
* GBK:国标编码,中文占2字节
* UTF-8:玩过吗v,对unicode进行编码,变长编码集,英文1字节,中文3字节.
* ISO8859-1:欧洲编码集,不支持中文.
* String提供了一组重载的构造方法,可以将给定的字节数组按照指定字符集还原字符串
* String str = new String(bytes, "GBK");
*/
// 读取所需数量之前以达到文件末尾,则抛出EOFException.
// 获取指针位置(偏移量)
long pos = raf.getFilePointer();
// 移动指针到指定位置
raf1.seek(0);
// 跳过输入的n个字节,以跳过丢弃跳过的字节
//int n = raf.skipBytes(5);
System.out.println(raf1.readLine());
// 关闭对象,释放资源
raf.close();
raf1.close();
IO:Input、Output输入与输出(IO分为:面向字节、面向字符)
功能:读写,方向:输入与输出(参照物,我们写的程序)
输入流用来读取数据,输出流用来写出数据
JAVA将流分为两大类:节点流和处理流
节点流:低级流,是实际连接程序与另一端的“管道”,负责实际搬运数据。读写一定是建立在低级流的基础之上进行的。
处理流:高级流,不能独立存在(没意义),高级流一定会连接在其它流上,使得数据“流经”该流时,对其进行加工处理,简化我们对数据读写时的 某些操作。
文件流:
文件流是一对低级流,用于读写文件数据。功能与RandomAccessFile一样。但是地层的读写方式不同。流是顺序读写的,而RandomAccessFile是基于指针随机读写的。
FileOutputStream(String path);
FileOutputStream(File file);
以上两种创建是覆盖写模式,即若要操作的文件已经存在,会先将该文件数据清除,然后通过流写出的数据作为该文件数据。
FileOuputStream(String path, true);
FileOutputStream(File file, true);
当第二个参数为true时,该流为追加模式。
文件输入流,用于读取文件数据
FileInputStream fis = new FileInputStream("./a.txt");
byte data[] = new byte[1024];
int len = fis.read(data);
// 获取返回值,得到实际读取的字节量
String str = new String(data, 0, len);
缓冲流:
缓冲流是一对高级流
BufferedOutputStream bos、
BufferedInputStream bis
使用了缓冲流读写时,我们就不再需要关注必须用块对俄加快效率了。因为缓冲流内部维护了一个字节数组,最终会将我们的读写操作转换为块读写加快读写效率的,直接关掉缓存流,间接就关掉了文件流。
缓冲输出流写数据时,缓冲区问题
第一种:bos.flush();
第二种:bos.close(); 内部也有flush().
两个都不写,可能有数据存在缓冲区中。
对象流:
ObjectInputStream ois
ObjectOutputStream oos
对象流是一对高级流,可以方便我们读写java中的任何对象。
对象输出流:可以将指定的对象转换为一组字节后写出。
对象输入流:可以将一组字节还原为对应的对象,前提这组字节应当是对象输出流将一个对象转换的字节。
例:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("./user.temp")));
oos.writeObject(new User());
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("./user.temp")));
User user2 = (User) ois.readObject();
注意:
对象先流经对象输出流,而对象输出流将该对象转换为了一组字节,这个过程称为对象序列化
转换的这组字节再流经文件输出流,然后写入文件保存,将数据写入磁盘做长久保存的过程,称为数据持久化。
被写出的对象需要实现Serializable接口,成员变量都必须是引用类型,且都实现了Serializable接口。
当有属性不需要被序列化时,可以使用 transient 修饰
JAVA将流按照读写单位划分为字节流和字符流
字符流:以字符为读写单位,字符流读写数据有一定局限性,只能用于读写文本数据。非文本数据不能使用字符流读取。
java.io.Reader, java.io.Writer
Reader 是所有字符输入流的父类
Writer 是所有字符输出流的父类
转换流(呈上启下):
java.io.InputStreamReader
java.io.OutputStreamWriter
它们是一对高级流,同时也是常用的字符流实现类。几乎所有的字符流都只能连接在其它字符流上,基本上低级流都是字节流,起到将字符流与字节流“对接”的作用。
缓冲字符流
java.io.BufferedWriter
java.io.BufferedReader
内部有缓冲区,可以块读写字符。并且可以按行读写字符串
java.io.PrintWriter
具有自动行刷新的缓冲字符输出流,内部总是会连接BufferedWriter作为缓冲操作。
PrintWriter提供了直接对文件写操作的构造方法
new printWriter(String path);
new printWriter(File file);
PrintWriter pw = new PrintWriter("./a.txt", "GBK");
PrintWriter的构造方法若第一个参数是一个流,那么就支持第二个参数,该参数为boolean类型,若值为true时,那么PrintWriter就具有了自动行刷新功能。
即:每当使用println()写出一行字符串后,会自动flush,注意使用print()是不会自动行刷新的。
BufferedReader
缓冲字符输入流,可以按行读取一行字符串,BufferedReader提供了直接读取一行字符串的方法:
String str = new BufferedReader(new InputStreamReader(new FileInputStream("./a.txt")),"GBK").readLine();
该方法会连续读取若干字符,当读取到换行符('\n')时,将之前读取的字符按字符串形式返回,若返回为null时,表示流到了文件末尾。
FileOutputStream fos = new FileOutputStream("./a.txt");
// 创建时可以指定字符编码集
// OutputStreamWriter osw = new OutputStreamWriter(fos);
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw);
// 以上流程是:字节流-> 转换流->缓冲字符流->具有自动行刷新的缓冲字符流
在这国庆假期间,特此温习下java基础。