C++项目——云备份-③-实用工具类设计与实现

news2024/10/6 10:27:44

文章目录

  • 专栏导读
  • 1.文件实用工具类的设计
  • 2.文件实用工具类的实现
    • 2.1前置知识补充
      • 2.1.1struct stat 与 stat介绍
      • 2.1.2std::experimental::filesystem认识
    • 2.2FileUtil实现
  • 3.JSON实用工具类的设计
  • 4.JSON实用工具类的实现
  • 5.实用工具类整理

专栏导读

🌸作者简介:花想云 ,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人…致力于 C/C++、Linux 学习。

🌸专栏简介:本文收录于 C++项目——云备份

🌸相关专栏推荐:C语言初阶系列C语言进阶系列C++系列数据结构与算法Linux
🌸项目Gitee链接:https://gitee.com/li-yuanjiu/cloud-backup

在这里插入图片描述

1.文件实用工具类的设计

不管是客户端还是服务端,文件的传输备份都涉及到文件的读写,包括数据管理信息的持久化也是如此,因此首先设计封装文件操作类,这个类封装完毕之后,则在任意模块中对文件进行操作时都将变的简单化。

文件实用工具类FileUtil主要包含以下成员:

class FileUtil
{
public:
    FileUtil(const std::string &filename) :_filename(filename);
    int64_t FileSize(); // 获取文件大小
    time_t LastMtime(); // 获取文件最后一次修改时间
    time_t LastATime(); // 获取文件最后一次访问时间
    std::string FileName(); // 获取文件路径中的纯文件名称 a/b/c/test.cc --> test.cc
    bool GetPosLen(std::string *body, size_t pos, size_t len); // 获取文件指定区间的数据
    bool GetContent(std::string *body); // 获取文件内容
    bool SetContent(const std::string &body); // 向文件写入数据
    bool Compress(const std::string &packname); // 压缩文件
    bool UnCompress(const std::string &filename); // 解压缩文件
    bool Exists(); // 判断文件是否存在
    bool Remove(); // 删除文件
    bool CreateDirectory(); // 创建文件目录
    bool ScanDirectory(std::vector<std::string> *array); // 浏览指定目录下的所有文件
private:
    std::string _filename; // 文件名--包含路径
};
  • _filename:文件名称(包含路径),例如 a/b/c/test.cc
  • FileUtil:构造函数;
  • FileSize:获取文件大小;
  • LastMtime:获取文件最后一次修改时间;
  • LastATime:获取文件最后一次访问时间;
  • FileName:获取文件路径中的纯文件名称 a/b/c/test.cc --> test.cc
  • GetPosLen:获取文件指定区间的数据;
  • GetContent:获取文件内容;
  • SetContent:向文件写入数据;
  • Compress:压缩文件;
  • UnCompress:解压缩文件;
  • Exists:判断文件是否存在;
  • Remove:删除文件;
  • CreateDirectory:创建文件目录;
  • ScanDirectory:浏览指定目录下的所有文件;

2.文件实用工具类的实现

2.1前置知识补充

FileUtil的实现中,我们使用了较多相对不常见库函数,在此先做复习。

2.1.1struct stat 与 stat介绍

认识stat函数之前我们首先认识一下struct stat类型。

在C语言中,struct stat是一个用于表示文件或文件系统对象属性的结构体类型。这个结构体通常用于与文件和目录相关的操作,例如获取文件的大小、访问权限、最后修改时间等信息。struct stat类型的定义通常由操作系统提供,因此其具体字段可能会因操作系统而异。

以下是一个典型的struct stat结构体的字段,尽管具体字段可能会因操作系统而异:

struct stat {
    dev_t     st_dev;         // 文件所在设备的ID
    ino_t     st_ino;         // 文件的inode号
    mode_t    st_mode;        // 文件的访问权限和类型
    nlink_t   st_nlink;       // 文件的硬链接数量
    uid_t     st_uid;         // 文件的所有者的用户ID
    gid_t     st_gid;         // 文件的所有者的组ID
    off_t     st_size;        // 文件的大小(以字节为单位)
    time_t    st_atime;       // 文件的最后访问时间
    time_t    st_mtime;       // 文件的最后修改时间
    time_t    st_ctime;       // 文件的最后状态改变时间
    blksize_t st_blksize;     // 文件系统I/O操作的最佳块大小
    blkcnt_t  st_blocks;      // 文件占用的块数
};

struct stat结构体中的这些字段提供了关于文件或目录的各种信息。不同的操作系统可能会提供额外的字段,或者字段的意义可能会有所不同。

stat函数用于获取与指定路径名相关联的文件或目录的属性,并将这些属性填充到一个struct stat结构体中。以下是stat函数的函数原型:

int stat(const char *pathname, struct stat *statbuf);
  • pathname是要获取属性的文件或目录的路径名;
  • statbuf是一个指向struct stat结构体的指针,用于存储获取到的属性信息;
  • stat函数返回一个整数值,如果操作成功,返回0;如果出现错误,返回-1,并设置errno全局变量以指示错误的类型。

注意需要包含头文件<sys/stat.h><unistd.h>来使用stat函数。

2.1.2std::experimental::filesystem认识

std::experimental::filesystem 库是 C++ 标准库的一部分,最早出现在 C++17 中,并被视为实验性的文件系统库。它提供了一组类和函数,用于处理文件系统操作,如文件和目录的创建、访问、遍历、复制、删除等。这个库的目的是使文件系统操作更加便捷,同时具有跨平台性,因此你可以在不同操作系统上执行相同的文件操作,而不需要考虑底层细节。

以下是一些 std::experimental::filesystem 库的主要特性和功能:

  • std::experimental::filesystem::path 类:用于表示文件路径。它可以自动处理不同操作系统的路径分隔符,使得代码更具可移植性。

  • 文件和目录操作:这个库提供了许多函数来执行常见的文件和目录操作,包括文件创建、复制、移动、删除,以及目录的创建、删除、遍历等。

  • 文件属性查询:你可以使用这个库来查询文件和目录的属性,如文件大小、修改时间等。

  • 异常处理std::experimental::filesystem 库定义了一些异常类,以处理与文件系统操作相关的错误,如文件不存在或无法访问等问题。

  • 迭代器:你可以使用迭代器来遍历目录中的文件和子目录,这是一个非常方便的功能,用于递归遍历文件系统。

需要注意的是,尽管 std::experimental::filesystem 在 C++17 中引入,但它是一个实验性的特性,并且不一定在所有编译器和平台上都得到完全支持。因此,一些编译器可能需要特定的编译选项或配置才能使用这个库。

从 C++17 开始,文件系统库已正式成为 C++ 标准的一部分,并迁移到 std::filesystem 命名空间中,而不再是实验性的特性。因此,在新的 C++标准中,建议使用 std::filesystem 库来执行文件系统操作。

2.2FileUtil实现

namespace fs = std::experimental::filesystem;
class FileUtil
{
public:
    FileUtil(const std::string &filename) :_filename(filename)
    {}
    int64_t FileSize()
    {
        struct stat st;
        if(stat(_filename.c_str(), &st) < 0)
        {
            std::cout << "get file size failed!" << std::endl;
            return -1;
        }
        return st.st_size;
    }
    time_t LastMtime()
    {
        struct stat st;
        if(stat(_filename.c_str(), &st) < 0)
        {
            std::cout << "get last modify time failed!" << std::endl;
            return -1;
        }
        return st.st_mtime;
    }
    time_t LastATime()
    {
        struct stat st;
        if(stat(_filename.c_str(), &st) < 0)
        {
            std::cout << "get last access time failed!" << std::endl;
            return -1;
        }
        return st.st_atime;  
    }
    std::string FileName()
    {
        size_t pos = _filename.find_last_of("/");
        if(pos == std::string::npos)
        {
            return _filename;
        }
        return _filename.substr(pos+1);
    }
    bool GetPosLen(std::string *body, size_t pos, size_t len)
    {
        size_t fsize = FileSize();
        if(pos + len > fsize)
        {
            std::cout << "GetPosLen: get file len error" << std::endl;
            return false;
        }
        std::ifstream ifs;
        ifs.open(_filename, std::ios::binary);
        if(ifs.is_open() == false)
        {
            std::cout << "GetPosLen: open file failed!" << std::endl;
            return false;
        }
        ifs.seekg(pos, std::ios::beg); // 将文件指针定位到pos处
        body->resize(len);
        ifs.read(&(*body)[0], len);
        if(ifs.good() == false)
        {
            std::cout << "GetPosLen: get file content failed" << std::endl;
            ifs.close();
            return false;
        }
        ifs.close();
        return true;
    }
    bool GetContent(std::string *body)
    {
        size_t fsize = FileSize();
        return GetPosLen(body, 0, fsize);
    }
    bool SetContent(const std::string &body)
    {
        std::ofstream ofs;
        ofs.open(_filename, std::ios::binary);
        if(ofs.is_open() == false)
        {
            std::cout << "SetContent: write open file failed" << std::endl;
            return false;
        }
        ofs.write(&body[0], body.size());
        if(ofs.good() == false)
        {
            std::cout << "SetContent: write open file failed" << std::endl;
            ofs.close();
            return false;
        }
        ofs.close();
        return true;
    }
    bool Compress(const std::string &packname)
    {
        // 1.获取源文件数据
        std::string body;
        if(GetContent(&body) == false)
        {
            std::cout << "compress get file content failed" << std::endl;
            return false;
        }
        // 2.对数据进行压缩
        std::string packed = bundle::pack(bundle::LZIP, body);
        // 3.将压缩的数据存储到压缩包文件中
        FileUtil fu(packname);
        if(fu.SetContent(packed) == false)
        {
            std::cout << "compress write packed data failed!" << std::endl;
            return false;
        }
        return true;
    }
    bool UnCompress(const std::string &filename)
    {
        // 1.将当前压缩包数据读取出来
        std::string body;
        if(GetContent(&body) == false)
        {
            std::cout << "Uncompress get file content failed!" << std::endl;
            return false;
        }
        // 2.对压缩的数据进行解压缩
        std::string unpacked = bundle::unpack(body);
        // 3.将解压缩的数据写入到新文件中
        FileUtil fu(filename);
        if(fu.SetContent(unpacked) == false)
        {
            std::cout << "Uncompress write packed data failed!" << std::endl;
            return false;
        }
        return true;
    }
    bool Exists()
    {
        return fs::exists(_filename);
    }
    bool Remove()
    {
        if(Exists() == false)
        {
            return true;
        }
        remove(_filename.c_str());
        return true;
    }
    bool CreateDirectory()
    {
        if(Exists()) return true;
        return fs::create_directories(_filename);
    }
    bool ScanDirectory(std::vector<std::string> *array)
    {
        for(auto& p : fs::directory_iterator(_filename)) // 迭代器遍历指定目录下的文件
        {
            if(fs::is_directory(p) == true) continue;
            // relative_path 带有路径的文件名
            array->push_back(fs::path(p).relative_path().string());
        }
        return true;
    }
private:
    std::string _filename;
};

3.JSON实用工具类的设计

Jsoncpp已经为我们你提供了序列化与反序列化接口,但是为了使得实用更加便捷,我们可以自己再封装一个JsonUtil的类。

JsonUtil类中包含以下成员:

class JsonUtil
{
public:
    static bool Serialize(const Json::Value &root, std::string *str); // 序列化操作
    static bool Unserialize(const std::string &str, Json::Value *root); // 反序列化操作
};

由于前面的章节已经介绍过Json的使用,接下来我们直接看函数的实现。

4.JSON实用工具类的实现

class JsonUtil
{
public:
    static bool Serialize(const Json::Value &root, std::string *str)
    {
        Json::StreamWriterBuilder swb;
        std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
        std::stringstream ss;
        if(sw->write(root, &ss) != 0)
        {
            std::cout << "json write failed!" << std::endl;
            return false;
        }
        *str = ss.str();
        return true;
    }
    static bool Unserialize(const std::string &str, Json::Value *root)
    {
        Json::CharReaderBuilder crb;
        std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
        std::string err;
        bool ret = cr->parse(str.c_str(), str.c_str() + str.size(), root, &err);
        if(ret == false)
        {
            std::cout << "parse error" << std::endl;
            return false; 
        }
        return true;
    }
};

5.实用工具类整理

最后,我们将两个实用工具类都放到util.hpp的头文件中。

// util.hpp
#ifndef __MY_UTIL__
#define __MY_UTIL__
/*
    1.获取文件大小
    2.获取文件最后一次修改时间
    3.获取文件最后一次访问时间
    4.获取文件路径名中的文件名称 /abc/test.txt -> test.txt
    5.向文件写入数据
    6.获取文件数据
    7.获取文件指定位置 指定数据长度
    8.判断文件是否存在
    9.创建目录
    10.浏览获取目录下的所有文件路径名
    11.压缩文件
    12.解压缩所有文件
    13.删除文件
*/
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sys/stat.h>
#include <experimental/filesystem>
#include <jsoncpp/json/json.h>
#include "bundle.h"

namespace cloud
{
    namespace fs = std::experimental::filesystem;
    class FileUtil
    {
    public:
        FileUtil(const std::string &filename) :_filename(filename)
        {}
        int64_t FileSize()
        {
            struct stat st;
            if(stat(_filename.c_str(), &st) < 0)
            {
                std::cout << "get file size failed!" << std::endl;
                return -1;
            }
            return st.st_size;
        }
        time_t LastMtime()
        {
            struct stat st;
            if(stat(_filename.c_str(), &st) < 0)
            {
                std::cout << "get last modify time failed!" << std::endl;
                return -1;
            }
            return st.st_mtime;
        }
        time_t LastATime()
        {
            struct stat st;
            if(stat(_filename.c_str(), &st) < 0)
            {
                std::cout << "get last access time failed!" << std::endl;
                return -1;
            }
            return st.st_atime;  
        }
        std::string FileName()
        {
            size_t pos = _filename.find_last_of("/");
            if(pos == std::string::npos)
            {
                return _filename;
            }
            return _filename.substr(pos+1);
        }
        bool GetPosLen(std::string *body, size_t pos, size_t len)
        {
            size_t fsize = FileSize();
            if(pos + len > fsize)
            {
                std::cout << "GetPosLen: get file len error" << std::endl;
                return false;
            }
            std::ifstream ifs;
            ifs.open(_filename, std::ios::binary);
            if(ifs.is_open() == false)
            {
                std::cout << "GetPosLen: open file failed!" << std::endl;
                return false;
            }
            ifs.seekg(pos, std::ios::beg); // 将文件指针定位到pos处
            body->resize(len);
            ifs.read(&(*body)[0], len);
            if(ifs.good() == false)
            {
                std::cout << "GetPosLen: get file content failed" << std::endl;
                ifs.close();
                return false;
            }
            ifs.close();
            return true;
        }
        bool GetContent(std::string *body)
        {
            size_t fsize = FileSize();
            return GetPosLen(body, 0, fsize);
        }
        bool SetContent(const std::string &body)
        {
            std::ofstream ofs;
            ofs.open(_filename, std::ios::binary);
            if(ofs.is_open() == false)
            {
                std::cout << "SetContent: write open file failed" << std::endl;
                return false;
            }
            ofs.write(&body[0], body.size());
            if(ofs.good() == false)
            {
                std::cout << "SetContent: write open file failed" << std::endl;
                ofs.close();
                return false;
            }
            ofs.close();
            return true;
        }
        bool Compress(const std::string &packname)
        {
            // 1.获取源文件数据
            std::string body;
            if(GetContent(&body) == false)
            {
                std::cout << "compress get file content failed" << std::endl;
                return false;
            }
            // 2.对数据进行压缩
            std::string packed = bundle::pack(bundle::LZIP, body);
            // 3.将压缩的数据存储到压缩包文件中
            FileUtil fu(packname);
            if(fu.SetContent(packed) == false)
            {
                std::cout << "compress write packed data failed!" << std::endl;
                return false;
            }
            return true;
        }
        bool UnCompress(const std::string &filename)
        {
            // 1.将当前压缩包数据读取出来
            std::string body;
            if(GetContent(&body) == false)
            {
                std::cout << "Uncompress get file content failed!" << std::endl;
                return false;
            }
            // 2.对压缩的数据进行解压缩
            std::string unpacked = bundle::unpack(body);
            // 3.将解压缩的数据写入到新文件中
            FileUtil fu(filename);
            if(fu.SetContent(unpacked) == false)
            {
                std::cout << "Uncompress write packed data failed!" << std::endl;
                return false;
            }
            return true;
        }
        bool Exists()
        {
            return fs::exists(_filename);
        }
        bool Remove()
        {
            if(Exists() == false)
            {
                return true;
            }
            remove(_filename.c_str());
            return true;
        }
        bool CreateDirectory()
        {
            if(Exists()) return true;
            return fs::create_directories(_filename);
        }
        bool ScanDirectory(std::vector<std::string> *array)
        {
            for(auto& p : fs::directory_iterator(_filename)) // 迭代器遍历指定目录下的文件
            {
                if(fs::is_directory(p) == true) continue;
                // relative_path 带有路径的文件名
                array->push_back(fs::path(p).relative_path().string());
            }
            return true;
        }
    private:
        std::string _filename;
    };
    class JsonUtil
    {
    public:
        static bool Serialize(const Json::Value &root, std::string *str)
        {
            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            std::stringstream ss;
            if(sw->write(root, &ss) != 0)
            {
                std::cout << "json write failed!" << std::endl;
                return false;
            }
            *str = ss.str();
            return true;
        }
        static bool Unserialize(const std::string &str, Json::Value *root)
        {
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            std::string err;
            bool ret = cr->parse(str.c_str(), str.c_str() + str.size(), root, &err);
            if(ret == false)
            {
                std::cout << "parse error" << std::endl;
                return false; 
            }
            return true;
        }
    };
}
#endif

在这里插入图片描述

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

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

相关文章

ESP32智能小车+PS2无线遥控器+麦克纳姆轮+microPython

from machine import Pin,PWM from ps2 import PS2Controller import time import os# ############################################# # PS2 遥控器 # ############################################# ps2ctl PS2Controller(di_pin_no26, do_pin_no27, cs_pin_no14, clk_pin…

Unity中Shader的模型网格阴影

文章目录 前言一、网格阴影原理1、在世界空间下&#xff0c;把角色模型在Y轴上压缩成一个面片&#xff0c;把颜色修改成像影子的颜色2、把压缩后的面片&#xff0c;移动到合适的位置&#xff0c;把模型和阴影面片错开3、实现距离脚近的阴影偏移少&#xff0c;距离脚远的阴影偏移…

【已解决】AttributeError: module ‘cv2‘ has no attribute ‘bgsegm‘

问题 使用cv2.bgsegm.createBackgroundSubtractorMOG()去除背景的时候&#xff0c;遇到如下问题&#xff1a; AttributeError: module cv2 has no attribute bgsegm原因 报错原因&#xff1a;使用的python环境中没有安装扩展包contrib 解决方法 可以通过pip或者conda安装 …

QT中文乱码解决方案与乱码的原因

相信大家应该都遇到过中文乱码的问题&#xff0c;有时候改一改中文就不乱码了&#xff0c;但是有时候用同样的方式还是乱码&#xff0c;那么这个乱码到底是什么原因&#xff0c;又该如何彻底解决呢&#xff1f; 总结 先总结一下&#xff1a; Qt5中&#xff0c;将QString()的构…

Java实现Csv文件导入导出

Java实现Csv文件导入导出 什么是.csv文件&#xff1f; CSV&#xff08;Comma-Separated Values&#xff0c;逗号分隔的值&#xff09;是一种简单、实用的文件格式&#xff0c;用于存储和表示包括文本、数值等各种类型的数据。CSV 文件通常以 .csv 作为文件扩展名。这种文件格…

基于蜣螂优化算法DBO优化的VMD-KELM光伏发电短期功率预测MATLAB代码

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; VMD适用于处理非线性和非平稳信号&#xff0c;例如振动信号、生物信号、地震信号、图像信号等。它在信号处理、振动分析、图像处理等领域有广泛的应用&#xff0c;特别是在提取信号中的隐含信息和去除噪声方面…

字符串中的strcpy和strncpy区别

strcpy:函数原型是char *strcpy(char* dest, const char *src)&#xff0c;含义是将src中的字符串复制到dest中。 strncpy:函数原型是char *strncpy(char *dest const char *src,int n&#xff09;&#xff0c;表示把src所指向的字符串中以src地址开始的前n个字节复制到dest所…

香港施政报告人才引进政策2023全面解读,对优才计划申请是否有影响?

香港施政报告人才引进政策2023全面解读&#xff0c;对优才计划申请是否有影响&#xff1f; 香港第二份施政报告10月25日出来了&#xff01;这次真的是“走进民生”啊&#xff0c;什么路都帮你想好了&#xff01; 总结就是&#xff1a;继续抢人才、留人才&#xff01;在昨天的《…

103.linux5.15.198 编译 firefly-rk3399(2)

1. 平台&#xff1a; rk3399 firefly 2g16g 2. 内核&#xff1a;linux5.15.136 &#xff08;从内核镜像网站下载&#xff09; 3. 交叉编译工具 gcc version 7.5.0 (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 4. 宿主机&#xff1a;ubuntu18.04 5. 需要的素材和资料&#xff…

MySQL 单表查询 多表设计

目录 数据库操作-DQL(单表查询)语法基本查询&#xff08;不带任何条件&#xff09;条件查询&#xff08;where&#xff09;聚合函数分组查询&#xff08;group by [having]&#xff09;&#xff08;重点&#xff09;排序查询&#xff08;order by&#xff09;&#xff08;重点&…

MySQL数据库基本操作2

文章目录 主要内容一.DQL1.语法格式代码如下&#xff08;示例&#xff09;: 2.数据准备代码如下&#xff08;示例&#xff09;: 3.简单查询代码如下&#xff08;示例&#xff09;: 4.运算符5.运算符操作-算术运算符代码如下&#xff08;示例&#xff09;: 6.运算符操作-条件查询…

Spring Cloud Sentinel整合Nacos实现配置持久化

sentinel配置相关配置后无法持久化&#xff0c;服务重启之后就没了&#xff0c;所以整合nacos&#xff0c;在nacos服务持久化&#xff0c;sentinel实时与nacos通信获取相关配置。 使用上一章节Feign消费者服务实现整合。 版本信息&#xff1a; nacos:1.4.1 Sentinel 控制台 …

【DRAM存储器十七】DDR2介绍-DDR2的新增技术-Post CAS、ODT、RDQS、OCD

&#x1f449;个人主页&#xff1a;highman110 &#x1f449;作者简介&#xff1a;一名硬件工程师&#xff0c;持续学习&#xff0c;不断记录&#xff0c;保持思考&#xff0c;输出干货内容 参考资料&#xff1a;《镁光DDR数据手册》 目录 Post CAS ODT RDQS OCD Post CA…

方舟生存进化ARK个人服务器搭建教程保姆级

方舟生存进化ARK个人服务器搭建教程保姆级 大家好我是艾西&#xff0c;在很久之前我有给大家分享过方舟生存进化的搭建架设教程&#xff0c;但时间久远且以前的教程我现在回头看去在某些地方说的并不是那么清楚。最近也是闲暇无事打算重新巩固下方舟生存进化的搭建架设教程&…

[计算机提升] Windows文件系统类型介绍

1.13 文件系统 在Windows系统中&#xff0c;文件系统是一种用于组织和管理计算机上存储的文件和目录的方法。它提供了一种结构化的方式来访问、存储和检索数据。 以下是Windows系统中常见的文件系统&#xff1a; FAT&#xff08;FAT16、FAT32&#xff09;&#xff1a;FAT&…

2023年中国研磨液需求量、市场规模及行业竞争格局分析[图]

研磨是半导体加工过程中的一项重要工艺&#xff0c;它主要是应用化学研磨液混配磨料的方式对半导体表面进行精密加工&#xff0c;研磨液是平坦化工艺中研磨材料和化学添加剂的混合物&#xff0c;研磨材料主要是石英、二氧化铝和氧化铈&#xff0c;研磨液是影响半导体表面质量的…

endnote设置

问题1&#xff1a;参考文献的tab太长 首先要在endnote里面这样设置&#xff0c;file->output->edit "XXX" 保存之后&#xff0c;在word更新目录。 在word里面设置悬挂缩进 结果&#xff1a; Endnote参考编号与参考文献距离太远怎么调整 endnote 文献对齐方式…

LibTorch实战一:MNIST的python代码

目录 一、下载MNIST-demo的cpp、python版本代码 二、五分钟读懂pytorch代码 三、下载MNIST数据集、训练模型 四、模型序列化、可视化分析 本文借用mnist这个相对简易深度学习任务来开始讲解libtorch如何部署模型。因此&#xff0c;这是一个如何编写libtorch代码的实战教程。…

Linux权限大揭秘:深入理解系统安全

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; &#x1f354;前言&#xff1a; 在之前的内容中&#xff0c;我们了解了Linux中的一些简单权限&#xff0c;如root超级账号与普通账户的区别、Linux文件权限管理、文件类型和访问权限以及许多关于修改权限的指令及其规则…

源发行版17 需要目标发行版 17问题解决

java: 警告: 源发行版 17 需要目标发行版 17 问题描述&#xff1a;解决办法&#xff1a;总结 问题描述&#xff1a; 解决办法&#xff1a; 1.将 Settings --> Build, Execution, Deployment --> Complier --> Java Complier 配置下的 Project bytecode version: 17 改…