java高质量数据流概念讲解,保证一篇文章帮助你搞懂概念!

简介: 【8月更文挑战第11天】java高质量数据流概念讲解,保证一篇文章帮助你搞懂概念!

数据流转

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

在java中,对数据进行读写操作非常容易!下图展示了Java中数据流转的大致过程:
数据从数据源通过管道(stream)流转之数据目的地,管道的入口我们称之为input,出口称之为out,因此,数据流转操作也称之为IO操作。java中就封装了IO类帮助我们操作文件。
image.png

文件流操作

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

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

想要获得文件路径,我们可以按照下图的操作方式获取GIF 2023-11-3 10-16-42.gif
关联好文件路径,我们就可以对文件进行一些操作了:

文件基础操作

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
    }
}

文件夹基础操作

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

  • 获取文件夹内的数据列表

GIF 2023-11-3 11-12-20.gif

  • 获取文件夹中的文件对象
    File[] files = file.listFiles();
    for (File file1 : files) {
         
         
      System.out.println(file1 );  // testData.txt
    }
    

    文件复制

    在java中,实现文件复制是一个稍微复杂的过程。现在,我们通过一个示例来演示下代码。我们需要在Data文件夹下创建一个testData的副本文件testData_copy.txt
    image.png
    java中,对象复制的流程大致如下模型image.png
    首先,我们需要数据源对象数据目的对象:
    ```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:**
```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");
        // 文件输入流(管道对象)
        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);
                }
            }
        }
    }
}

我们来运行看看GIF 2023-11-3 14-53-35.gif
可以看到,文件复制的确完成了,但是为什么复制出来的文件只有一个H字符???
这其实和java的文件复制原理有关,文件流复制时,是这个过程:

复制时,阀门1打开,H字符进入管道1:
image.png
H字符进入管道2时,阀门1关闭,阀门2打开
image.png
H字符进入数据目的地后,阀门2也随之关闭,复制完成
image.png
在上述代码中,我们的阀门1阀门2只开启过一次,自然只能复制一个H字符

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

所以很简单,我们只需要循环执行上述代码即可!那该执行几次呢?我们看下面代码:GIF 2023-11-3 15-06-43.gif
我们将阀门多开启了一次,导致副本文件多了一个乱码字符,通过打印结果可见,当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也提供了缓冲区的优化方式。
它的概念非常容易,就是在文件传输的管道中,增加了一个缓冲管道

image.png
其复制流程大致如下:
阀门1打开,所有内容进入管道1image.png
阀门1关闭,所有内容进入缓冲区
image.png
缓冲区内容进入管道2阀门2打开image.png
管道2内容进入数据目的地,复制完成,阀门2关闭。
image.png
完整代码如下:

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);
                }
            }
        }
    }
}

字符流操作

文件流的操作是基于文件的字节实现的。字符流的操作提供了另一种通过一行字符的形式操作数据。
image.png
再文件复制时,它会将一整行的字符一次性复制过去。

它的语法流程如下
首先,定义两个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);
                }
            }
        }
    }
}
相关文章
|
27天前
|
存储 安全 Java
从入门到精通:Java Map全攻略,一篇文章就够了!
【10月更文挑战第17天】本文详细介绍了Java编程中Map的使用,涵盖Map的基本概念、创建、访问与修改、遍历方法、常用实现类(如HashMap、TreeMap、LinkedHashMap)及其特点,以及Map在多线程环境下的并发处理和性能优化技巧,适合初学者和进阶者学习。
40 3
|
3月前
|
Java 程序员
Java中的继承和多态:理解面向对象编程的核心概念
【8月更文挑战第22天】在Java的世界中,继承和多态不仅仅是编程技巧,它们是构建可维护、可扩展软件架构的基石。通过本文,我们将深入探讨这两个概念,并揭示它们如何共同作用于面向对象编程(OOP)的实践之中。你将了解继承如何简化代码重用,以及多态如何为程序提供灵活性和扩展性。让我们启程,探索Java语言中这些强大特性的秘密。
|
3月前
|
前端开发 Java 编译器
【前端学java】java基础练习缺少项目?看这篇文章就够了!(完结)
【8月更文挑战第11天】java基础练习缺少项目?看这篇文章就够了!(完结)
40 0
|
18天前
|
算法 Java 数据库连接
Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性
本文详细介绍了Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性。连接池通过复用数据库连接,显著提升了应用的性能和稳定性。文章还展示了使用HikariCP连接池的示例代码,帮助读者更好地理解和应用这一技术。
31 1
|
25天前
|
存储 安全 Java
从入门到精通:Java Map全攻略,一篇文章就够了!
【10月更文挑战第19天】本文介绍了Java编程中重要的数据结构——Map,通过问答形式讲解了Map的基本概念、创建、访问与修改、遍历方法、常用实现类(如HashMap、TreeMap、LinkedHashMap)及其特点,以及Map在多线程环境下的使用和性能优化技巧,适合初学者和进阶者学习。
42 4
|
2月前
|
监控 算法 Java
深入理解Java中的垃圾回收机制在Java编程中,垃圾回收(Garbage Collection, GC)是一个核心概念,它自动管理内存,帮助开发者避免内存泄漏和溢出问题。本文将探讨Java中的垃圾回收机制,包括其基本原理、不同类型的垃圾收集器以及如何调优垃圾回收性能。通过深入浅出的方式,让读者对Java的垃圾回收有一个全面的认识。
本文详细介绍了Java中的垃圾回收机制,从基本原理到不同类型垃圾收集器的工作原理,再到实际调优策略。通过通俗易懂的语言和条理清晰的解释,帮助读者更好地理解和应用Java的垃圾回收技术,从而编写出更高效、稳定的Java应用程序。
|
3月前
|
存储 前端开发 JavaScript
【前端学java】一篇文章带你精通java 中的数组(10)
【8月更文挑战第10天】一篇文章带你精通java 中的数组
17 3
【前端学java】一篇文章带你精通java 中的数组(10)
|
3月前
|
Java Docker 微服务
微服务架构的概念、特点以及如何在Java Web开发中实现微服务。
微服务架构的概念、特点以及如何在Java Web开发中实现微服务。
88 1
|
3月前
|
存储 安全 搜索推荐
深入探讨Session和Cookie的概念、用途以及如何在Java Web开发中有效地使用它们进行用户状态管理。
在Java Web开发中,Session和Cookie是管理用户状态的核心技术。Session存储于服务器端,通过唯一的Session ID识别用户,确保数据安全与隐私;Cookie则存储于客户端,用于记录用户偏好等信息。两者各有优势:Session适合存储敏感数据,但需合理管理避免资源浪费;Cookie便于持久化存储,但在安全性上需谨慎设置。开发者可通过Servlet API轻松操作二者,实现个性化用户体验与应用性能优化。
59 2
|
3月前
|
设计模式 Java
常用设计模式介绍~~~ Java实现 【概念+案例+代码】
文章提供了一份常用设计模式的全面介绍,包括创建型模式、结构型模式和行为型模式。每种设计模式都有详细的概念讲解、案例说明、代码实例以及运行截图。作者通过这些模式的介绍,旨在帮助读者更好地理解源码、编写更优雅的代码,并进行系统重构。同时,文章还提供了GitHub上的源码地址,方便读者直接访问和学习。
常用设计模式介绍~~~ Java实现 【概念+案例+代码】