一文带你搞懂Java中的数据流处理

 更新时间:2024年02月22日 08:23:38   作者:石小石Orz  
这篇文章主要为大家详细介绍了Java中数据流处理的相关知识,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以跟随小编一起学习一下

数据流转

在前端的javascrit中,我们几乎是没有能力对计算机上的某个文件进行读写操作的,毕竟js只是一个网页脚本。但是,nodejs是可以实现文件读写操作的。

在java中,对数据进行读写操作非常容易!下图展示了Java中数据流转的大致过程:

数据从数据源通过管道(stream)流转之数据目的地,管道的入口我们称之为input,出口称之为out,因此,数据流转操作也称之为IO操作。java中就封装了IO类帮助我们操作文件。

文件流操作

要操作一个文件,我们必须先创建文件对象,使用文件路径关联系统文件。

如图,我们Data文件夹有一个名 为testData的txt文件

想要获得文件路径,我们可以按照下图的操作方式获取

关联好文件路径,我们就可以对文件进行一些操作了:

文件基础操作

import java.io.File;

public class Data_IO {
    public static void main(String[] args) {
        // 文件流操作 基于 java.io
        // 使用文件路径关联系统文件
        String filePath = "D:\Code\JAVA\collection\src\Data\testData.txt";

        //  创建文件对象
        File file = new File(filePath);
        
        // 文件对象的操作

        // 判断当前文件对象是否文件(File对象也可能是文件夹)
        System.out.println(file.isFile());            // true
        // 判断文件对象是否为文件夹
        System.out.println(file.isDirectory());       // false
        // 判断文件是否关联成功
        System.out.println(file.exists());            // true
        // 获取文件名称
        System.out.println(file.getName());           // testData.txt
        // 获取文件长度
        System.out.println(file.lastModified());      // 1698977593862
        // 获取文件的绝对路径
        System.out.println(file.getAbsolutePath());   // D:\Code\JAVA\collection\src\Data\testData.txt
    }
}

文件夹基础操作

文件夹的一些基础方法和文件是一致的。但有几个方法是文件夹操作独有的,如

获取文件夹内的数据列表

获取文件夹中的文件对象

File[] files = file.listFiles();
for (File file1 : files) {
    System.out.println(file1 );  // testData.txt
}

文件复制

在java中,实现文件复制是一个稍微复杂的过程。现在,我们通过一个示例来演示下代码。我们需要在Data文件夹下创建一个testData的副本文件testData_copy.txt

java中,对象复制的流程大致如下模型

首先,我们需要数据源对象数据目的对象:

import java.io.*;

public class IO_Copy {
    public static void main(String[] args) {
        // 数据源对象
        File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt");
        // 数据目的地对象
        File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt");
    }
}

数据目的对象的路径并不存在,是我们自己定义的要生成的文件路径。

然后,我们要创建文件输入管道1文件输出管道2:

import java.io.*;

public class IO_Copy {
    public static void main(String[] args) {
        // 数据源对象
        File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt");
        // 数据目的地对象
        File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt");
        // 文件输入流(管道对象)
        FileInputStream in = null;
        // 文件输出流(管道对象)
        FileOutputStream out = null;
    }
}

接下来,我们就要打开阀门1阀门2进行数据流转了

in = new FileInputStream(srcFile);
out = new FileOutputStream(destFile);
// 打开阀门,流转数据(输入端)
int data = in.read();
// 打开阀门,流转数据(输出端)
out.write(data);

数据流转完毕,我们需要关闭管道

in.close();
out.close();

当然,数据操作过程中,存在很多异常情况,比如找不到数据源文件等等,所以实际代码中,我们需要进行异常处理。比较完成的代码如下:

import java.io.*;

public class IO_Copy {
    public static void main(String[] args) {
        // 数据源对象
        File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt");
        // 数据目的地对象
        File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt");

        // 文件输入流(管道对象)
        FileInputStream in = null;
        // 文件输出流(管道对象)
        FileOutputStream out = null;
        try {
            in = new FileInputStream(srcFile);
            out = new FileOutputStream(destFile);
            // 打开阀门1,流转数据(输入端)
            int data = in.read();
            // 打开阀门2,流转数据(输出端)
            out.write(data);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if(in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if(out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

我们来运行看看

可以看到,文件复制的确完成了,但是为什么复制出来的文件只有一个H字符???

这其实和java的文件复制原理有关,文件流复制时,是这个过程:

复制时,阀门1打开,H字符进入管道1:

H字符进入管道2时,阀门1关闭,阀门2打开

H字符进入数据目的地后,阀门2也随之关闭,复制完成

在上述代码中,我们的阀门1阀门2只开启过一次,自然只能复制一个H字符

in = new FileInputStream(srcFile);
out = new FileOutputStream(destFile);
// 打开阀门1,流转数据(输入端)
int data = in.read();
// 打开阀门2,流转数据(输出端)
out.write(data);

所以很简单,我们只需要循环执行上述代码即可!那该执行几次呢?我们看下面代码:

我们将阀门多开启了一次,导致副本文件多了一个乱码字符,通过打印结果可见,当data值为-1前,终止这个循环即可!改写代码:

import java.io.*;

public class IO_Copy {
    public static void main(String[] args) {
        // 数据源对象
        File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt");
        // 数据目的地对象
        File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt");

        // 文件输入流(管道对象)
        FileInputStream in = null;
        // 文件输出流(管道对象)
        FileOutputStream out = null;
        try {
            in = new FileInputStream(srcFile);
            out = new FileOutputStream(destFile);
            // 打开阀门,流转数据(输入端)
            int data = in.read();
            out.write(data);

            // 打开阀门,流转数据(输出端)
            while ((data = in.read()) != -1){
                out.write(data);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if(in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if(out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

缓冲流

上述的文件复制效率很低,每复制一个字符,都要开启关闭阀门一次,因此,java也提供了缓冲区的优化方式。

它的概念非常容易,就是在文件传输的管道中,增加了一个缓冲管道

其复制流程大致如下:

阀门1打开,所有内容进入管道1

阀门1关闭,所有内容进入缓冲区

缓冲区内容进入管道2阀门2打开

管道2内容进入数据目的地,复制完成,阀门2关闭。

完整代码如下:

import java.io.*;

public class IO_Copy {
    public static void main(String[] args) {
        // 数据源对象
        File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt");
        // 数据目的地对象
        File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt");

        // 文件输入流(管道对象)
        FileInputStream in = null;
        // 文件输出流(管道对象)
        FileOutputStream out = null;

        // 缓冲输入流
        BufferedInputStream bufferIn = null;
        BufferedOutputStream bufferOut = null;

        // 创建一个大小为1024字节的缓存区cache。这将用于存储从源文件读取的数据,然后再写入目标文件。
        byte[] cache = new byte[1024];

        try {
            in = new FileInputStream(srcFile);
            out = new FileOutputStream(destFile);
            // 缓冲输入流
            bufferIn = new BufferedInputStream(in);
            // 缓冲输出流
            bufferOut = new BufferedOutputStream(out);

            // 数据流转
            int data;
            // 当读取到文件末尾(即data为-1)时,循环结束。
            while ((data = bufferIn.read(cache)) != -1){
                bufferOut.write(cache,0,data);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if(bufferIn != null){
                try {
                    bufferIn.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if(bufferOut != null){
                try {
                    bufferOut.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

字符流操作

文件流的操作是基于文件的字节实现的。字符流的操作提供了另一种通过一行字符的形式操作数据。

再文件复制时,它会将一整行的字符一次性复制过去。

它的语法流程如下

首先,定义两个File对象,srcFile和destFile。这两个对象分别代表了源文件(我们要从中读取数据的文件)和目标文件(我们要写入数据的文件)。

// 数据源对象
File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt");
// 数据目的地对象
File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt");

然后,创建了两个流对象,reader和writer。这两个对象分别用于从源文件读取数据和向目标文件写入数据。

BufferedReader reader = null;  
PrintWriter writer = null;

接着,使用reader读取源文件的内容,而writer会向目标文件写入内容。

try {  
    reader = new BufferedReader(new FileReader(srcFile));  
    writer = new PrintWriter(destFile);  
    ...  
} catch (IOException e) {  
    throw new RuntimeException(e);  
}

在try块中,读取源文件的内容。每次读取一行,直到文件结束(也就是没有更多的行可以读取)。每读取一行,我们都会打印这一行(在控制台输出),并且写入到目标文件。

while ((line = reader.readLine()) != null){  
    System.out.println(line);  // 打印到控制台  
    writer.println(line);      // 写入到目标文件  
}

在读取和写入操作结束后,我们调用writer.flush()方法,确保所有待写入的数据都被立即写入到目标文件。

writer.flush();

完整代码如下:

import java.io.*;

public class IO_Copy {
    public static void main(String[] args) {
        // 数据源对象
        File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt");
        // 数据目的地对象
        File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt");

        // 字符输入流(管道对象)
        BufferedReader reader = null;
        // 字符输出流(管道对象)
        PrintWriter writer = null;

        try {
            reader = new BufferedReader(new FileReader(srcFile));
            writer = new PrintWriter(destFile);


            // 读取文件的一行数据(字符串)
            String line = null;

            while ((line = reader.readLine()) != null){
                System.out.println(line);  // Hello
                writer.println(line);
            }
            // 刷写数据
            writer.flush();

        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if(reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

以上就是一文带你搞懂Java中的数据流处理的详细内容,更多关于Java数据流处理的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot框架集成ElasticSearch实现过程示例详解

    SpringBoot框架集成ElasticSearch实现过程示例详解

    这篇文章主要为大家介绍了SpringBoot如何集成ElasticSearch的实现过程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2021-11-11
  • 一次Jvm old过高的排查过程实战记录

    一次Jvm old过高的排查过程实战记录

    这篇文章主要给大家介绍了一次Jvm old过高的排查过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • Java开发之普通web项目转为Maven项目的方法

    Java开发之普通web项目转为Maven项目的方法

    这篇文章主要给大家介绍了关于Java开发之普通web项目转为Maven项目的相关资料,文中通过图文将转换的方法步骤介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-12-12
  • SpringBoot注册web组件的实现方式

    SpringBoot注册web组件的实现方式

    Servlet是Java Web应用程序的基础,它提供了处理客户端请求的机制,Servlet三大组件是指Servlet、Filter和Listener,它们是Java Web应用程序的核心组件,本文将给大家介绍一下SpringBoot注册web组件的实现方式,需要的朋友可以参考下
    2023-10-10
  • MyBatisPlus代码生成器的使用示例

    MyBatisPlus代码生成器的使用示例

    本文主要介绍了MyBatisPlus代码生成器的使用示例,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,感兴趣的可以了解一下
    2021-12-12
  • IntelliJ IDEA如何集成maven

    IntelliJ IDEA如何集成maven

    这篇文章主要介绍了IntelliJ IDEA如何集成maven问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • springboot 整合dubbo3开发rest应用的场景分析

    springboot 整合dubbo3开发rest应用的场景分析

    这篇文章主要介绍了springboot 整合dubbo3开发rest应用,本文通过实际的案例演示下基于 dubbo的2.7.X的版本,整合springboot完成一个rest应用开发和调用的案例,需要的朋友可以参考下
    2022-09-09
  • GC算法实现垃圾优先算法

    GC算法实现垃圾优先算法

    为什么会存在那么多的垃圾回收算法呢?我想这个问题的答案可能是没有任何一种内存回收算法是完美的,所以在针对不同的情景需求下,不同的内存回收算法有其独特的优势,所以最后就延续了多种回收算法
    2022-01-01
  • Java状态机的一种优雅写法分享

    Java状态机的一种优雅写法分享

    状态机是一种数学模型,对于我们业务实现有很大的帮助。我们可以用非常多的方法实现状态机,这篇文章就来介绍一个状态机优雅的实现方法,希望对大家有所帮助
    2023-04-04
  • 使用IDEA如何打包发布SpringBoot并部署到云服务器

    使用IDEA如何打包发布SpringBoot并部署到云服务器

    这篇文章主要介绍了使用IDEA如何打包发布SpringBoot并部署到云服务器问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12

最新评论