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

目录
相关文章
|
4月前
|
Java 关系型数据库 数据库
Java 项目实战教程从基础到进阶实战案例分析详解
本文介绍了多个Java项目实战案例,涵盖企业级管理系统、电商平台、在线书店及新手小项目,结合Spring Boot、Spring Cloud、MyBatis等主流技术,通过实际应用场景帮助开发者掌握Java项目开发的核心技能,适合从基础到进阶的学习与实践。
579 4
|
5月前
|
监控 Java API
现代 Java IO 高性能实践从原理到落地的高效实现路径与实战指南
本文深入解析现代Java高性能IO实践,涵盖异步非阻塞IO、操作系统优化、大文件处理、响应式网络编程与数据库访问,结合Netty、Reactor等技术落地高并发应用,助力构建高效可扩展的IO系统。
175 0
|
2月前
|
Java Unix Go
【Java】(8)Stream流、文件File相关操作,IO的含义与运用
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。!但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
202 1
|
3月前
|
安全 Java
Java之泛型使用教程
Java之泛型使用教程
286 10
|
2月前
|
Oracle Java 关系型数据库
Java 简单教程
Java是跨平台、面向对象的编程语言,广泛用于企业开发、Android应用等。本教程涵盖环境搭建、基础语法、流程控制、面向对象、集合与异常处理,助你快速入门并编写简单程序,为进一步深入学习打下坚实基础。
343 0
|
4月前
|
Java 测试技术 API
Java IO流(二):文件操作与NIO入门
本文详解Java NIO与传统IO的区别与优势,涵盖Path、Files类、Channel、Buffer、Selector等核心概念,深入讲解文件操作、目录遍历、NIO实战及性能优化技巧,适合处理大文件与高并发场景,助力高效IO编程与面试准备。
|
4月前
|
SQL Java 数据库连接
Java IO流(一):字节流与字符流基础
本文全面解析Java IO流,涵盖字节流、字符流及其使用场景,帮助开发者理解IO流分类与用途,掌握文件读写、编码转换、异常处理等核心技术,通过实战案例提升IO编程能力。
|
5月前
|
存储 Java Linux
操作系统层面视角下 Java IO 的演进路径及核心技术变革解析
本文从操作系统层面深入解析Java IO的演进历程,涵盖BIO、NIO、多路复用器及Netty等核心技术。分析各阶段IO模型的原理、优缺点及系统调用机制,探讨Java如何通过底层优化提升并发性能与数据处理效率,全面呈现IO技术的变革路径与发展趋势。
131 3
|
10月前
|
JavaScript NoSQL Java
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
500 96
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
|
5月前
|
缓存 安全 Java
Java 并发新特性实战教程之核心特性详解与项目实战
本教程深入解析Java 8至Java 19并发编程新特性,涵盖CompletableFuture异步编程、StampedLock读写锁、Flow API响应式流、VarHandle内存访问及结构化并发等核心技术。结合电商订单处理、缓存系统、实时数据流、高性能计数器与用户资料聚合等实战案例,帮助开发者高效构建高并发、低延迟、易维护的Java应用。适合中高级Java开发者提升并发编程能力。
167 0