文件IO
构造方法
签名 | 说明 |
---|---|
File(File parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例 |
File(String pathname) | 根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者 相对路径 |
File(String parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用 路径表示 |
文件操作常用接口
当然可以,以下是您提供的信息以Markdown表格形式组织的结果:
返回值类型 | 方法签名 | 说明 |
---|---|---|
String | getParent() | 返回 File 对象的父目录文件路径 |
String | getName() | 返回 File 对象的纯文件名称 |
String | getPath() | 返回 File 对象的文件路径 |
String | getAbsolutePath() | 返回 File 对象的绝对路径 |
String | getCanonicalPath() | 返回 File 对象的修饰过的绝对路径 |
boolean | exists() | 判断 File 对象描述的文件是否真实存在 |
boolean | isDirectory() | 判断 File 对象代表的文件是否是一个目录 |
boolean | isFile() | 判断 File 对象代表的文件是否是一个普通文件 |
boolean | createNewFile() | 根据 File 对象,自动创建一个空文件。成功创建后返回 true |
boolean | delete() | 根据 File 对象,删除该文件。成功删除后返回 true |
void | deleteOnExit() | 根据 File 对象,标注文件将被删除,删除动作会到 JVM 运行结束时才会进行 |
String[] | list() | 返回 File 对象代表的目录下的所有文件名 |
File[] | listFiles() | 返回 File 对象代表的目录下的所有文件,以 File 对象表示 |
boolean | mkdir() | 创建 File 对象代表的目录 |
boolean | mkdirs() | 创建 File 对象代表的目录,如果必要,会创建中间目录 |
boolean | renameTo(File dest) | 进行文件改名,也可以视为我们平时的剪切、粘贴操作 |
boolean | canRead() | 判断用户是否对文件有可读权限 |
boolean | canWrite() | 判断用户是否对文件有可写权限 |
getCanonicalPath()和getAbsolutePath()的区别:
import java.io.File;
import java.io.IOException;
public class demo6 {
public static void main(String[] args) throws IOException {
File file = new File("./demo5.java");
String ret1 = file.getAbsolutePath();
String ret2 = file.getCanonicalPath();
System.out.println(ret1);
System.out.println(ret2);
}
}
从执行结果上很容易发现getAbsolutePath()会带上".\"路径,但是getCanonicalPath()是将其省略简化了。
字节流:对应着二进制文件,每次读写的最小单位是"字节"(8bit)
字符流:对应着文本文件,本质上是对字节流的封装。字符流能自动帮我们把几个相邻的字节转换成一个字符。(帮我们完成自动查字符集表),一个字符对应几个字节得看字符集是哪种(utf8一个中文对应三个字节,GBK一个中文对应两个字节)。
String和char字符集区别
String使用的字符集是uft8(每个中文字符占3个字节),如果用是char使用的是Unicode(每个中文字符占2个字节)。
如果String转成char或者char转成String,也会转换其字符集。
Reader和Writer(字符流)
Reader和Writer本质是都是抽象类,无法实例化对象,但是可以接收子类对象。
Reader
第一个read()不带参数的,返回值int其实就是返回读到的那个字符,要强转成char。
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class demo6 {
public static void main(String[] args) throws IOException {
try(Reader reader = new FileReader("D:/test.txt")) {//利用try-resource可以自动调用close
while (true){
int c = reader.read();
if(c==-1){
break;
}
char ch = (char)c;
System.out.println(ch);
}
}
}
}
第二个带参数CharBuffer target不常用。
第三个带参数char[] cbuf,返回值int是表示写入多少个字符。
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class demo6 {
public static void main(String[] args) throws IOException {
try(Reader reader = new FileReader("D:/test.txt")) {//利用try-resource可以自动调用close
while (true){
char[] buffer = new char[1024];
int n = reader.read(buffer);
if(n == -1){
break;
}
System.out.println("n = " + n);
for(int i = 0;i < n;++i){
System.out.println(buffer[i]);
}
}
}
}
}
第四个带参数char[] cbuf,int offer,int len,是将读取到的内容保存在cbuf里面,读取文件是从offer位置开始,读取len长度。
Writer
第一个write是写入单个字符c,可以先用char c = ‘a’,然后使用write((int)c);的方式写入单个字符。
第二个是写入str,这个我们平常用的比较多。
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class demo6 {
public static void main(String[] args) throws IOException {
try(Writer writer = new FileWriter("D:/test.txt",true)) {//这里如果加了true表示在当前文件的尾部追加内容,如果没有加true,则这次写入的内容会覆盖当前文件。
writer.write("aaaaa");
}
}
}
InputStream和OutputStream(字节流)
使用方法类似于Reader和Writer
import java.io.*;
public class demo6 {
public static void main(String[] args) throws RuntimeException {
try(OutputStream outputStream = new FileOutputStream("D:/test.txt",true)) {//这里的true也是表示往文件末尾进行写入而不是覆盖。
String str = "你好世界";
outputStream.write(str.getBytes());//因为写入操作要求使用byte数组,所以要转换一下。
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
import java.io.*;
public class demo6 {
public static void main(String[] args) throws RuntimeException {
try(InputStream inputStream = new FileInputStream("D:/test.txt")){
byte[] bytes = new byte[1024];//接收读入的数组
int n = inputStream.read(bytes);
for(int i = 0;i < n;++i){
System.out.printf("%x\n",bytes[i]);//以16进制的形式打印读取的内容
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Scanner结合InputStream
import java.io.*;
import java.util.Scanner;
public class demo6 {
public static void main(String[] args) {
try(InputStream inputStream = new FileInputStream("D:/test.txt")){
Scanner scanner = new Scanner(inputStream);//把InputStream对象放进Scanner里
String str = scanner.nextLine();//读取一行
System.out.println(str);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
PrintWriter结合OutputStream
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
public class demo6 {
public static void main(String[] args) {
try(OutputStream outputStream = new FileOutputStream("D:/test.txt",true)) {
PrintWriter printWriter = new PrintWriter(outputStream);//将outputStream对象放到PrintWriter中
printWriter.println("这是测试!");
printWriter.flush();//刷新缓冲器
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
关于flush,如果没有刷新缓冲器,当程序结束的时候,缓冲区里还剩余的内容将会丢失!
文件描述符表还有文件资源泄漏
文件描述符表保存了文件描述符,空间是有限制的,如果一直有文件打开,但是不关闭前面没用的连接就会使得文件描述符表的可用资源越来越少,当文件描述符表用完了就会出现问题(文件描述符表可以看成是数组)。
为了避免打开文件的时候忘记close,我们可以使用try-finally或者try-resource方式进行操作,保证会调用close方法。
try{//通过try-finally保证关闭文件
Reader reader = new Reader的子类
}finally {
close();
}
try(Reader reader = new Reader的子类){//通过try-resource的方式打开文件
//代码
}
能放在try()里面的要求实现了closeable接口,只要是流对象都可以。
当然,要close肯定不只是read和write,只要是打开操作文件(比如socket)对象都要close!
如果有错误欢迎各位大佬纠正。