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);
                }
            }
        }
    }
}
相关文章
|
2月前
|
存储 缓存 NoSQL
java 集合入门基础理论的核心概念与实用长尾知识
本文介绍了Java集合框架的基础理论知识,包括单列集合(List、Set、Queue)和双列集合(Map)的特点及常用实现类(如ArrayList、HashSet、HashMap等)。详细讲解了集合的遍历方式(迭代器、增强for循环、Lambda表达式)和典型应用场景(如数据去重、键值存储等)。通过具体代码示例,帮助初学者理解集合框架的核心概念和实际应用,为Java编程中的数据存储与管理提供基础指导。
84 0
|
3月前
|
存储 安全 Java
2025 年最新 40 个 Java 基础核心知识点全面梳理一文掌握 Java 基础关键概念
本文系统梳理了Java编程的40个核心知识点,涵盖基础语法、面向对象、集合框架、异常处理、多线程、IO流、反射机制等关键领域。重点包括:JVM运行原理、基本数据类型、封装/继承/多态三大特性、集合类对比(ArrayList vs LinkedList、HashMap vs TreeMap)、异常分类及处理方式、线程创建与同步机制、IO流体系结构以及反射的应用场景。这些基础知识是Java开发的根基,掌握后能为后续框架学习和项目开发奠定坚实基础。文中还提供了代码资源获取方式,方便读者进一步实践学习。
815 2
|
3月前
|
分布式计算 Java 大数据
Java 语言基础概念与常识之主要特点解析
Java是一种广泛应用于企业级开发、移动应用(如Android)、大数据处理及云计算等领域的编程语言。其核心特点包括跨平台性(一次编写,到处运行)、面向对象设计、自动垃圾回收、多线程支持和高性能表现。Java通过JVM实现跨平台,具备强大的健壮性和安全性,同时拥有丰富的标准库与活跃的开发者社区。本文深入解析Java的技术优势及其在电商系统、大数据处理和云计算中的实际应用,并提供相关面试资料供学习参考。
118 0
|
8月前
|
缓存 Java 开发者
Java字面量详解:概念、分类与使用实例
本文介绍了Java字面量的概念、分类及应用。
267 11
|
8月前
|
Java 数据安全/隐私保护
Java的基础概念(二)
本文介绍了Java编程语言中的运算符和表达式,涵盖算术运算符、赋值运算符、关系运算符、逻辑运算符、三元运算符等。重点讲解了算术运算符的使用,如加减乘除取余,并强调了整数除法和取余的特殊性。同时,详细说明了隐式转换与强制转换的概念及应用场景,以及字符串和字符的拼接规则。通过多个案例演示了不同运算符的实际应用,包括数值拆分、自增自减、三元表达式的使用等。最后简要提及了运算符的优先级,指出小括号具有最高优先级。
|
9月前
|
存储 Java 程序员
Java的基础概念一
### Java编程基础简介 #### 一、注释 注释用于解释代码,不会参与编译和运行。Java支持三种注释: - **单行注释**:以 `//` 开头。 - **多行注释**:以 `/* ... */` 包围。 - **文档注释**:通常用于生成开发文档。 #### 二、关键字 关键字是被Java赋予特定含义的英文单词,全部小写,且在代码编辑器中有特殊颜色标记。常用的如 `class` 表示定义一个类。
Java的基础概念一
|
10月前
|
算法 Java 数据库连接
Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性
本文详细介绍了Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性。连接池通过复用数据库连接,显著提升了应用的性能和稳定性。文章还展示了使用HikariCP连接池的示例代码,帮助读者更好地理解和应用这一技术。
182 1
|
11月前
|
存储 安全 Java
从入门到精通:Java Map全攻略,一篇文章就够了!
【10月更文挑战第19天】本文介绍了Java编程中重要的数据结构——Map,通过问答形式讲解了Map的基本概念、创建、访问与修改、遍历方法、常用实现类(如HashMap、TreeMap、LinkedHashMap)及其特点,以及Map在多线程环境下的使用和性能优化技巧,适合初学者和进阶者学习。
381 4
|
11月前
|
存储 安全 Java
从入门到精通:Java Map全攻略,一篇文章就够了!
【10月更文挑战第17天】本文详细介绍了Java编程中Map的使用,涵盖Map的基本概念、创建、访问与修改、遍历方法、常用实现类(如HashMap、TreeMap、LinkedHashMap)及其特点,以及Map在多线程环境下的并发处理和性能优化技巧,适合初学者和进阶者学习。
511 3
|
监控 算法 Java
深入理解Java中的垃圾回收机制在Java编程中,垃圾回收(Garbage Collection, GC)是一个核心概念,它自动管理内存,帮助开发者避免内存泄漏和溢出问题。本文将探讨Java中的垃圾回收机制,包括其基本原理、不同类型的垃圾收集器以及如何调优垃圾回收性能。通过深入浅出的方式,让读者对Java的垃圾回收有一个全面的认识。
本文详细介绍了Java中的垃圾回收机制,从基本原理到不同类型垃圾收集器的工作原理,再到实际调优策略。通过通俗易懂的语言和条理清晰的解释,帮助读者更好地理解和应用Java的垃圾回收技术,从而编写出更高效、稳定的Java应用程序。