Java学习笔记-Day27 Java IO流(一) 非流式部分
一、Java IO
1、IO的层次
Java IO主要包括三个部分:
(1)流式部分:IO的主体部分。
(2)非流式部分:主要包含一些辅助流式部分的类,如:File类、RandomAccessFile类和FileDescriptor类等等。
(3)其他类:文件读取部分的类与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类。
注意:这里的IO指的是BIO,即阻塞IO。
2、java.io包
java.io包是JDK内置的包,其中包含一系列对文件和目录的属性进行操作,对文件进行读写操作的类。程序中如果要使用到该包中的类,对文件或流进行操作,则必须显式地声明如下语句:
import java.io.*;
java.io包是Java中最传统的IO操作,在利用io包的输入流工具(InputStream、Reader)进行数据读取操作时,如果无法读取到需要的内容,将会导致执行读取数据操作的线程陷入阻塞状态。因此,在进行流的写入和读取时要尤为小心,保证数据读取的数量和顺序的准确性,否则可能导致程序执行异常。
二、非流式部分
1、File类
File类(java.io.File)的对象是一个表示文件和目录的路径。在程序中,一个File类的对象可以代表一个文件或目录。
当创建一个File对象后,就可以利用它来对文件或目录的属性进行操作,如:文件名、最后修改日期、文件大小等等。
需要注意的是,File对象并不能直接对文件内容进行读写操作,只能查看文件的属性。实例化File类时,如果该File类的对象表示的目录或文件不存在,是不会创建该对象表示的目录或文件。如果想创建该对象表示的目录或文件,就需要调用该File对象的 createNewFile()
或 mkdir() / mkdirs()
方法。
1.1、构造方法
File(String pathname)
:通过将给定的路径名的字符串转换为抽象路径名来创建新的 File实例。
1.2、路径名的表达
由于在Java中 \
符号是转义字符,如果使用 \
作为路径分割符,则实际需要编写 \\
,有一个更好的替代方法是使用Unix系统中常用的 /
作为路径分割符。
绝对路径:路径名以盘符开头,从磁盘的根目录开始。如:C:\\Windows\\addins
。
相对路径:路径名以 /
或 \\
开头,则相对路径的根为 当前项目所在 磁盘的根目录 。如:\\14.txt
。不以 /
或 \\
开头,则相对路径的根为 项目的根目录,如:14.txt
。
1.3、部分方法
(1)
boolean canExecute()
:测试程序是否可以执行此File对象表示的文件。如果返回值为true,表示能执行,如果返回值为false,表示不能执行。
(2)
boolean canRead()
:测试程序是否可以读取由此File对象表示的文件。如果返回值为true,表示能读取,如果返回值为false,表示不能读取。
(3)
boolean canWrite()
:测试程序是否可以修改由此File对象表示的文件。如果返回值为true,表示能写,如果返回值为false,表示不能写(只读)。
(4)
boolean createNewFile()
:当且仅当具有该名称的文件尚不存在时,会创建一个由该抽象路径名命名的新的空文件。
(5)
boolean delete()
:删除由此抽象路径名表示的File对象。
(6)
String getAbsolutePath()
:返回此File对象的绝对路径名的字符串。
(7)
boolean isDirectory()
:测试此File对象是否为目录。
(8)
boolean isFile()
:测试此File对象是否为文件。
(9)
long lastModified()
:返回此File对象表示的文件上次修改的时间,返回值为毫秒值。
(10)
long length()
:返回由此File对象表示的文件的长度,单位为字节。
(11)
boolean mkdir()
:创建由此File对象命名的目录。
(12)
boolean mkdirs()
:创建由此File对象命名的目录,包括任何必需但不存在的父目录。
(13)
File[] listFiles()
:返回一个File类型的数组,该数组包含由此File对象表示的目录中的文件和目录的File对象。如果被文件的File对象调用或者没有访问权限,则会返回null。
1.4、遍历所有目录下的文件
如果想要遍历所有目录下的文件,可以使用递归遍历。
/**
* 经典面试题: 遍历目录下的文件(逐级遍历)
*/
public class TestFile03 {
public static void main(String[] args) throws IOException {
// 使用路径名字符串创建一个File对象
File file = new File("C:\\Users");
// 调用showFiles方法
showFiles(file);
}
/**
* showFiles方法
*/
public static void showFiles(File file) {
//返回一个File类型的数组,表示由此File对象表示的目录中所有子文件和子目录
File[] files = file.listFiles();
// 没有访问权限,则会返回null
if (files != null) {
// 遍历目录下的文件和子目录
for (File f : files) {
if (f.isFile()) {
//输出绝对路径名
System.out.println(f.getAbsolutePath());
} else {
// 递归调用
showFiles(f);
}
}
}
}
}
2、RandomAccessFile
RandomAccessFile 既可以读取文件内容,也可以向文件输出数据。RandomAccessFile 支持随机访问的方式,可以直接跳转到文件的任意地方来读写数据。
由于RandomAccessFile可以自由访问文件的任意位置,所以如果需要访问文件的部分内容,而不是把文件从头读到尾,使用RandomAccessFile将是更好的选择。
2.1、构造方法
(1)
RandomAccessFile(File file, String mode)
:创建一个随机访问文件流,从File参数指定的文件中读取或者写入数据。
(2)RandomAccessFile(String name, String mode)
:创建一个随机访问文件流,从String参数指定的文件中读取或者写入数据。
构造方法的第二个参数mode:
① “r” : 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
② “rw”: 打开以便读取和写入。
③ “rws”: 打开以便读取和写入。相对于 “rw”,“rws” 还要求对“文件的内容”或“元数据”的每个更新都同步写入到基础存储设备。
④ “rwd” : 打开以便读取和写入,相对于 “rw”,“rwd” 还要求对“文件的内容”的每个更新都同步写入到基础存储设备。
2.2、关于指针位置的方法
(1)
long getFilePointer()
:返回此文件中的当前偏移量(文件指针的位置)。
(2)
void seek(long pos)
:设置文件指针偏移,从该文件的开头测量,发生下一次读取或写入。
2.3、读的部分方法 readXxx()
(1)
boolean readBoolean()
:从此文件读取一个 boolean 。
(2)
byte readByte()
:从此文件中读取一个带符号的byte。
(3)
char readChar()
:从此文件中读取一个字符。
(4)
double readDouble()
:从此文件读取 double 。
(5)
float readFloat()
:从此文件读取一个 float 。
2.4、写的部分方法 writeXxx()
(1)
void writeDouble(double v)
:使用Double类的doubleToLongBits方法将double参数转换成 long,然后将该 long值到作为一个8字节的数量、高字节写入到该文件,。
(2)
void writeFloat(float v)
:使用Float类的floatToIntBits方法将float参数转换成 int,然后将该 int值作为一个4字节数量、高字节写入到该文件,。
(3)
void writeInt(int v)
:将 int写入文件为4个字节,高字节 int 。
(4)
void writeLong(long v)
:将 long写入文件为8个字节,高字节为先。
(5)
void writeShort(int v)
:将 short写入文件作为2个字节,高字节优先。
2.5、字符串的写入方法
- 字符串的写入方法
(1)
void writeBytes(String s)
:将字符串作为字节序列写入文件。
(2)
void writeChars(String s)
:将字符串作为字符序列写入文件。
(3)
void writeUTF(String str)
:以机器无关的方式使用 modified UTF-8编码将字符串写入文件。
RandomAccessFile 类中写入字符串的三个方法是实现了 DataOutput接口而具有的。writeBytes 是以一串有序的字节将字符串写入文件,每一个字符都是以其高八位写入的。writeChars 是以一串有序的字符写入字符串,每一个字符都由两个字节组成。writeUTF 是使用modified UTF-8 编码以一种与机器无关的方式写入字符串数据,具体有其自己的写入规则。
对于使用 RandomAccessFile 类写入、读出字符串,建议大家统一标准:
写入时使用 writeBytes 方法,将字符串以有序字节的形式写入文件,读取时,根据之前写入的字符串长度,通过循环读取每一个字节,然后将其构造成字符串。但是有中文字符的时候,不建议使用,因为会产生乱码。JAVA中的char是16位的,一个char存储一个中文字符,直接用writeBytes方法转换会变为8位,直接导致高8位丢失。从而导致中文乱码。
public class TestRandomAccess03 {
public static void main(String[] args) throws IOException {
write();
read();
}
//中文会出现乱码
public static void read() throws IOException {
RandomAccessFile fa = new RandomAccessFile("E://infomation.txt", "r");
// 设置指针位置
fa.seek(0);
System.out.println("point="+fa.getFilePointer());
byte[] b3 = new byte[7];
fa.read(b3);
System.out.println("b3="+new String(b3));
//7
System.out.println("point="+fa.getFilePointer());
// 设置指针位置
fa.seek(7);
System.out.println("point="+fa.getFilePointer());
byte[] b4 = new byte[8];
fa.read(b4);
System.out.println("b3="+new String(b4));
//15
System.out.println("point="+fa.getFilePointer());
fa.close();
}
// writeBytes(String s):将字符串作为字节序列写入文件。
// 指针计算的是字符
public static void write() throws IOException {
RandomAccessFile fa = new RandomAccessFile("E://infomation.txt", "rw");
System.out.println("point="+fa.getFilePointer());
fa.writeBytes("hello爪哇");
System.out.println("point="+fa.getFilePointer());
fa.writeBytes("helloTom");
System.out.println("point="+fa.getFilePointer());
fa.close();
}
}
2.6、统一使用的字符串写入读出方法
字符串写入方法
void write(byte[] b)
:从指定的字节数组写入 b.length个字节到该文件,从当前文件指针开始。
字符串读出方法
int read(byte[] b)
:从该文件读取最多 b.length字节的数据到字节数组 。
- 使用字符串写入读出方法的代码
ublic class TestRandomAccess04 {
public static void main(String[] args) throws IOException {
write();
read();
}
// read(byte[] b):从该文件读取最多 b.length字节的数据到字节数组。
// 指针计算的是 字节
public static void read() throws IOException {
RandomAccessFile fa = new RandomAccessFile("E://infomation.txt", "r");
System.out.println("point="+fa.getFilePointer());
byte[] b = new byte[17];
System.out.println(fa.read(b));
System.out.println("b="+new String(b));
fa.close();
}
// write(byte[] b):从指定的字节数组写入 b.length个字节到该文件,从当前文件指针开始。
// 指针计算的是 字节
public static void write() throws IOException {
RandomAccessFile fa = new RandomAccessFile("E://infomation.txt", "rw");
//0
System.out.println("point="+fa.getFilePointer());
fa.write("hello爪哇".getBytes());
//9
System.out.println("point="+fa.getFilePointer());
fa.write("helloTom".getBytes());
//17
System.out.println("point="+fa.getFilePointer());
fa.close();
}
}