文件的分类:
Java 中通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述。
注意,有 File 对象,并不代表真实存在该文件。
getCanonicalPath() : 简化过后的路径。
比如:
./home/../test 等价于 ./test
代码示例:
public static void main(String[] args) throws IOException {
File file = new File("..\\hello-world.txt"); // 并不要求该文件真实存在
System.out.println(file.getParent());
System.out.println(file.getName());
System.out.println(file.getPath());
System.out.println(file.getAbsolutePath());
System.out.println(file.getCanonicalPath());
}
运行结果:
public static void main(String[] args) throws IOException {
File file = new File("hello-world.txt"); // 要求该文件不存在,才能看到相同的现象
System.out.println(file.exists()); // false
System.out.println(file.isDirectory()); // false
System.out.println(file.isFile()); // false
// 创建文件
System.out.println(file.createNewFile()); // true
System.out.println(file.exists()); // true
System.out.println(file.isDirectory()); // false
System.out.println(file.isFile()); // true
System.out.println(file.createNewFile()); // false
}
public static void main(String[] args) throws IOException {
File file = new File("some-file.txt"); // 要求该文件不存在,才能看到相同的现象
System.out.println(file.exists()); // false
System.out.println(file.createNewFile()); // true
System.out.println(file.exists()); // true
System.out.println(file.delete()); // true
System.out.println(file.exists()); // false
}
public static void main(String[] args) throws IOException {
File file = new File("some-file.txt"); // 要求该文件不存在,才能看到相同的现象
System.out.println(file.exists()); // false
System.out.println(file.createNewFile()); // true
System.out.println(file.exists()); // true
file.deleteOnExit();
System.out.println(file.exists()); // true
}
文件等到程序退出才被删除,所以调用过 deleteOnExit 再进行判断文件是否存在还是 true,但是我们去查看目录就会发现文件被删了。
public static void main(String[] args) throws IOException {
File dir = new File("some-dir"); // 要求该目录不存在,才能看到相同的现象
System.out.println(dir.isDirectory()); // false
System.out.println(dir.isFile()); // false
System.out.println(dir.mkdir()); // true
System.out.println(dir.isDirectory()); // true
System.out.println(dir.isFile()); // false
}
注意:文件/目录创建出来之前它什么都不是,只是一个 File 对象。
public static void main(String[] args) throws IOException {
File dir = new File("some-parent\\some-dir"); // some-parent 和 some-dir 都不存在
System.out.println(dir.isDirectory()); // false
System.out.println(dir.isFile()); // false
System.out.println(dir.mkdir()); // false
System.out.println(dir.isDirectory()); // false
System.out.println(dir.isFile()); // false
}
mkdir() 的时候,如果中间目录不存在,则无法创建成功; mkdirs() 可以解决这个问题。
public static void main(String[] args) throws IOException {
File dir = new File("some-parent\\some-dir"); // some-parent 和 some-dir 都不存在
System.out.println(dir.isDirectory()); // false
System.out.println(dir.isFile()); // false
System.out.println(dir.mkdirs()); // true
System.out.println(dir.isDirectory()); // true
System.out.println(dir.isFile()); // false
}
mkdirs() 同时创建多级目录。
public static void main(String[] args) throws IOException {
File file = new File("some-file.txt"); // 要求 some-file.txt 得存在,可以是普通文件,可以是目录
File dest = new File("dest.txt"); // 要求 dest.txt 不存在
System.out.println(file.exists()); // true
System.out.println(dest.exists()); // false
System.out.println(file.renameTo(dest)); // true
System.out.println(file.exists()); // false
System.out.println(dest.exists()); // true
}
针对文件内容的读写,Java 标准库提供了一组类,按照文件内容分为两个系列:
注意:这些抽象类的实现类有很多,这里只列举了几个常见的。
虽然类有很多,但是使用都是差不多的,这里以 InputStream 和 OutputStream 为例。
方法
注意: 使用完资源要记住关闭 close()
try (InputStream is = new FileInputStream("input.txt")) {
// do something
}
代码中没有显式调用 close(), 但是 try 会帮我们自动调用,执行完 try 语句块后,自动帮我们调用 close().
注意:想要使用 try with resources 必须实现 Closeable 接口,所有的流对象都实现了这个接口。
InputStream 是一个抽象类,FileInputStream 是 InputStream 的一个实现类。
构造方法
代码示例:
一次读取一个字节
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("hello.txt")) {
while (true) {
int b = is.read();
if (b == -1) {
// 代表文件已经全部读完
break;
}
System.out.printf("%c", b);
}
}
}
一次读取多个字节
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("hello.txt")) {
byte[] buf = new byte[1024];
int len;
while (true) {
len = is.read(buf);
if (len == -1) {
// 代表文件已经全部读完
break;
}
for (int i = 0; i < len; i++) {
System.out.printf("%c", buf[i]);
}
}
}
}
相比较而言,后一种的 IO 次数更少,性能更好。
注意,这里面写中文的时候使用的是 UTF-8 编码。
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("hello.txt")) {
byte[] buf = new byte[1024];
int len;
while (true) {
len = is.read(buf);
if (len == -1) {
// 代表文件已经全部读完
break;
}
// 每次使用 3 字节进行 utf-8 解码,得到中文字符
// 利用 String 中的构造方法完成
// 这个方法了解下即可,不是通用的解决办法
for (int i = 0; i < len; i += 3) {
String s = new String(buf, i, 3, "UTF-8");
System.out.printf("%s", s);
}
}
}
}
注意:这里利用了这几个中文的 UTF-8 编码后长度刚好是 3 个字节和长度不超过 1024 字节的现状,所以这种方式并不是通用的。
字符类型使用 InputStream 读取非常麻烦且困难,所以,我们使用比较熟悉的Scanner 类完成该工作 。
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("hello.txt")) {
try (Scanner scanner = new Scanner(is, "UTF-8")) {
while (scanner.hasNext()) {
String s = scanner.next();
System.out.print(s);
}
}
}
}
注意:close 操作也会触发缓冲区刷新。
OutputStream 是一个抽象类,FileOutputStream是 OutputStream 的一个实现类。
利用 OutputStream 进行字符写入:
单个字节的写
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("output.txt")) {
os.write('H');
os.write('e');
os.write('l');
os.write('l');
os.write('o');
// 不要忘记 flush
os.flush();
}
}
一下写入一个字节数组中的数据
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("output.txt")) {
byte[] b = new byte[] {
(byte)'G', (byte)'o', (byte)'o', (byte)'d'
};
os.write(b);
// 不要忘记 flush
os.flush();
}
}
将字节数组的某个区间写入
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("output.txt")) {
byte[] b = new byte[] {
(byte)'G', (byte)'o', (byte)'o', (byte)'d', (byte)'B',
(byte)'a', (byte)'d'
};
os.write(b, 0, 4);
// 不要忘记 flush
os.flush();
}
}
将一个字符串中的内容写入
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("output.txt")) {
String s = "Nothing";
byte[] b = s.getBytes();
os.write(b);
// 不要忘记 flush
os.flush();
}
}
写入中文
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("output.txt")) {
String s = "你好中国";
byte[] b = s.getBytes("utf-8");
os.write(b);
// 不要忘记 flush
os.flush();
}
}
上述已经完成输出工作,但总有所不方便,我们将 OutputStream 处理下,使用 PrintWriter 类来完成输出,因为 PrintWriter 类中提供了我们熟悉的 print/println/printf 方法
public static void main(String[] args) throws IOException {
OutputStream os = new FileOutputStream("output.txt");
OutputStreamWriter osWriter = new OutputStreamWriter(os, "utf-8"); // 告诉它,我们的字符集编码是 utf-8 的
PrintWriter writer = new PrintWriter(osWriter);
// 接下来我们就可以方便的使用 writer 提供的各种方法了
writer.print("Hello");
writer.println("你好");
writer.printf("%d: %s\n", 1, "没什么");
// 不要忘记 flush
writer.flush();
}
好啦! 以上就是对 文件操作 的讲解,希望能帮到你 !
评论区欢迎指正 !