文件操作和IO
1.文件
文件指的是 存储在硬盘上的文件。文件除了有数据内容之外,还有一部分信息,例如文件名、文件类型、文件大小等并不作为文件的数据而存在,这部分信息可以视为文件的元信息。
2. 硬盘上文件的目录结构
硬盘上文件的目录结构为树形结构。
3. 文件路径
- 绝对路径:指的就是从树根节点出发(Windows是盘符)一层一层最终到达目标文件
- 相对路径:先指定一个 当前目录、工作目录、基准目录,从当前目录出发,找到目标文件。
4. 文件重要分类:
- 文本文件 :是按照 文本/字符串 方式来理解文本内容(文件里面的二进制内容,都是表示的字符串),进一步可以认为二进制文件的内容都是合法的字符(如普通英文字母、使用ascii汉字、使用gbk/utf8)。
- 二进制文件:这里的内容任何数据都可以(图片、音频、可执行程序、动态库都属于二进制文件.class也是二进制)。
- 用记事本的方式来判定是文本文件还是二进制文件;使用记事本打开一个文件,如果看到的是正常内容,不是乱码,说明这是文本文件,乱码则是二进制文件。
5. Java中操作文件
5.1 Java对于文件操作的API
- 针对文件系统的操作,创建文件、删除文件、重命名文件、列出目录内容等
- 针对文件内容的操作:读文件和写文件
5.2 Java中使用File类来进行文件操作
File类所在包 为java.io。这里的io即输入input和输入output,数据从硬盘到cpu为输入,反之则输出。
5.3 File类属性
- static String(修饰符及类型) – pathSeparator :依赖于系统的路径分隔符,String类型的表示;
- static char – pathSeparator :依赖于系统的路径分隔符,char类型
5.4 构造方法
- File(File parent, String child):根据父目录 + 孩子文件路径,创建一个新的 File 实例
- File(String pathname) :根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者
相对路径 - File(String parent, String child) :根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用路径表示
5.5 方法:
- 获取路径、文件名、绝对路径
如下代码:
// File 常见的方法
import java.io.File;
import java.io.IOException;
public class IODemo1 {
public static void main(String[] args) throws IOException {
//File f = new File("E:/user/1/test.txt");
File f = new File("./test.txt");
// 返回 File 对象的父目录文件路径
System.out.println(f.getParent());
// 返回 FIle 对象的纯文件名称
System.out.println(f.getName());
//返回 File 对象的文件路径
System.out.println(f.getPath());
// 返回 File 对象的绝对路径
System.out.println(f.getAbsolutePath());
//返回 File 对象的修饰过的绝对路径
System.out.println(f.getCanonicalPath());
}
}
- 创建文件、查看文件是否存在、是否是文件、是否是目录
import java.io.File;
import java.io.IOException;
public class IODemo2 {
public static void main(String[] args) throws IOException {
File f = new File("./test.txt");
System.out.println(f.exists());
System.out.println(f.isFile());
System.out.println(f.isDirectory());
// 创建文件,创建完之后不会重复创建,
boolean ret = f.createNewFile();
System.out.println("ret = "+ret);
}
}
- 删除文件
import java.io.File;
public class IODemo3 {
public static void main(String[] args) throws InterruptedException {
File file = new File("./test.txt");
// 删除文件
//boolean ret = file.delete();
//System.out.println(ret);
// 根据File对象,标注文件将被删除,删除动作会到JVM运行结束时才会进行
file.deleteOnExit();
Thread.sleep(5000);
}
}
- 获取目录下所有文件名
import java.io.File;
import java.util.Arrays;
public class IODemo4 {
public static void main(String[] args) {
File file = new File(".");
// 返回File对象代表的目录下的所有文件名
//String[] files = file.list();
// 返回File对象代表的目录下的所有文件,以File对象表示
File[] files = file.listFiles();
//System.out.println(files); // 打印的是哈希值,不是地址
System.out.println(Arrays.toString(files));
}
}
- 创建目录(多层目录)
import java.io.File;
public class IODemo5 {
public static void main(String[] args) {
File file = new File("./aaa/bbb/ccc");
// 创建单个目录
//boolean ret = file.mkdir();
boolean ret = file.mkdirs();
System.out.println(ret);
}
}
- 重命名
import java.io.File;
public class IODemo6 {
public static void main(String[] args) {
File src = new File("./test2.txt");
File dest = new File("./aaa/test2.txt");
// 重命名 还可以移动文件
System.out.println(src.renameTo(dest));
}
}
6. 文件内容的读写 – 文件流(数据流)
- 字节流:每次读写的最小单位就是一个字符。 InputStream和OutputStream
- 字符流:每次读写的最小单位是一个字符(一个字符可能由多个字节构成)。字符流可以内部处理字符编码。Reader 和 Writer。
6.1 InputStream
由于inputStream 是抽象类,不能实例化。所以new的是一个 FileInputStream。
inputStream 是抽象类,不能实例化。有些类我们不希望它能够创建出实例的,使用abstract来描述,编译器就可以进行更严格的检查(如单例模式,数据库约束)所谓 面向对象 就是通过代码抽象的表示实际事物的一种方式。
-
read()方法:返回类型为int,读取一个字节的数据,返回-1代表读完了。
-
read(byte[] b) :最多读取 b.length 字节的数据到 b 中,返回实际读到的数量;-1 代表已经读完了
-
read(byte[] b,int off, int len):最多读取 len - off 字节的数据到 b 中,放在从 off 开始,返回实际读到的数量;-1 代表以及读完了
read的参数版本,传入的字节数参数,是一个输出型参数,byte[]是引用类型,方法内部针对数组内容进行修改,方法执行结束之后,方法外部也能生效。 -
close() :返回类型为void,关闭字节流。
使用try() 代码块会自动调用inputStream的close方法。
public class IODemo7 {
public static void main(String[] args) throws IOException { // FileNotFoundException也是一种特殊的IOException
/*InputStream inputStream = null;
try {
// 打开文件
inputStream = new FileInputStream("./test.txt");
// 中间还有很多逻辑,所有得使用try finally,最后执行inputStream.close()以免没执行
} finally {
// 关闭文件
inputStream.close();
}*/
// 使用try模块 ,此时try自动调用inputStream得close,但前提得FileInputStream实现了Closeable接口得类,才能放到try()里面
try (InputStream inputStream = new FileInputStream("./test.txt")) {
// 读取文件,也不知道文件有多少个字节,使用while来完成
while (true) {
/*int b = inputStream.read();
if (b == -1) {
// 读到文件末尾为-1,文件读取完毕
break;
}
//打印这个字节的数据 文件内容是abcde 以16进制打印它的ASCII码
// 如果内容是中文,此时打印出的就是每个字节,就是对应到utf8编码的值
System.out.printf("%x ", b);*/
//
byte[] buffer = new byte[1024];
int n = inputStream.read(buffer);
if (n == -1) {
break;
}
for (int i = 0; i < n; i++) {
System.out.printf("%x ",buffer[i]);
}
}
}
}
}
6.2 使用InputStream读文件
读文件:就是把硬盘数据读取到内存中。
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class IODemo8 {
public static void main(String[] args) {
try(InputStream inputStream = new FileInputStream("./test.txt")) {
while (true) {
byte[] buffer = new byte[1024];
int n = inputStream.read(buffer);
if (n == -1) {
break;
}
String s = new String(buffer,0,n);
System.out.println(s);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
6.3 使用OutputStream写文件
在FileOutputStream()添加true参数,是在源文件里的内容进行追加
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class IODemo9 {
public static void main(String[] args) {
// append参数是追加
try (OutputStream outputStream = new FileOutputStream("./test.txt",true)) {
//此处写入的是二进制,
byte[] buffer = new byte[] {97,98,99,100,101};
outputStream.write(buffer);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
7. Reader和Writer字符流
使用方式和InputStream、OutputStream差不多。
7.1 Reader读文件
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class IODemo10 {
public static void main(String[] args) {
// 使用字符流读取文件内容
try (Reader reader = new FileReader("./test.txt")) {
// 读取文件
while (true) {
char[] buffer = new char[1024];
int n = reader.read(buffer);
if (n == -1) {
break;
}
String s = new String(buffer,0,n);
System.out.println(s);
/*for (int i = 0;i < n;i++) {
System.out.print(buffer[i]);
System.out.println(" ");
}*/
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
7.2 Writer写文件
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class IODemo11 {
public static void main(String[] args) {
try (Writer writer = new FileWriter("./test.txt",true)) {
String str = "你好帅哥";
writer.write(str);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
8. 使用Scanner接收intputStream
Scanner(System.in)本质就是一个inputStream
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
public class IODemo12 {
public static void main(String[] args) {
try (InputStream inputStream = new FileInputStream("./test.txt")) {
Scanner scanner = new Scanner(inputStream);
while (scanner.hasNext()) {
String s = scanner.next();
System.out.println(s);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}