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 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
14天前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
14天前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
14天前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
|
1月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
67 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
23天前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
本指南介绍了如何在Spring Boot项目中集成Firebase云消息服务(FCM),包括创建项目、添加依赖、配置服务账户密钥、编写推送服务类以及发送消息等步骤,帮助开发者快速实现推送通知功能。
61 2
|
30天前
|
Java 数据库连接 编译器
Kotlin教程笔记(29) -Kotlin 兼容 Java 遇到的最大的“坑”
Kotlin教程笔记(29) -Kotlin 兼容 Java 遇到的最大的“坑”
|
1月前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
本系列教程笔记详细讲解了Kotlin语法,适合希望深入了解Kotlin的开发者。对于需要快速学习Kotlin的小伙伴,推荐查看“简洁”系列教程。本篇笔记重点介绍了Kotlin与Java混编的技巧,包括代码转换、类调用、ProGuard问题、Android库开发建议以及相互调用时的注意事项。
23 3
|
1月前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
21 3
|
1月前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)