对文件的操作无非就是输入和输出操作,也就是I/O编程。java开发者在java基础类库中专门提供了一组API来帮助对文件的操作,因此只需要掌握好这些方法即可完成I/O编程。
目录
文件的路径有绝对路径和相对路径
绝对路径是指以盘符开始到目标文件或目录的路径,比如打开java文件中的jeconsole文件的路径:C:\Program Files\Java\jdk1.8.0_192\bin

举例使用绝对路径打开一个文件并读取里面的内容:
一:首先先在文件操作目录下面新建一个TMD文件


二:在IDEA中创建字节流并读取该文件

- public class InputStream5 {
- public static void main(String[] args) {
- try(InputStream is = new FileInputStream("C:\\Users\\86158\\Desktop\\JAVA\\JAVA本地代码仓库" +
- "\\JAVA-project\\untitled\\文件操作\\TMD.txt")){//绝对路径
- try(Scanner scanner = new Scanner(is,"UTF-8")){
- while(scanner.hasNext()){
- String s = scanner.next();
- System.out.print(s);
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
输出的结果为:

在用绝对路径打开一个文件时,只要绝对路径一输错,字符输入流就找不到指定的文件,就会报错,例如像下面这样:

所以在使用字符串作为文件路径来打开一个文件时一般不用绝对路径,而是使用相对路径。
一般以.或者..开头的路径,其中.表示当前文件所在目录,..表示当前文件的父目录。在文件操作中使用相对路径要涉及到一个概念——基准目录,基准目录又称为工作目录,在IDEA中,直接运行一个程序,此时的工作目录就是当前项目所在的目录。比如上面的TMD.txt这个文件的工作目录就是

同时相对路径中的相对含义指的是目标文件相对于当前文件的路径
举例:使用相对路径读取文件

- public class InputStream5 {
- public static void main(String[] args) {
- try(InputStream is = new FileInputStream("TMD.txt")){//相对路径
- try(Scanner scanner = new Scanner(is,"UTF-8")){
- while(scanner.hasNext()){
- String s = scanner.next();
- System.out.print(s);
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
文件内容的读写涉及到文件的输入输出流,这些被写入或者读到的数据被统称为数据流。如果将数据比作为池中的水,那么文件的写(write)操作就相当于将桶中的水倒入池中,从桶的角度出发,被倒出的水相当于输出流。文件的读(read)操作相当于将池中的倒给桶,从桶的角度出发,水相当于输入流。

在java中主要利用创建InputStream(字节输入流)对象来读取(read)指定文件中的数据。InputStream是一个抽象类,不能直接使用,但是可以使用它的实例化对象。实例化一个FileInputStream对象,然后读取这个对象中的数据即可。
- read() 功能:从输入流读取一个字节的数据,当返回结果为-1表示读取到文件末尾
- read(byte[] b) 功能:从输入流读取b.length个字节的数据,并将它们存储到缓冲区数组b中。当返回结果为-1表示读取到文件末尾
- close() 功能:关闭字节流
- FileInputStream(File file) 功能:利用File文件创建字节输入流
- FileInputStream(String name) 功能:利用文件路径创建字节输入流
下面演示创建字节输入流并读取文件中的数据
- /**
- * 读文件
- */
- public class InputStream1 {
- public static void main(String[] args) throws IOException {
- /**
- * 创建文件的过程,就相当于在打开文件,打开文件以后才能读写
- * 每次调用read就可以读取一些数据出来,read读取结果的范围就是0——255.
- * 如果读到文件末尾,此时继续read就会返回-1
- */
- InputStream inputStream = null;
- try {
- inputStream = new FileInputStream("./test.txt");
- while(true){
- int i =inputStream.read();
- if(i==-1){
- break;
- }
- System.out.printf("%c",i);
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally{
- inputStream.close();//每次读完以后一定要释放资源
- }
- }
- }
这种写法是一个字节一个字节的读取,比较麻烦,下面还有另一种写法是按照数组缓存区的大小来读取数据:
- public class File1 {
- public static void main(String[] args) throws IOException {
- try (InputStream inputStream = new FileInputStream("./Test.txt")) {
- byte[] buf = new byte[1024];
- int len;
- while(true){
- len = inputStream.read(buf);//从字符输入流inputStream中读取buf.length长度的直接到buf数组中
- if(len==-1){//判断时候读到文件的末尾
- break;
- }
- for (int i = 0; i < len; i++) {
- System.out.printf("%c",buf[i]);
- }
- }
- } catch(IOException e){
- e.printStackTrace();
- }
- }
- }
不过最常用的方法还是利用Scanner进行字符的读取
Scanner的构造方法
Scanner(InputStream is,String charset) 功能:使用指定的charset字符集来读取字符输入流is中的数据
- public class File2 {
- public static void main(String[] args) throws FileNotFoundException {
- try(InputStream inputStream = new FileInputStream("./Test.txt")) {
- try(Scanner scanner = new Scanner(inputStream,"UTF-8")){
- while(scanner.hasNext()){
- String s = scanner.next();
- System.out.println(s);
- }
- }
- }catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
其中Scanner构造方法中也可以不指定字符集
在java中主要利用创建OutputStream(字节输出流)对象来向指定文件中写入(write)数据。OutputStream是一个抽象类,不能直接使用,但是可以使用它的实例化对象。实例化一个FileOutputStream对象,然后向这个对象中写入数据即可。
- write() 功能:将指定的字节写入到输出流中
- write(byte[] b) 功能:将字符数组中的数据全部写入到输出流中
- close() 功能:关闭输出流
- flush() 功能:刷新缓冲区,将输出流中的数据全部添加到设备中
- FileOutputStream(File file) 功能:利用File文件创建字节输出流
- FileOutputStream(String name) 功能:利用文件路径创建字节输出流
下面演示创建字节输出流并将字节输出流中的数据写入到指定的文件中:

写入之前文件中的数据
- public class File3 {
- public static void main(String[] args) throws FileNotFoundException {
- try(OutputStream outputStream = new FileOutputStream("Test.txt")){
- outputStream.write('A');
- outputStream.write('B');
- outputStream.write('C');
- outputStream.write('D');
- outputStream.write('E');
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
写入之后文件中的数据
写入数据的另一种写法,一次性将字符数组中的数据全部写入到输出流中:
- public class File4 {
- public static void main(String[] args) {
- try(OutputStream outputStream = new FileOutputStream("Test.txt")){
- String s = "尼日码佩洛西";
- outputStream.write(s.getBytes());
- outputStream.flush();
- } catch(IOException e){
- e.printStackTrace();
- }
- }
- }

下面是我们向字符输出流中写入数据的最常用方式:
利用PrintWriter类来包装一下OutputStream然后可以更方便的进行写数据,其中PrintWriter是具有自动行刷新的缓冲字符输出流
- public class File5 {
- public static void main(String[] args) throws FileNotFoundException {
- try(OutputStream outputStream = new FileOutputStream("Test.txt")){
- PrintWriter writer = new PrintWriter(outputStream);
- //将格式化的字符数据写入字符输出流中
- writer.println("这里是中国");
- writer.println("请马上离开");
- writer.flush();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }