【Java EE】文件内容的读写⸺数据流

目录

  • 🌴数据流的概念
    • 🌸数据流分类
  • 🌳字节流的读写
    • 🌸InputStream(从文件中读取字节内容)
      • 🌻示例1
      • 🌻示例2
      • 🌻利用 Scanner 进行字符读取
    • 🌸OutputStream(向文件中写内容)
      • 🌻示例1
      • 🌻示例2
      • 🌻利⽤ PrintWriter 找到我们熟悉的⽅法
  • 🎄字符流的读写
    • 🌸Reader(读操作)
    • 🌸Writer(写操作)
  • 🦚小程序练习
    • 练习一
    • 练习二
    • 练习三

🌴数据流的概念

在这里插入图片描述
数据流是一串连续不断的数据的集合,就象水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流。

数据写入程序可以是一段、一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流。对数据读取程序来说,看不到数据流在写入时的分段情况,每次可以读取其中的任意长度的数据,但只能先读取前面的数据后,再读取后面的数据。

不管写入时是将数据分多次写入,还是作为一个整体一次写入,读取时的效果都是完全一样的。

“流是磁盘或其它外围设备中存储的数据的源点或终点。”

在电脑上的数据有三种存储方式,一种是外存,一种是内存,一种是缓存。比如电脑上的硬盘,磁盘,U盘等都是外存,在电脑上有内存条,缓存是在CPU里面的。外存的存储量最大,其次是内存,最后是缓存,但是外存的数据的读取最慢,其次是内存,缓存最快。这里总结从外存读取数据到内存以及将数据从内存写到外存中。

对于内存和外存的理解,我们可以简单的理解为容器,即外存是一个容器,内存又是另外一个容器。那又怎样把放在外存这个容器内的数据读取到内存这个容器以及怎么把内存这个容器里的数据存到外存中呢?

在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:

标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流等等,java中将输入输出抽象称为流,就好像水管,将两个容器连接起来。将数据冲外存中读取到内存中的称为输入流,将数据从内存写入外存中的称为输出流。

流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。

总结的基本概念如下:

数据流:一组有序,有起点和终点的字节的数据序列。包括输入流和输出流。
输入流(Input Stream):程序从输入流读取数据源。数据源包括外界(键盘、文件、网络…),即是将数据源读入到程序的通信通道
输出流(Output Stream):程序向输出流写入数据。将程序中的数据输出到外界(显示器、打印机、文件、网络…)的通信通道。
采用数据流的目的就是使得输出输入独立于设备。Input Stream不关心数据源来自何种设备(键盘,文件,网络)Output Stream不关心数据的目的是何种设备(键盘,文件,网络)

🌸数据流分类

流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种:

  • 字节流:数据流中最小的数据单元是字节

  • 字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。

🌳字节流的读写

🌸InputStream(从文件中读取字节内容)

方法
在这里插入图片描述

说明
InputStream 只是⼀个抽象类,要使⽤还需要具体的实现类。关于 InputStream 的实现类有很多,基
本可以认为不同的输⼊设备都可以对应⼀个 InputStream 类,我们现在只关⼼从⽂件中读取,所以使
⽤== FileInputStream==

FileInputStream构造方法

签名说明
FileInputStream(File file)利用 File 构造文件输入流
FileInputStream(String name)利用文件路径构造文件输入流

我们在使用该实例化对对象进行操作时我们该可以分为以下几步

  1. 打开文件
  2. 进行读写操作
  3. 关闭文件

但是这里我们需要注意的是,每一次打开文件都会消耗一些相应的资源,而每一个进程的资源时有限的,所以我们一定要注意关闭文件操作,但是关闭文件操作可能会因为某些情况忘记写,或者没执行到。这时候就会出现问题

这时候我们想到一个办法,使用final进行执行这一步操作

InputStream reader = new FileInputStream("D:/tmp.txt");
try {
	//一系列读写操作
} finally {
	reader.close();
}

但是这样写太繁琐,代码也不美观,所以Java里面提供了以下写法

try(InputStream reader = new FileInputStream("D:/tmp.txt")) {
	//	一系列操作
}

这里虽然没有写会执行到close,但是在try执行结束后就会执行到;

这是因为该类实现了Closeable接口
在这里插入图片描述

🌻示例1

将⽂件完全读完的两种⽅式。相⽐较⽽⾔,后⼀种的 IO 次数更少,性能更好。

  • 方式一:一个字节一个字节读
  • 在这里插入图片描述
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        try (InputStream is = new FileInputStream("hello。txt")) {
            while (true) {
                int b = is.read();
                if (b == -1) {
                // 代表文件已经全部读完
                    break;
                }
                System.out.print((char)b + "");
            }
        }
    }
}

结果:
在这里插入图片描述

  • 方式二:缓冲区读法
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        try (InputStream is = new FileInputStream("hello")) {
            while (true) {
                byte[] buffer = new byte[1024];
                int b = is.read(buffer);
                if (b == -1) {
                // 代表文件已经全部读完
                    break;
                }
                for(int i = 0; i < b ; i ++) {
                    System.out.print((char) buffer[i] + "");
                }
            }
        }
    }
}

两种方式对比
更推荐方式二,效率更高,就比如你练习网球发球,你需要不断的发球,一大筐网球放在体育教材室里面,你现在有两种做法,第一种一次:拿一个来发球,发完了,又回去拿,第二种:一次拿一筐放在脚边不断发球

很明显第二种效率更高,上述两种方式也是如此

🌻示例2

这里我们把文件内容中填充中文看看,hello.txt 中填写 “你好”
在这里插入图片描述
注意:写中文的时候使用 UTF-8 编码。如果强转为char会出现乱码问题。

我们使用16进制对结果进行输出时,就输出的是它们各自对应的 UTF-8 编码,如下所示:
在这里插入图片描述
三个字节表示一个字

这里我们就可以利用了这几个中文的 UTF-8 编码后长度刚好是 3 个字节和长度不超过 1024 字节的现状,但这种方式并不是通用的

代码如下:

import java.io.*;
// 需要先在项⽬⽬录下准备好⼀个 hello.txt 的⽂件,⾥⾯填充 "你好" 的内容
public class Main {
 public static void main(String[] args) throws IOException {
  try (InputStream is = new FileInputStream("hello.txt")) {
   byte[] buf = new byte[1024];
   int len;
   while (true) {
    len = is.read(buf);
    if (len == -1) {
     // 代表⽂件已经全部读完
     break;
    }
    // 每次使⽤ 3 字节进⾏ utf-8 解码,得到中⽂字符
    // 利⽤ String 中的构造⽅法完成
    // 这个⽅法了解下即可,不是通⽤的解决办法
    for (int i = 0; i < len; i += 3) {
     String s = new String(buf, i, 3, "UTF-8");
     System.out.printf("%s", s);
    }
   }
  }
 }
}

在这里插入图片描述

🌻利用 Scanner 进行字符读取

上述例⼦中,我们看到了对字符类型直接使⽤ InputStream 进⾏读取是⾮常⿇烦且困难的,所以,我
们使⽤⼀种我们之前⽐较熟悉的类来完成该⼯作,就是 Scanner 类。

构造方法说明
Scanner(InputStream is, String charset)使用 charset 字符集进行 is 的扫描读取

代码实现如下:

import java.io.*;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws IOException {
        try (InputStream is = new FileInputStream("hello.txt")) {
            try (Scanner scanner = new Scanner(is, "UTF-8")) {
                while (scanner.hasNext()) {
                    String s = scanner.next();
                    System.out.print(s);
                }
            }
        }
    }
}

在这里插入图片描述

🌸OutputStream(向文件中写内容)

该类的方法有
| 修饰符及返回值类型 | 方法签名 |
|--|--|
|  |  |

说明
OutputStream 同样只是⼀个抽象类,要使⽤还需要具体的实现类。我们现在还是只关⼼写⼊⽂件
中,所以使⽤ FileOutputStream

接下来
利⽤ OutputStreamWriter 进⾏字符写⼊

🌻示例1

import java.io.*;
public class Main {
 public static void main(String[] args) throws IOException {
 try (OutputStream os = new FileOutputStream("output.txt")) {
 os.write('H');
 os.write('e');
 os.write('l');
 os.write('l');
 os.write('o');
 // 不要忘记 flush
 os.flush();
 }
 }
}

在这里插入图片描述
注意:此处的write操作会先清除该文件里面的内容再进行填充

那么如何才能不清除文件而实现续写呢?其实很简单,我们只需要在构造对象时,使用带有true参数的构造方法就好

比如以下代码对上述文件进行续写操作

public class Main1 {
    public static void main(String[] args) throws IOException {
        try (OutputStream os = new FileOutputStream("hello.txt",true)) {
            os.write('H');
            os.write('e');
            os.write('l');
            os.write('l');
            os.write('o');
            // 不要忘记 flush
            os.flush();
        }
    }
}

最后注意一点:

  • 我们在写操作完成后,一定要flush冲刷一下,也就是刷新一下

🌻示例2

import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException {
        try (OutputStream os = new FileOutputStream("output.txt")) {
            byte[] b = new byte[] {
                    (byte)'G', (byte)'o', (byte)'o', (byte)'d'
            };
            os.write(b);

            // 不要忘记 flush
            os.flush();
        }
    }
}

代码:

import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException {
        try (OutputStream os = new FileOutputStream("output.txt")) {
            byte[] b = new byte[] {
                    (byte)'G', (byte)'o', (byte)'o', (byte)'d', (byte)'B', (byte)'a'
            };
            os.write(b, 0, 4);

            // 不要忘记 flush
            os.flush();
        }
    }
}

代码:
写入汉字

import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException {
        try (OutputStream os = new FileOutputStream("output.txt")) {
            String s = "你好中国";
            byte[] b = s.getBytes("utf-8");
            os.write(b);

            // 不要忘记 flush
            os.flush();
        }
    }
}

🌻利⽤ PrintWriter 找到我们熟悉的⽅法

上述,我们其实已经完成输出⼯作,但总是有所不⽅便,我们接来下将 OutputStream 处理下,使⽤
PrintWriter 类来完成输出,因为
PrintWriter 类中提供了我们熟悉的 print/println/printf ⽅法

    OutputStream os = ...;
        OutputStreamWriter osWriter = new OutputStreamWriter(os, "utf-8"); // 告诉
        PrintWriter writer = new PrintWriter(osWriter);
// 接下来我们就可以⽅便的使⽤ writer 提供的各种⽅法了
        writer.print("Hello");
        writer.println("你好");
        writer.printf("%d: %s\n", 1, "没什么");
// 不要忘记 flush
        writer.flush();

🎄字符流的读写

🌸Reader(读操作)

这里是需要实例化一个 FileReader进行操作,可使用的方法参考字节流

这里的字符流操作与字节流操作类似,这里不做过多赘述,直接看代码

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class IODemo3 {
    public static void main(String[] args) {
        try(Reader reader = new FileReader("D:/tmp.txt")) {
            while(true) {
                int n = reader.read();
                if(n == -1) {
                    break;
                }
                System.out.print((char)n + "");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

再来一个数组版本的吧

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class IODemo3 {
    public static void main(String[] args) {
        char[] arr = new char[1024];
        try(Reader reader = new FileReader("D:/tmp.txt")) {
            while(true) {
                int n = reader.read(arr);
                if(n == -1) {
                    break;
                }
                for(int i = 0; i < n ; i ++) {
                    System.out.print(arr[i] + "");
                }

            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

🌸Writer(写操作)

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class IODemo4 {
    public static void main(String[] args) {
        try(Writer writ = new FileWriter("D:/tmp.txt")) {
            writ.write("祝大家万事如意!");
            writ.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

🦚小程序练习

练习一

扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件

import java.io.*;
import java.util.*;
public class Test1 {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入要扫描的根目录(绝对路径 OR 相对路径): ");
        String rootDirPath = scanner.next();
        File rootDir = new File(rootDirPath);
        if (!rootDir.isDirectory()) {
            System.out.println("您输入的根目录不存在或者不是目录,退出");
            return;
        }
        System.out.print("请输入要找出的文件名中的字符: ");
        String token = scanner.next();
        List<File> result = new ArrayList<>();
// 因为文件系统是树形结构,所以我们使用深度优先遍历(递归)完成遍历
        scanDir(rootDir, token, result);
        System.out.println("共找到了符合条件的文件 " + result.size() + " 个,它们分别是");
        for (File file : result) {
            System.out.println(file.getCanonicalPath() + " 请问您是否要删除该文件?y/n");
                    String in = scanner.next();
            if (in.toLowerCase().equals("y")) {
                file.delete();
            }
        }
    }
    private static void scanDir(File rootDir, String token, List<File> result) {
        File[] files = rootDir.listFiles();
        if (files == null || files.length == 0) {
            return;
        }
        for (File file : files) {
            if (file.isDirectory()) {
                scanDir(file, token, result);
            } else {
                if (file.getName().contains(token)) {
                    result.add(file.getAbsoluteFile());
                }
            }
        }
    }
}

练习二

进行普通文件的复制

import java.io.*;
import java.util.*;
public class Test2 {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入要复制的文件(绝对路径 OR 相对路径): ");
        String sourcePath = scanner.next();
        File sourceFile = new File(sourcePath);
        if (!sourceFile.exists()) {
            System.out.println("文件不存在,请确认路径是否正确");
            return;
        }
        if (!sourceFile.isFile()) {
            System.out.println("文件不是普通文件,请确认路径是否正确");
            return;
        }
        System.out.print("请输入要复制到的目标路径(绝对路径 OR 相对路径): ");
        String destPath = scanner.next();
        File destFile = new File(destPath);
        if (destFile.exists()) {
            if (destFile.isDirectory()) {
                System.out.println("目标路径已经存在,并且是一个目录,请确认路径是否正确");
                return;
            }
            if (destFile.isFile()) {
                System.out.println("目录路径已经存在,是否要进行覆盖?y/n");
                String ans = scanner.next();
                if (!ans.toLowerCase().equals("y")) {
                    System.out.println("停止复制");
                    return;
                }
            }
        }
        try (InputStream is = new FileInputStream(sourceFile)) {
            try (OutputStream os = new FileOutputStream(destFile)) {
                byte[] buf = new byte[1024];
                int len;
                while (true) {
                    len = is.read(buf);
                    if (len == -1) {
                        break;
                    }
                    os.write(buf, 0, len);
                }
                os.flush();
            }
        }
        System.out.println("复制已完成");
    }
}

练习三

扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)

注意:我们现在的方案性能较差,所以尽量不要在太复杂的目录下或者大文件下实验

import java.io.*;
import java.util.*;
public class Test3 {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入要扫描的根目录(绝对路径 OR 相对路径): ");
        String rootDirPath = scanner.next();
        File rootDir = new File(rootDirPath);
        if (!rootDir.isDirectory()) {
            System.out.println("您输入的根目录不存在或者不是目录,退出");
            return;
        }
        System.out.print("请输入要找出的文件名中的字符: ");
        String token = scanner.next();
        List<File> result = new ArrayList<>();
		// 因为文件系统是树形结构,所以我们使用深度优先遍历(递归)完成遍历
        scanDirWithContent(rootDir, token, result);
        System.out.println("共找到了符合条件的文件 " + result.size() + " 个,它们分别是");
        for (File file : result) {
            System.out.println(file.getCanonicalPath());
        }
    }
    private static void scanDirWithContent(File rootDir, String token,
                                           List<File> result) throws IOException {
        File[] files = rootDir.listFiles();
        if (files == null || files.length == 0) {
            return;
        }
        for (File file : files) {
            if (file.isDirectory()) {
                scanDirWithContent(file, token, result);
            } else {
                if (isContentContains(file, token)) {
                    result.add(file.getAbsoluteFile());
                }
            }
        }
    }
    // 我们全部按照utf-8的字符文件来处理
    private static boolean isContentContains(File file, String token) throws
            IOException {
        StringBuilder sb = new StringBuilder();
        try (InputStream is = new FileInputStream(file)) {
            try (Scanner scanner = new Scanner(is, "UTF-8")) {
                while (scanner.hasNextLine()) {
                    sb.append(scanner.nextLine());
                    sb.append("\r\n");
                }
            }
        }
        return sb.indexOf(token) != -1;
    }
}

⭕总结
关于《【Java EE】文件内容的读写⸺数据流》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/433691.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

阿里云重新更新系统导致秘钥失效

报错解决方案&#xff1a; ssh-keygen -f "/Users/pengzhanliang/.ssh/known_hosts" -R "39.105.149.49"这个命令会从~/.ssh/known_hosts文件中移除与IP地址39.105.149.49相关的所有条目 再次尝试连接到远程服务器。这次&#xff0c;SSH将提示您接受新的主…

简单、透明、安全、高度集成!龙蜥可信 SBOM 能力探索与实践

近两年&#xff0c;软件供应链有非常多安全事件&#xff0c;包括软件供应链的各个阶段开发、构建、交付、使用等每个环节都有很多的软件供应链的安全事件发生。在 2023 龙蜥操作系统大会全面建设安全生态分论坛上&#xff0c;阿里云技术专家郑耿、周彭晨分享了龙蜥社区在构建 S…

企业计算机服务器中了faust勒索病毒怎么解密,faust勒索病毒解密流程

网络在为企业提供便利的同时&#xff0c;也为企业的数据安全问题带来严重威胁&#xff0c;网络安全是众多企业关系的主要话题&#xff0c;近期&#xff0c;云天数据恢复中心接到一大波企业的求助&#xff0c;企业的计算机服务器都被faust后缀勒索病毒攻击&#xff0c;导致企业计…

Electron 多显示器渲染

Electron打出的包&#xff0c;如果当前有俩个显示器&#xff0c;则可以配置当前显示倒哪个显示器上&#xff0c;或者可以配置不同的显示器&#xff0c;启动不同的项目&#xff0c;只在Windows和Linux下测试过&#xff0c;Mac没有真机&#xff0c;可以利用docker安装MacOS环境&a…

Jmeter性能测试 -3数据驱动实战

什么是数据驱动&#xff1f; 从数据文件中读取测试数据&#xff0c;驱动测试过程的一种测试方法。数据驱动可以理解为更高级的参数化。 特点&#xff1a;测试数据与测试代码分离&#xff1b;数据控制过程 好处&#xff1a;降低开发和维护成本&#xff0c;减少代码量&#xf…

如何做代币分析:以 LDO 币为例

作者&#xff1a;lesleyfootprint.network 编译&#xff1a;mingfootprint.network 数据源&#xff1a;LDO 代币仪表板 &#xff08;仅包括以太坊数据&#xff09; 在加密货币和数字资产领域&#xff0c;代币分析起着至关重要的作用。代币分析指的是深入研究与代币相关的数据…

数字社交时代的引领者:Facebook的元宇宙探索

引言&#xff1a; 在当今数字社交时代&#xff0c;人们的社交方式正在经历着翻天覆地的变化。随着虚拟现实技术的不断发展和元宇宙概念的崛起&#xff0c;社交网络正朝着一个全新的未来迈进。作为全球最大的社交网络平台之一&#xff0c;Facebook正在积极探索元宇宙时代的社交…

理解npm run dev 和 npm run serve的区别

文章目录 1. 分析npm run2. dev与serve的区别 1. 分析npm run npm npm 是 Node.js 的包管理器&#xff0c;它允许你安装、更新、删除和管理 Node.js 的模块和应用程序。 run run 是 npm 的一个子命令&#xff0c;用于执行在 package.json 文件的 scripts 部分定义的脚本。 dev…

C++初阶篇----类与对象下卷

目录 1.再谈析构函数1.1构造函数体赋值1.2 初始化列表1.3 explicit关键字 2.Static成员2.1概念2.2 特性 3.友元3.1 概念3.2友元函数3.3 友元类 4.内部类4.1 概念 5.匿名对象5.1 概念 6.拷贝对象时的一些编译器优化7.再次理解封装 1.再谈析构函数 1.1构造函数体赋值 在对类的实…

ssm基于javaEE+springboot校园闲置二手物品拍卖交易平台_ngad7

为提升浏览用户观感及使用体验&#xff0c;本系统要具有易用性和美观性。通过页面的简单提示就可完成操作&#xff0c;校园闲置物品交易平台展示界面应该清楚简洁&#xff0c;使用户通过美观的前台页面能快速定位想要浏览的校园闲置物品交易平台信息。后台界面也应简约&#xf…

Ubuntu22.04系统 安装cAdvisor提示找不到 CPU 的挂载点错误解决办法。

如果我们在安装cAdvisor时容器启动不起来 查看日志如下图所示 1、查看cgroup文件系统是v2 还是 v1 mount | grep cgroup 如图所示我的是v2 &#xff0c; cAdvisor 目前的最新版本&#xff08;v0.39.0&#xff09;仍然只支持 cgroup v1&#xff0c;不支持 cgroup v2。因此&#…

CAN通信篇 - ComM模块配置(六)

文章目录 ComMConfigSetComMChannelComMUserPerChannelComMNetworkManagementComMPncComMGeneralComMGeneration总结ComM模块时通信控制模块。在ComM模块中存在三个概念:通道、用户、Pnc,但在本文我们暂时先不介绍Pnc相关功能需要的配置,仅关注基本CAN通信需要的配置。ComM模…

本机虚拟机centos7设置固定ip

一、配置虚拟机网络 1、点击编辑 2、点击更改设置 记住子网地址&#xff1a;192.168.121.0 点击确定 二、配置虚拟机网络配置文件 首先进去root中&#xff0c;然后进入vim编辑器中 (1)su - root (2) vim /etc/sysconfig/network-scripts/ifcfg-ens33 在VIM编辑器中修改并添加…

MATLAB环境下基于离散小波变换的体外血管图像处理

下面简要介绍小波变换的部分应用。 信号去噪。小波去噪是根据有效信号和噪声信号在小波变换后表现出的不同特性实现的&#xff0c;一般可用于去除语音、图像、视频等中的噪声信号。小波去噪方法根据对小波系数的非线性处理方式分为三类&#xff0c;分别是小波变换模极大值去噪…

【C++】string 类

1. 标准库中的string类 注意&#xff1a; 1. string是表示字符串的字符串类 2. 该类的接口与常规容器的接口基本相同&#xff0c;再添加了一些专门用来操作string的常规操作。 比特就业课 3. string在底层实际是&#xff1a;basic_string模板类的别名&#xff0c;typedef b…

HBuilder X 关于404问题

大家好&#xff0c;我是晴天学长&#xff0c;本次分享来自昨天的bug调试,本分享感谢一位友友的支持&#xff0c;提供了样例图片。&#x1f4aa;&#x1f4aa;&#x1f4aa; 1) .先项目再html文件 创建项目再创建html&#xff0c;实也不复杂&#xff0c;就是一个库的事情&#…

力扣经典题目解析--反转链表

原题地址: . - 力扣&#xff08;LeetCode&#xff09; 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 题目解析 链表&#xff08;Linked List&…

【Java】关于ZooKeeper的原理以及一致性问题,协议和算法和ZooKeeper的理论知识和应用 场景

1. 目录 目录 1. 目录 2. 什么是ZooKeeper 3. 一致性问题 4. 一致性协议和算法 4.1. 2PC&#xff08;两阶段提交&#xff09; 4.2. 3PC&#xff08;三阶段提交&#xff09; 4.3. Paxos 算法 4.3.1. prepare 阶段 4.3.2. accept 阶段 4.3.3. paxos 算法的死循环…

3d怎么拖模型---模大狮模型网

在3D建模软件中拖动(移动)模型通常是一种基本的操作&#xff0c;用来调整模型的位置或布局。以下是一般情况下在3D建模软件中拖动模型的基本步骤&#xff1a; 3d拖模型的步骤&#xff1a; 选择模型&#xff1a;在3D建模软件中选中你要拖动的模型。通常可以通过单击模型来选中它…

Docker容器化解决方案

什么是Docker&#xff1f; Docker是一个构建在LXC之上&#xff0c;基于进程容器的轻量级VM解决方案&#xff0c;实现了一种应用程序级别的资源隔离及配额。Docker起源于PaaS提供商dotCloud 基于go语言开发&#xff0c;遵从Apache2.0开源协议。 Docker 自开源后受到广泛的关注和…