java文件操作和IO流入门级教程(2)

简介: java文件操作和IO流入门级教程(2)

文件内容相关的操作

文件内容相关的操作,就是对文件内容进行读写操!


我们也是通过java中的API进行学习!


我们java提供了两种对文件操作读取的方案!


字符流: 以字符为单位进行读取!

文件流: 以字节为单位进行读取!

这里的字节流和字符流就对应了我们的二进制文件和字符文件的读取


什么是流呢?

就好比水流,我们将文件的读取抽象成了水流!


输入流: 就好比你在喝水,文件读取的过程!

输出流:就好比你在输出知识,文件删除的过程!


image.png

image.png

我们通过这个表格就可以对字符流和字节流的读取进行区分!

我们会详细学习这些读取类!


字节流

字节流:就是以字节为单位,一次读写一个或多个字节!


读操作


如果我们要对一个文件进行读操作,都要进行那些步骤呢?


打开文件

进行读操作

关闭文件

我们通过下面案例对字节流读取进行学习!

//字节流读操作!
import java.io.*;
public class File2 {
    public static void main(String[] args) throws IOException {
        //输入操作,也就是读文件(学习读书过程就是输入)
        File file = new File("./hello.txt");
        //输入流,打开文件!
        InputStream inputStream = new FileInputStream(file);
        byte[] result = new byte[1024];
        //byte数组用来存放读取结果
        while (true){
            int len = inputStream.read(result);//保存了有效字节数!
            if(len==-1){//读取完成!
                break;
            }
            for (int i = 0; i 
                System.out.print((char)result[i]);
            }
        }
        //关闭文件!
        inputStream.close();
    }
 }

image.png

读取结果:

FileInputStream用于读取诸如图像数据的原始字节流!


构造方法:

image.png

我们这里的字节流读操作,用到了read方法!

image.png

下面3个read方法都是对输入流进行读操作!


int read()
从该输入流读取一个字节的数据。

无参方法read(),默认读取一个字节,返回值是一个整型int!

为啥不是返回一个byte型呢?

我们知道byte范围是-128~127

而我们规定当返回值为-1就表示读取到文件末尾!

如果这样就冲突了!

所以这里的返回值是int 一个字节的范围是 0~255


int read(byte[] b)

从该输入流读取最多 b.length个字节的数据为字节数组。

我们通过byte数组,去接收读取的结果!

而这里的返回值是读取到的有效字节个数!

image.png

返回-1就是读取结束!


int read(byte[] b, int off, int len)

从该输入流读取最多 len`字节的数据为字节数组。

和上面的读取操作类似!

这里的b字节数组存放读取内容时,是从off数组下标开始,一次最多可以读取len长度的字节!

而返回值是读取到有效字节数!


输出流写操作

写文件也是类似的步骤!


打开文件

进行写操作

关闭文件

我们先看一个案例:


//字节流写操作
public static void main(String[] args) throws IOException {
        //输出操作,也就是写文件(学习做题,写博客过程就是输出)
        File file = new File("./4_22.txt");
        //打开文件!
       OutputStream outputStream = new FileOutputStream(file);
       //我们将string字符串写入 file文件!
       String string = "hello world!";
       //我们要通过字节方式进行写操作!
       outputStream.write(string.getBytes());
        System.out.println("写入成功!");
        //关闭流文件!
        outputStream.close();
    }

image.png



FileOutputStream用于写入诸如图像数据的原始字节流。 对于写入字符流,请考虑使用FileWriter 。


我们输出流写操作,主要通过write 方法进行!


void write(byte[] b)

将 b.length个字节从指定的字节数组写入此文件输出流。

void write(byte[] b, int off, int len)

将 len字节从位于偏移量 off的指定字节数组写入此文件输出流。

void write(int b)

将指定的字节写入此文件输出流。

这里的write和read类似!

这里是将b数组里的内容写到file文件!


注意:

这里每次打开文件进行写操作,都会将文件内容置空,再进行写操作!如果并不存在此文件,就会创建改文件!

如果我们要从文件末尾开始写操作呢?


//追加写入操作!
public static void main(String[] args) throws IOException {
        //输出操作,也就是写文件(学习做题,写博客过程就是输出)
        File file = new File("./4_22.txt");
        //打开文件!
        //true可追加!默认不可追加!
       OutputStream outputStream = new FileOutputStream(file,true);
       //我们将string字符串写入 file文件!
       String string = "hello world!";
       //我们要通过字节方式进行写操作!
       outputStream.write(string.getBytes());
        System.out.println("追加写入成功!");
        //关闭流文件!
        outputStream.close();
    }

我们需要在创建输出流对象时通过构造方法传参设置是否可追加!

image.png

字符流

字符流:就是以字符为单位,一次读取一个或多个字符!


字符流读操作:


//字符流读操作!
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class File3 {
    public static void main(String[] args){
        Reader reader = null;
        try {
            //打开文件!
            reader = new FileReader("./hello.txt");
            while (true){
                //一次读取一个字符!
               int x =  reader.read();
               if(x==-1){//读取结束!
                   break;
               }
               //输出该字符!
                System.out.print((char)x);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //关闭文件!
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

image.png

我们可以看到上面的代码比较繁琐,因为要处理好多异常,还有关闭文件操作!

我们可以简化一下代码,将文件流在try语句块创建,语句块结束就会自动关闭资源!


//优化后的代码!
public static void main(String[] args){
        ///try() 中语句块结束自动关闭资源!
        try (Reader reader = new FileReader("./hello.txt")){
            //打开文件!
            while (true){
                //一次读取一个字符!
               int x =  reader.read();
               if(x==-1){//读取结束!
                   break;
               }
               //输出该字符!
                System.out.print((char)x);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

注意:

只要实现了Closeable这个接口的类都可以进行这样的操作!

image.png

而我们的文件操作流对象实现了这个接口!


字符流的读取和字节流的读取大同小异!


int read()

读一个字符

int read(char[] cbuf)

将字符读入数组。

abstract int read(char[] cbuf, int off, int len)

将字符读入数组的一部分。

int read(CharBuffer target)

尝试将字符读入指定的字符缓冲区。

字符流写操作:


//字符流写操作!
    public static void main(String[] args) {
        //打开文件!
        try(Writer writer = new FileWriter("./4_22.txt",true)){
             String string = "加油!";
                writer.write(string);
            System.out.println("追加写入成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

image.png

常用方法:


Writer append(char c)

将指定的字符附加到此作者。

Writer append(CharSequence csq)

将指定的字符序列附加到此作者。

Writer append(CharSequence csq, int start, int end)

将指定字符序列的子序列附加到此作者。

abstract void close()

关闭流,先刷新。

abstract void flush()

刷新流。

void write(char[] cbuf)

写入一个字符数组。

abstract void write(char[] cbuf, int off, int len)

写入字符数组的一部分。

void write(int c)

写一个字符

void write(String str)

写一个字符串

void write(String str, int off, int len)

写一个字符串的一部分。

上述方法就可以对字符流进行写操作了!


文件操作案例

我们通过下面3个案例进一步巩固学习!

问题一:

扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件


//实例一
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class File4 {
    public static void main(String[] args) throws IOException {
       // 扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),
        // 并且后续询问用户是否要删除该文件
        Scanner scanner = new Scanner(System.in);
        //获取要扫描的目录文件!
        System.out.print("目录文件->");
        String dirctoryString = scanner.next();
        File dirctoryFile = new File(dirctoryString);
        //获取要删除的文件
        System.out.printf("要删除的文件->");
        String fileString = scanner.next();
        //扫描文件!
        scanFile(dirctoryFile,fileString);
    }
    private static void scanFile(File dirctoryFile,String fileString) throws IOException {
        //将该目录下的文件列出!
        File[] files = dirctoryFile.listFiles();
        for (File file:files) {
            System.out.println(file.getCanonicalFile());
            if(file.isDirectory()){
                //目录文件继续遍历!
                scanFile(file,fileString);
            }else {
                //文件判断是否要删除!
                if(file.getName().contains(fileString)){
                    //进行删除!
                    file.delete();
                }
            }
        }
    }
}

image.png

我们可以找到test文件,然后进行了删除操作!

image.png

问题二:

进行普通文件的复制


//实例二:
import java.io.*;
import java.util.Scanner;
public class File5 {
    public static void main(String[] args) throws IOException {
        //进行文件复制操作!
        Scanner scanner = new Scanner(System.in);
        //获取要复制的源文件!
        System.out.print("源文件->");
        String srcString = scanner.next();
        File srcFile = new File(srcString);
        //获取源文件目录:
        String parentString = srcFile.getParent();
        System.out.println("目录文件:"+parentString);
        //目录文件
        File parentFile = new File(parentString);
        //获取目标文件
        System.out.printf("目标文件->");
        String desString = scanner.next();
        File desFile = new File(desString);
        //扫描文件!
        scanner(parentFile,srcFile,desFile);
    }
    private static void scanner(File parentFile,File srcFile, File desFile) {
        File[] files = parentFile.listFiles();
        for (File file:files) {
            System.out.println(file.getName());
           if(file.isDirectory()) {//目录文件继续遍历
               scanner(file, srcFile,desFile);
           }
           if(file.getName().equals(desFile.getName())){
               //找到了目标文件!
               //进行复制操作!
               copyfile(srcFile,desFile);
               return;
           }
        }
    }
    private static void copyfile(File srcFile, File desFile) {
        try(Reader reader = new FileReader(srcFile)){//读src文件!
            //存放读取结果
            char[] chars = new char[1024];
            while (true){
                int len = reader.read(chars);
                if(len==-1){//读取结束!
                    break;
                }
                //写入到目标文件!
                try(Writer writer = new FileWriter(desFile,true)){
                    String string = new String(chars,0,len);
                    System.out.println("复制内容:"+string);
                    writer.write(string);
                }
                System.out.println("复制成功!");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

源文件:

image.png


目标文件:

image.png

注意这里的目标文件要写绝对或相对路径!

问题三:


扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)

注意 :我们现在的方案性能较差,所以尽量不要在太复杂的目录下或者大文件下实验!


//实例三
import java.io.*;
import java.util.Scanner;
public class File6 {
    public static void main(String[] args) throws IOException {
        // 扫描指定目录,并找到名称中包含指定字符或者内容的所有普通文件(不包含目录),
        Scanner scanner = new Scanner(System.in);
        //获取要扫描的目录文件!
        System.out.print("目录文件->");
        String dirctoryString = scanner.next();
        File dirctoryFile = new File(dirctoryString);
        //获取要删除的关键字
        System.out.printf("要删除的关键字->");
        String fileString = scanner.next();
        //扫描文件!
        scanFile(dirctoryFile,fileString);
    }
    private static void scanFile(File dirctoryFile,String fileString) throws IOException {
        //将该目录下的文件列出!
        File[] files = dirctoryFile.listFiles();
        for (File file:files) {
            System.out.println(file.getCanonicalFile());
            if(file.isDirectory()){
                //目录文件继续遍历!
                scanFile(file,fileString);
            }else {
                //文件判断是否要删除!
                if(file.getName().contains(fileString)){
                    //文件名称有该关键字进行删除!
                    file.delete();
                    System.out.println(file.getName()+" 删除成功!");
                }else {
                    //查看文件内容是否含该关键字!
                    if(isdelete(file,fileString)){
                        file.delete();
                        System.out.println(file.getName()+" 删除成功!");
                    }
                }
            }
        }
    }
    private static boolean isdelete(File file, String fileString) {
        try(Reader reader = new FileReader(file)){
            char[] chars = new char[1024];
            while (true){
                int len = reader.read(chars);
                if(len==-1){
                    break;
                }
                String str = new String(chars,0,len);
                System.out.println(file.getName()+" 内容:"+str);
                if (str.contains(fileString)) {
                    //如果内容中包含了该关键字!
                    return true;
                }
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
}

image.png

目录
相关文章
|
1月前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
3天前
|
前端开发 Java Maven
【前端学java】全网最详细的maven安装与IDEA集成教程!
【8月更文挑战第12天】全网最详细的maven安装与IDEA集成教程!
16 2
【前端学java】全网最详细的maven安装与IDEA集成教程!
|
8天前
|
存储 网络协议 Oracle
java教程
java教程【8月更文挑战第11天】
14 5
|
6天前
|
Java Android开发
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
23 1
|
11天前
|
存储 缓存 Java
15 Java IO流(File类+IO流+字节流+字符流+字节编码)
15 Java IO流(File类+IO流+字节流+字符流+字节编码)
33 3
|
1月前
|
SQL 安全 Java
「滚雪球学Java」教程导航帖(更新2024.07.16)
《滚雪球学Spring Boot》是一个面向初学者的Spring Boot教程,旨在帮助读者快速入门Spring Boot开发。本专通过深入浅出的方式,将Spring Boot开发中的核心概念、基础知识、实战技巧等内容系统地讲解,同时还提供了大量实际的案例,让读者能够快速掌握实用的Spring Boot开发技能。本书的特点在于注重实践,通过实例学习的方式激发读者的学习兴趣和动力,并引导读者逐步掌握Spring Boot开发的实际应用。
41 1
「滚雪球学Java」教程导航帖(更新2024.07.16)
|
19天前
|
安全 Java Linux
(七)Java网络编程-IO模型篇之从BIO、NIO、AIO到内核select、epoll剖析!
IO(Input/Output)方面的基本知识,相信大家都不陌生,毕竟这也是在学习编程基础时就已经接触过的内容,但最初的IO教学大多数是停留在最基本的BIO,而并未对于NIO、AIO、多路复用等的高级内容进行详细讲述,但这些却是大部分高性能技术的底层核心,因此本文则准备围绕着IO知识进行展开。
WXM
|
24天前
|
Oracle Java 关系型数据库
Java JDK下载安装及环境配置超详细图文教程
Java JDK下载安装及环境配置超详细图文教程
WXM
125 3
|
1月前
|
测试技术 API Android开发
《手把手教你》系列基础篇(九十七)-java+ selenium自动化测试-框架设计篇-Selenium方法的二次封装和页面基类(详解教程)
【7月更文挑战第15天】这是关于自动化测试框架中Selenium API二次封装的教程总结。教程中介绍了如何设计一个支持不同浏览器测试的页面基类(BasePage),该基类包含了对Selenium方法的二次封装,如元素的输入、点击、清除等常用操作,以减少重复代码。此外,页面基类还提供了获取页面标题和URL的方法。
44 2
|
1月前
|
Web App开发 XML Java
《手把手教你》系列基础篇(九十六)-java+ selenium自动化测试-框架之设计篇-跨浏览器(详解教程)
【7月更文挑战第14天】这篇教程介绍了如何使用Java和Selenium构建一个支持跨浏览器测试的自动化测试框架。设计的核心是通过读取配置文件来切换不同浏览器执行测试用例。配置文件中定义了浏览器类型(如Firefox、Chrome)和测试服务器的URL。代码包括一个`BrowserEngine`类,它初始化配置数据,根据配置启动指定的浏览器,并提供关闭浏览器的方法。测试脚本`TestLaunchBrowser`使用`BrowserEngine`来启动浏览器并执行测试。整个框架允许在不同浏览器上运行相同的测试,以确保兼容性和一致性。
47 3