【随笔】Java 连接操作FTP与SFTP 详细指南

news2024/11/26 10:30:56
引言

在Java开发中,文件传输协议(FTP)和安全文件传输协议(SFTP)是处理文件传输的两种常见方式。FTP是标准的网络文件传输协议,而SFTP则在FTP基础上增加了安全层(SSH),提供了更加安全的文件传输方式。本文将详细介绍如何在Java中实现与FTP和SFTP服务器的连接,并深入讲解各种函数的用法,以及如何进行二次封装,以提升代码的可复用性和可维护性。
Jsch官网

文章目录

        • 引言
        • 一、Java连接FTP的实现
          • 1. 配置与依赖
          • 2. 基本连接与文件操作
          • 3. 常用函数详解
          • 4. 二次封装的工具类
        • 二、Java连接SFTP的实现
          • 1. 配置与依赖
          • 2. 基本连接与文件操作
          • 3.常用函数详解
          • 4. 二次封装的工具类
            • FTP工具类的级联创建目录封装
            • SFTP工具类的级联创建目录封装
            • 使用注意事项
        • 三、Java连接FTP与SFTP的对比
          • 1. 安全性
          • 2. 性能
          • 3. 支持与兼容性
        • 四、总结与个人看法

一、Java连接FTP的实现

FTP协议(File Transfer Protocol)是一种用于在网络中传输文件的标准协议。Java提供了丰富的库来实现FTP连接,其中最常用的是Apache Commons Net库。该库提供了一个FTPClient类,简化了与FTP服务器的交互。

1. 配置与依赖

在使用FTPClient类之前,首先需要在项目中引入Apache Commons Net库的依赖。在Maven项目中,可以通过在pom.xml文件中添加以下依赖项来实现:

<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.8.0</version>
</dependency>
2. 基本连接与文件操作

使用FTPClient连接到FTP服务器的基本流程如下:

  1. 创建FTPClient对象。
  2. 使用connect方法连接到FTP服务器。
  3. 使用login方法进行身份验证。
  4. 使用相应的方法执行文件操作,如上传、下载、删除文件等。
  5. 使用logout方法注销。
  6. 最后关闭连接。

以下是一个简单的示例,展示了如何连接到FTP服务器并上传文件:

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class FTPExample {
    public static void main(String[] args) {
        FTPClient ftpClient = new FTPClient();
        try {
            // 连接到FTP服务器
            ftpClient.connect("ftp.example.com", 21);
            // 登录到FTP服务器
            ftpClient.login("username", "password");

            // 设置文件传输类型为二进制文件
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

            // 上传文件
            try (InputStream inputStream = new FileInputStream("local/file/path")) {
                boolean done = ftpClient.storeFile("/remote/file/path", inputStream);
                if (done) {
                    System.out.println("The file is uploaded successfully.");
                }
            }

            // 注销并关闭连接
            ftpClient.logout();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (ftpClient.isConnected()) {
                    ftpClient.disconnect();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

在这个示例中,ftpClient.connect用于连接FTP服务器,ftpClient.login进行身份验证,ftpClient.storeFile方法用于上传文件。需要注意的是,FTP传输的默认模式是ASCII,因此在上传二进制文件时,需要调用setFileType(FTP.BINARY_FILE_TYPE)来设置传输模式。

3. 常用函数详解

FTPClient类提供了丰富的功能,以下是一些常用的FTP操作函数:

  • 连接与登录

    • connect(String hostname, int port):连接到指定的FTP服务器和端口。
    • login(String username, String password):使用用户名和密码登录FTP服务器。
    • logout():注销当前用户。
  • 文件操作

    • storeFile(String remote, InputStream local):将本地文件上传到服务器。
    • retrieveFile(String remote, OutputStream local):从服务器下载文件到本地。
    • deleteFile(String pathname):删除服务器上的文件。
    • listFiles(String pathname):列出指定目录下的文件和子目录。
  • 目录操作

    • makeDirectory(String pathname):在服务器上创建一个新目录。
    • removeDirectory(String pathname):删除服务器上的目录。
    • changeWorkingDirectory(String pathname):改变当前工作目录。
    • printWorkingDirectory():获取当前工作目录的路径。
  • 连接管理

    • disconnect():断开与FTP服务器的连接。
    • isConnected():检查是否已连接到服务器。
4. 二次封装的工具类

为了提高代码的可复用性,可以将上述FTP操作封装到一个工具类中。这不仅简化了使用,还可以集中处理异常和日志记录等通用逻辑。

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class FTPUtil {
    private FTPClient ftpClient;

    public FTPUtil(String host, int port, String username, String password) throws IOException {
        ftpClient = new FTPClient();
        ftpClient.connect(host, port);
        ftpClient.login(username, password);
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    }

    public boolean uploadFile(String remoteFilePath, InputStream inputStream) throws IOException {
        try {
            return ftpClient.storeFile(remoteFilePath, inputStream);
        } finally {
            inputStream.close();
        }
    }

    public boolean downloadFile(String remoteFilePath, OutputStream outputStream) throws IOException {
        try {
            return ftpClient.retrieveFile(remoteFilePath, outputStream);
        } finally {
            outputStream.close();
        }
    }

    public boolean deleteFile(String filePath) throws IOException {
        return ftpClient.deleteFile(filePath);
    }

    public void logoutAndDisconnect() throws IOException {
        if (ftpClient.isConnected()) {
            ftpClient.logout();
            ftpClient.disconnect();
        }
    }
}

这个FTPUtil类提供了基本的上传、下载、删除文件功能,并封装了连接和注销逻辑,简化了FTP操作的使用。

二、Java连接SFTP的实现

SFTP(SSH File Transfer Protocol)是基于SSH协议的文件传输协议,提供了更加安全的文件传输方式。Java中实现SFTP连接通常使用JSch库,这个库由JCraft开发,用于SSH2的Java实现。

1. 配置与依赖

在使用JSch库之前,同样需要在项目中引入依赖。在Maven项目中,添加以下依赖项:

<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.55</version>
</dependency>
2. 基本连接与文件操作

使用JSch连接到SFTP服务器的基本流程如下:

  1. 创建JSch对象。
  2. 使用getSession方法创建会话并进行身份验证。
  3. 使用connect方法连接到SFTP服务器。
  4. 使用ChannelSftp对象执行文件操作。
  5. 关闭连接。

以下是一个简单的示例,展示了如何连接到SFTP服务器并上传文件:

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

public class SFTPExample {
    public static void main(String[] args) {
        String SFTPHOST = "sftp.example.com";
        int SFTPPORT = 22;
        String SFTPUSER = "username";
        String SFTPPASS = "password";
        String SFTPWORKINGDIR = "/remote/path/";

        Session session = null;
        ChannelSftp channelSftp = null;

        try {
            JSch jsch = new JSch();
            session = jsch.getSession(SFTPUSER, SFTPHOST, SFTPPORT);
            session.setPassword(SFTPPASS);

            // 配置StrictHostKeyChecking属性
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);

            session.connect();

            channelSftp = (ChannelSftp) session.openChannel("sftp");
            channelSftp.connect();

            // 上传文件
            try (InputStream inputStream = new FileInputStream("local/file/path")) {
                channelSftp.put(inputStream, SFTPWORKINGDIR + "fileName");
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (channelSftp != null) {
                channelSftp.disconnect();
            }
            if (session != null) {
                session.disconnect();
            }
        }
    }
}

在这个示例中,JSch类用于管理SSH连接和会话,ChannelSftp类用于执行具体的SFTP操作。需要注意的是,在实际开发中,StrictHostKeyChecking属性建议设置为yes以增强安全性。

3.常用函数详解

ChannelSftp类提供了丰富的功能,用于实现SFTP操作。以下是一些常用的SFTP操作函数:

  • 连接与会话管理

    • connect():连接到SFTP服务器。
    • disconnect():断开与SFTP服务器的连接。
    • getSession():获取当前连接的会话(Session)。
  • 文件操作

    • put(InputStream src, String dst):将本地文件上传到SFTP服务器的目标路径。
    • get(String src, OutputStream dst):从SFTP服务器下载文件到本地。
    • rm(String path):删除服务器上的文件。
    • ls(String path):列出指定目录下的文件和子目录。
  • 目录操作

    • cd(String path):切换到指定目录。
    • mkdir(String path):在SFTP服务器上创建新目录。
    • rmdir(String path):删除SFTP服务器上的目录。
  • 权限与属性管理

    • chmod(int permissions, String path):修改文件或目录的权限。
    • chown(int uid, String path):修改文件或目录的所有者。
    • chgrp(int gid, String path):修改文件或目录的所属组。
    • stat(String path):获取文件或目录的属性。
4. 二次封装的工具类

为了更好地管理SFTP连接和操作,实现更强大的功能,如级联创建目录和其他操作,我们可以将常用功能封装到一个工具类中,提高代码的可读性和可维护性的同时,确保可以顺利处理复杂的文件系统操作。比如级联创建目录,在级联创建目录时,我们需要逐级检查每个目录是否存在,如果不存在则创建它。这在FTP和SFTP操作中都非常常见。

FTP工具类的级联创建目录封装
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class FTPUtil {
    private FTPClient ftpClient;

    public FTPUtil(String host, int port, String username, String password) throws IOException {
        ftpClient = new FTPClient();
        ftpClient.connect(host, port);
        ftpClient.login(username, password);
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    }

    // 上传文件
    public boolean uploadFile(String remoteFilePath, InputStream inputStream) throws IOException {
        try {
            return ftpClient.storeFile(remoteFilePath, inputStream);
        } finally {
            inputStream.close();
        }
    }

    // 下载文件
    public boolean downloadFile(String remoteFilePath, OutputStream outputStream) throws IOException {
        try {
            return ftpClient.retrieveFile(remoteFilePath, outputStream);
        } finally {
            outputStream.close();
        }
    }

    // 删除文件
    public boolean deleteFile(String filePath) throws IOException {
        return ftpClient.deleteFile(filePath);
    }

    // 级联创建目录
    public boolean createDirectories(String remoteDirPath) throws IOException {
        String[] directories = remoteDirPath.split("/");
        String currentDir = "";
        boolean dirExists = false;

        for (String dir : directories) {
            if (dir.isEmpty()) continue;
            currentDir += "/" + dir;
            dirExists = ftpClient.changeWorkingDirectory(currentDir);
            if (!dirExists) {
                if (!ftpClient.makeDirectory(currentDir)) {
                    throw new IOException("Failed to create directory: " + currentDir);
                }
                ftpClient.changeWorkingDirectory(currentDir);
            }
        }
        return true;
    }

    // 删除目录(仅删除空目录)
    public boolean deleteDirectory(String directoryPath) throws IOException {
        return ftpClient.removeDirectory(directoryPath);
    }

    // 递归删除目录(包括子文件和子目录)
    public boolean deleteDirectoryRecursively(String remoteDirPath) throws IOException {
        FTPFile[] files = ftpClient.listFiles(remoteDirPath);
        for (FTPFile file : files) {
            String filePath = remoteDirPath + "/" + file.getName();
            if (file.isDirectory()) {
                deleteDirectoryRecursively(filePath);
            } else {
                deleteFile(filePath);
            }
        }
        return deleteDirectory(remoteDirPath);
    }

    // 退出并断开连接
    public void logoutAndDisconnect() throws IOException {
        if (ftpClient.isConnected()) {
            ftpClient.logout();
            ftpClient.disconnect();
        }
    }
}
SFTP工具类的级联创建目录封装
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.Vector;

public class SFTPUtil {
    private ChannelSftp channelSftp;
    private Session session;

    public SFTPUtil(String host, int port, String username, String password) throws Exception {
        JSch jsch = new JSch();
        session = jsch.getSession(username, host, port);
        session.setPassword(password);

        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        session.connect();

        channelSftp = (ChannelSftp) session.openChannel("sftp");
        channelSftp.connect();
    }

    // 上传文件
    public void uploadFile(String remoteDir, String remoteFileName, InputStream inputStream) throws Exception {
        channelSftp.cd(remoteDir);
        channelSftp.put(inputStream, remoteFileName);
    }

    // 下载文件
    public void downloadFile(String remoteFilePath, OutputStream outputStream) throws Exception {
        channelSftp.get(remoteFilePath, outputStream);
    }

    // 删除文件
    public void deleteFile(String remoteFilePath) throws Exception {
        channelSftp.rm(remoteFilePath);
    }

    // 级联创建目录
    public void createDirectories(String remoteDirPath) throws Exception {
        String[] directories = remoteDirPath.split("/");
        String currentDir = "";
        for (String dir : directories) {
            if (dir.isEmpty()) continue;
            currentDir += "/" + dir;
            try {
                channelSftp.cd(currentDir);
            } catch (Exception e) {
                channelSftp.mkdir(currentDir);
                channelSftp.cd(currentDir);
            }
        }
    }

    // 删除目录(仅删除空目录)
    public void deleteDirectory(String remoteDir) throws Exception {
        channelSftp.rmdir(remoteDir);
    }

    // 递归删除目录(包括子文件和子目录)
    public void deleteDirectoryRecursively(String remoteDirPath) throws Exception {
        Vector<ChannelSftp.LsEntry> files = channelSftp.ls(remoteDirPath);
        for (ChannelSftp.LsEntry entry : files) {
            if (!entry.getFilename().equals(".") && !entry.getFilename().equals("..")) {
                String filePath = remoteDirPath + "/" + entry.getFilename();
                if (entry.getAttrs().isDir()) {
                    deleteDirectoryRecursively(filePath);
                } else {
                    deleteFile(filePath);
                }
            }
        }
        deleteDirectory(remoteDirPath);
    }

    // 退出并断开连接
    public void logoutAndDisconnect() {
        if (channelSftp != null) {
            channelSftp.disconnect();
        }
        if (session != null) {
            session.disconnect();
        }
    }
}
使用注意事项
  • 级联目录创建:在处理复杂路径时,必须确保各级目录按顺序被创建。如果操作失败,应当立即停止并报告错误。
  • 递归删除:在删除目录时,递归删除可以确保目录及其所有内容都被彻底删除。然而,必须注意,这是一项危险操作,可能会导致数据丢失,因此在执行之前应该进行仔细确认。
  • 异常处理:在目录操作过程中,由于路径错误、权限不足或网络问题可能导致异常,应确保这些异常被捕获并妥善处理,以避免影响系统的稳定性。
三、Java连接FTP与SFTP的对比

FTP和SFTP在实际项目中各有应用场景。FTP由于其简单性和广泛支持,适用于一些对安全性要求不高的场景;而SFTP由于具备更高的安全性和数据加密特性,更适合用于涉及敏感数据的场景。

1. 安全性

SFTP在安全性方面具有明显的优势。它通过SSH协议加密数据传输,避免了数据在传输过程中的被窃听和篡改风险。相比之下,FTP采用明文传输,容易受到中间人攻击。

2. 性能

FTP通常在速度上略优于SFTP,因为它省去了加密和解密过程。不过,在现代硬件环境下,这种性能差异通常可以忽略不计。

3. 支持与兼容性

FTP在许多系统中得到了广泛的支持,几乎所有的操作系统和许多文件管理工具都支持FTP。而SFTP的支持相对较少,但在涉及安全要求的项目中,SFTP是更合适的选择。

四、总结与个人看法

通过本文,我们深入探讨了如何在Java中实现FTP和SFTP连接,并详细介绍了相关的函数用法和二次封装工具类的实现。对于两者的应用场景和差异,我们也进行了对比分析。

个人看法:在选择FTP还是SFTP时,应该根据项目的具体需求进行权衡。如果安全性是重中之重,SFTP无疑是首选。此外,随着互联网安全要求的日益提高,FTP的应用场景可能会逐渐减少。因此,在新项目中,建议优先考虑SFTP作为文件传输的解决方案。当然,在某些内网环境或临时性项目中,FTP的简单性和较低的配置成本也使其成为一个不错的选择。在处理文件传输任务时,封装常用的操作功能,不仅可以提高代码的复用性,还能减少开发过程中的重复劳动,提升项目的开发效率。对于级联操作和递归操作,虽然实现起来相对复杂,但这些功能对于许多实际场景是必不可少的,因此在开发中应当积极采用这些封装技术,确保系统的健壮性和灵活性。

希望这篇随笔能够帮助你更好地理解和掌握Java中FTP和SFTP的实现方法,并为实际项目提供一些有价值的参考。如果你在开发过程中有任何问题或需要进一步探讨,欢迎随时交流。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式 之 —— 组合模式

目录 什么是组合模式&#xff1f; 定义 特点 结构 组合模式&#xff08;java代码示例&#xff09; 首先定义接口 定义叶节点&#xff08;Leaf类&#xff09; 定义容器节点&#xff08;Composite类&#xff09; 测试类&#xff1a; 树形图 运行结果&#xff1a; 组…

CUDA Programming - (1) CUDA简介

1. GPU 简介 处理器一般包含以下几部分&#xff1a;Cache 缓存&#xff0c;ALU 计算单元&#xff0c;Control 控制中心&#xff0c;RAM 内存。 CPU&#xff08;Central Processing Unit&#xff09;&#xff1a;中央处理器。适合进行逻辑&#xff0c;ALU计算核心较少。适合控…

乒乓球桌上的AI新星:谷歌机器人Agent,是竞技的未来,还是科技的幻想?

在巴黎奥运会乒乓球的激烈角逐中&#xff0c;一个不同寻常的选手悄然登场——谷歌的乒乓球机器人Agent。 这是首个在竞技水平上达到人类标准的AI机器人。 01 AI机器人颠覆初级玩家 Agent不仅能够在正反手之间自如转换&#xff0c;连续进攻&#xff0c;甚至在面对诸如长球、高…

【Qt】QWidegt的enable属性

enabled&#xff1a;描述了一个控件是否处于“可用”状态&#xff08;相对的概念“禁用”&#xff09;。 API说明 isEnabled() 获取到控件的可⽤状态 setEnabled 设置控件是否可使⽤. true 表⽰可⽤, false 表⽰禁⽤ 所谓“禁用”指的是该控件不能接收任何用户的输入事件…

localStorage用法

一、localStorage API使用 注意&#xff0c;localStorage 只能存储字符串。 1.1 存储数据 例如&#xff0c;对象存储时&#xff0c;可以使用JSON.stringify 转成字符串&#xff1b; // 假设你有一个对象 const myObject {name: Alice,age: 25, };// 使用 JSON.stringify 将…

解决windows7虚拟机安装不了vmtools问题

安装不了vmtools问题所在&#xff1a; 没打补丁 ​ 打补丁问题 补丁在本地下载之后无法传到win7虚拟机中 补丁获取 补丁链接如下&#xff1a; https://catalog.s.download.windowsupdate.com/c/msdownload/update/software/secu/2019/09/windows6.1-kb4474419-v3-x64_b5614c6…

脱胎于 S 语言的R语言,Ross Ihaka 和 Robert Gentleman 和社区的力量让 R 在学术界与研究机构放光彩

R语言从一门用于统计学教学的编程语言&#xff0c;发展成为全球数据科学领域的重要工具&#xff0c;离不开其强大的功能、丰富的社区资源和开源精神。这些都离不开Ross Ihaka 和 Robert Gentleman 和 社区的力量。 在1990年代初&#xff0c;新西兰奥克兰大学的统计学教授Ross I…

图解Kafka | 彻底弄明白 Kafka 两个最重要的配置

我已经使用 Kafka 近两年了&#xff0c;我发现有两个配置很重要&#xff0c;但是不太容易理解。这两个配置分别是acks和min.insync.replicas。 本文将通过一些插图来帮助理解这2个配置&#xff0c;以便更好的使用Kafka为我们服务。 复制 我假设你已经熟悉 Kafka了 &#xff…

【TabBar嵌套Navigation案例-按钮交换图片和文字的位置-分类 Objective-C语言】

一、接下来,我们接着来说这个Button的问题, 1.首先,我要做的事情,就是让它们两个去交换位置, 那么这个时候,我要去自定义一个东西, 然后,我现在要来到发现这个页面的View里边,我要去自定义一个Button, New一个File, 来一个Cocoa Touch Class, 然后,继承的是UIB…

8.13网络编程

笔记 多点通信 一、套接字属性 套接字属性的获取和设置 #include <sys/types.h> /* See NOTES */#include <sys/socket.h>int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level…

HarmonyOS.FA开发流程

开发环境配置 1、DevEco Studio的安装 2、DevEcoStudio模拟运行工程&#xff1a;运行Tools->Device Manager&#xff0c;使用已认证的HW开发者联盟帐号Login&#xff08;在DP平台申请测试者权限&#xff09;&#xff0c;点击"允许"授权&#xff0c;选择一个设备运…

【开端】通用数据库连接DatabaseManager支持可配置

一、绪论 Java开发中除了使用spring框架进行数据库连接&#xff0c;又是后也需要手写数据库连接&#xff0c;那么这里提供一种通用数据库连接方式&#xff0c;支持配置mysql orale DM &#xff0c;pg等。 二、DatabaseManager package cn.ctg.codegen.database; import java.…

代理用上了,docker都不能用的解决方案

https://docs.docker.com/engine/daemon/proxy/https://docs.docker.com/engine/daemon/proxy/ 1、 sudo mkdir -p /etc/systemd/system/docker.service.d 2、/etc/systemd/system/docker.service.d/http-proxy.conf [Service] Environment="HTTP_PROXY=http://127.0.…

vue3 路由带传参跳转;刷新后消失。一次性参数使用。

解决vue3 怎么做到路由跳转传参刷新后消失 解决路由跳转传参去除问题 想要跳转后根据参数显示对应的tab&#xff0c;但url传参刷新会持续保留无法重置。 router.replace替换又会导致显示内容为router.replace后的&#xff0c;传参目的丢失。 业务逻辑&#xff1a; 完成对应操作…

基于LPF改进的反电势观测器+锁相环PLL的永磁无感控制

导读:上期文章介绍的基于EMF+PLL的中高速永磁无感控制,其中决定转速和位置的估算精度的是反电势的获取精度。直接计算法很难保证反电势的估算精度,所以本期文章介绍一种基于LPF的改进型EMF观测器。 一、基于LPF改进的EMF观测器 传统的EMF观测器的表达式为: 注:这里重点强…

怎么用dos编译python

无论windos还是Linux只要安装了python&#xff0c;配置好了环境变量&#xff0c;则在命令行输入python这个命令的时候就会进入交互模式。在这个模式下可以进行一些简单的python代码编写。退出可以使用exit()方法。 Python程序是可以执行的&#xff0c;例如下面代码&#xff0c…

【LeetCode Cookbook(C++ 描述)】一刷二叉树之层序遍历(BFS)

目录 LeetCode #102&#xff1a;Binary Tree Lever Order Traversal 二叉树的层序遍历递归解法迭代解法 LeetCode #107&#xff1a;Binary Tree Level Order Traversal II - 二叉树的层序遍历 II递归解法迭代解法 LeetCode #429&#xff1a;N-ary Tree Level Order Traversal -…

8月13日

思维导图 作业 TCP机械臂测试 通过w(红色臂角度增大)s(红色臂角度减小)d(蓝色臂角度增大)a(蓝色臂角度减小)按键控制机械臂 代码 #include<myhead.h>#define SER_PORT 8888 #define SER_IP "192.168.0.108" #define CLI_PORT 6666 #define CLI_IP "192.…

Unity数据持久化 之 LitJson序列化与反序列化

语法规则可以看这篇文章&#xff1a;Unity数据持久化 之 Json 语法速通-CSDN博客 1.LitJson是什么 LitJSON - Home&#xff0c;Release LitJSON 0.19.0 LitJSON/litjson GitHub LitJSON是一个net库&#xff0c;用于处理与JSON (JavaScript Object Notation)字符串之间的转换…

【RTOS面试题】临时屏蔽/禁用中断的方法有什么用?什么时候用?做这种方法时应该注意什么?

目录 一、临时屏蔽中断的用途二、使用场景三 、 注意事项四、 示例代码五、结论 临时屏蔽/禁用中断的方法在嵌入式系统开发中非常重要&#xff0c;尤其在处理中断密集型的任务时。下面将详细介绍这种方法的用途、应用场景以及注意事项。 一、临时屏蔽中断的用途 保护关键代码段…