C# 自动备份文件

news2024/10/5 13:41:51

目录

文件目录如下

 APBackUpFiles

app.config

OracleHelper

LocalFileMethods

LogFile

packages.config

ReadFile

如何发布


在工作的时候,遇到了需要定时对服务器的文件进行备份的需求,原因是 AP(服务器)上的空间不够了,导致一直在报警空间不足,本文就工作中使用到的程序进行简单的记录,本功能包含如下几个部分:

  • 路径配置
  • 数据库连接
  • 文件移动
  • 文件删除
  • 文件压缩
  • 记录 log

文件目录如下

下面来一个一个介绍。


 APBackUpFiles

此方法的主要功能为:

  • 文件移动
  • 文件删除
  • 文件压缩
  • 记录 log

代码如下:

using Oracle.DataAccess.Client;
using System;
using System.Configuration;
using System.Data;
using System.IO;
using System.IO.Compression;

namespace APBackUpFilesToDisk
{
    class APBackUpFiles
    {
        static void Main()
        {
            /*
             * 注意将数据库连接改成正式环境
             * 注意上线的时候开启文件删除功能
             * 注意注释控制台输出的语句
             */
            Console.WriteLine("\t现在开始");
            Console.WriteLine("正在执行.");
            Console.WriteLine("正在执行..");
            Console.WriteLine("正在执行...");
            Console.WriteLine("执行期间,请勿对文件夹内部文件 移动 / 复制 / 删除 / 插入!");

            string sDtaes = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
            string sourceFolder = ConfigurationManager.AppSettings["SourcePath"]; // 源文件夹路径
            string backupFolder = ConfigurationManager.AppSettings["BackUpPath"]; // 备份文件夹路径
            string searchPattern = ConfigurationManager.AppSettings["FilenameSuffix"]; // 文件名匹配模式
            // log 文件存储路径,分时间存储
            string filename = ConfigurationManager.AppSettings["LogPath"] + "\\BackUpFiles_" + sDtaes + ".log";
            int iCounts = 0;// 已操作的文件个数

            // 文件操作方法 StreamWriter 数据流写入
            StreamWriter sws = new StreamWriter(filename, true);
            sws.AutoFlush = true;// 强制每行都写入,而不是等待close时候才写入
            // 程序开始标志
            sws.WriteLine("[Put File start : " + sDtaes + " ===============]");

            try
            {
                // 检查源文件夹是否存在
                if (!Directory.Exists(sourceFolder))
                {
                    // 追加写入
                    sws.WriteLine("源文件夹不存在。");
                    sDtaes = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
                    sws.WriteLine("[Put File end : " + sDtaes + " ===============]");
                    sws.WriteLine("===========================================================");
                    sws.Close();
                    return; // 退出程序
                }

                // 检查备份文件夹是否存在,不存在则创建
                if (!Directory.Exists(backupFolder))
                {
                    Directory.CreateDirectory(backupFolder);
                }

                // 查找匹配的文件并备份
                string[] filesToBackup = Directory.GetFiles(sourceFolder, searchPattern);// 默认按照文件名称排序

                foreach (string file in filesToBackup)
                {
                    string sControl = file.Substring(file.LastIndexOf("\\") + 1, 10);// 取文件名称,即 control lot 信息
                    iCounts++;// 只要对文件进行了判断,则计数加一
                    if (bCheckStatus(sControl))
                    {
                        // 构造备份文件路径
                        string backupFilePath = Path.Combine(backupFolder, Path.GetFileName(file));
                        // 备份文件
                        File.Copy(file, backupFilePath, true); // 如果目标文件已存在则覆盖
                        Console.WriteLine("备份文件 {0} 至 {1}", file, backupFilePath);
                        sws.WriteLine("BackUp File Success :【" + file + "】To【" + backupFilePath + "】");

                        // 删除已备份的文件
                        File.Delete(file);
                        Console.WriteLine("删除文件 {0}", file);
                        sws.WriteLine("[Delete File Success : " + file + "]");

                        if (iCounts == 20000) break;
                    }
                    else
                    {
                        Console.WriteLine("不备份文件 {0} ", sControl);
                        sws.WriteLine("不备份文件" + sControl + "");
                    }
                }

                Console.WriteLine("开始压缩文件...");
                sws.WriteLine("开始压缩文件...");
                // 压缩本地文件
                string startPath = ConfigurationManager.AppSettings["StartPath"];// 需要被压缩的文件夹
                string zipPath = ConfigurationManager.AppSettings["ZipPath"] + "\\" + sDtaes + ".zip";// 压缩包存储的路径,并为压缩包命名

                ZipFile.CreateFromDirectory(startPath, zipPath);
                Console.WriteLine("压缩文件成功!");
                sws.WriteLine("压缩文件成功!");

                Console.WriteLine("开始删除文件...");
                sws.WriteLine("开始删除文件...");
                // 删除本地文件,节省空间
                LocalFileMethods dlf = new LocalFileMethods();
                dlf.DeleteLocalTXT(startPath, searchPattern);
                Console.WriteLine("删除文件成功!");
                sws.WriteLine("删除文件成功!");

                sDtaes = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
                sws.WriteLine("[Put File end : " + sDtaes + " ===============]");
                sws.WriteLine("===========================================================");
                sws.WriteLine();
                sws.Close();
                Console.WriteLine("共执行:" + iCounts + "个文件");
            }
            catch (Exception ex)
            {
                Console.WriteLine("[发生异常 : " + ex.Message + "]");
                sws.WriteLine("[发生异常 : " + ex.Message + "]");
            }
        }

        /// <summary>
        /// 传入文件名称,查询是否满足删除条件          
        /// </summary>
        /// <param name="sControl"></param>
        /// <returns></returns>
        public static bool bCheckStatus(string sControl)
        {
            string sSql;
            DataTable dt = new DataTable();

            // sql 语句
            sSql = " select a.XXX from XXX a " +
                "where a.XXX like '" + sControl + "%' and a.XXX <> '" + sControl + "'";

            // sql 赋值 无参数传入 sql
            OracleParameter[] paramATIO = new OracleParameter[] { };

            // 执行sql
            dt = OracleHelper.ExecuteDataTable(sSql, paramATIO);

            // 若有数据,判断所有状态
            if (dt.Rows.Count > 0)
            {
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    if (dt.Rows[i][0].ToString() != "Terminated" && dt.Rows[i][0].ToString() != "Finished")
                    {
                        return false;
                    }
                }

                // sql 语句
                sSql = " select a.XXX from XXX a " +
                    "where a.XXX like '" + sControl + "%' and a.XXX <> '" + sControl + "'";

                // sql 赋值 无参数传入 sql
                paramATIO = new OracleParameter[] { };

                // 执行sql
                dt = OracleHelper.ExecuteDataTable(sSql, paramATIO);

                if (dt.Rows.Count > 0)// 有数据
                {
                    return true;
                }
            }
            else // 若 ASSY 无数据,需要去 FT 查
            {
                return false;
            }
            return false;
        }

    }
}


app.config

这个文件的作用是配置各种参数,包括了各种路径,可以实现在不改变代码的情况下直接修改操作的文件夹,简单的做到了降低耦合,提高代码复用性的作用,需要修改的时候直接改此配置文件即可。

<?xml version="1.0" encoding="utf-8"?>
<!--设定版本号及字符集-->

<configuration>
	<appSettings>
		<add key="Block" value="1"/>

		<!--源文件夹路径,即需要被备份的文件所在的路径-->
		<add key="SourcePath" value="C:\Test"/>

		<!--备份文件夹路径,即需要将源文件备份到哪个文件夹-->
		<add key="BackUpPath" value="D:\BackUpFiles"/>

		<!--需要被压缩的文件夹,即你要把哪个文件夹压缩,一般同备份文件夹路径-->
		<add key="StartPath" value="D:\BackUpFiles"/>

		<!--压缩包存储的路径,并为压缩包命名,即压缩之后的文件放在哪个文件夹-->
		<add key="ZipPath" value="D:\Zips"/>

		<!--log 文件存储路径,分时间存储,即 log 文件的储存路径-->
		<add key="LogPath" value="D:\APBackUpFilesToDisk\Logs"/>

		<!--文件名匹配模式,即你要从源文件夹中筛选哪些后缀的文件-->
		<add key="FilenameSuffix" value="*.LOT"/>

		<add key="ClientSettingsProvider.ServiceUri" value=""/>
	</appSettings>

	<!--默认配置,不用管-->
	<system.web>
		<membership defaultProvider="ClientAuthenticationMembershipProvider">
			<providers>
				<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri=""/>
			</providers>
		</membership>
		<roleManager defaultProvider="ClientRoleProvider" enabled="true">
			<providers>
				<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400"/>
			</providers>
		</roleManager>
	</system.web>
	<startup>
		<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
	</startup>
</configuration>

OracleHelper

此类的作用是连接数据库,在里面配置数据库连接,后面直接调用此方法即可实现简单的数据库操作(CRUD)。

using Oracle.DataAccess.Client;
using System.Data;

namespace APBackUpFilesToDisk
{
    class OracleHelper
    {
        private static string connStr = "User Id=XXX;Password=XXX;" +
                    "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=XX.XX.XX.XX)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=XXXX)))";

        #region 执行SQL语句,返回受影响行数
        public static int ExecuteNonQuery(string sql, params OracleParameter[] parameters)
        {
            using (OracleConnection conn = new OracleConnection(connStr))
            {
                conn.Open();
                using (OracleCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    cmd.Parameters.AddRange(parameters);
                    int i = cmd.ExecuteNonQuery();
                    conn.Close();
                    return i;
                }
            }
        }
        #endregion
        #region 执行SQL语句,返回DataTable;只用来执行查询结果比较少的情况
        public static DataTable ExecuteDataTable(string sql, params OracleParameter[] parameters)
        {
            using (OracleConnection conn = new OracleConnection(connStr))
            {
                conn.Open();
                using (OracleCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    cmd.Parameters.AddRange(parameters);
                    OracleDataAdapter adapter = new OracleDataAdapter(cmd);
                    DataTable datatable = new DataTable();
                    adapter.Fill(datatable);
                    conn.Close();
                    return datatable;
                }
            }
        }
        #endregion
    }
}

LocalFileMethods

本地文件操作的方法。

using System;
using System.IO;

namespace APBackUpFilesToDisk
{
    class LocalFileMethods
    {
        public void DeleteLocalTXT(string startPath,string searchPattern)
        {
            try
            {
                string[] txtList = Directory.GetFiles(startPath, searchPattern);
                // 删除源文件
                foreach (string f in txtList)
                {
                    File.Delete(f);
                }
            }
            catch (DirectoryNotFoundException dirNotFound)
            {
                Console.WriteLine(dirNotFound.Message);
            }

        }
    }
}

LogFile

记录 log 的方法。

using System;
using System.IO;

namespace APBackUpFilesToDisk
{
    class LogFile
    {

        private string ToFileNmae;
        //日志存储路径
        public void Logfile(string path)
        {
            this.ToFileNmae = path;
        }
        /// <summary>        
        /// 创建日志       
        /// </summary>       
        /// <param name="message">日志信息</param>       
        /// <param name="title">日志标题</param>     
        public void Log(string message)
        {
            string path = this.ToFileNmae;
            string filename = path + "\\Log.txt";
            string cont = "";
            FileInfo fileInf = new FileInfo(filename);
            if (File.Exists(filename))//如何文件存在 则在文件后面累加    
            {
                FileStream myFss = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                StreamReader r = new StreamReader(myFss);
                cont = r.ReadToEnd();
                r.Close();
                myFss.Close();
            }
            #region 生成文件日志
            FileStream myFs = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
            StreamWriter n = new StreamWriter(myFs);
            n.WriteLine(cont);

            n.WriteLine(DateTime.Now.ToString() + ":" + message);
            n.Close(); myFs.Close();

            if (fileInf.Length >= 1024 * 1024 * 200)
            {
                string NewName = path + "Log" + time() + ".txt";
                File.Move(filename, NewName);
            }
            #endregion
        }
        /// <summary>       
        /// 系统时间       
        /// </summary>    
        /// <returns></returns>     
        /// 
        public string time()
        {
            string dNow = DateTime.Now.ToString().Trim().Replace("/", "").Replace(":", "");
            string fileName = dNow.ToString();
            return fileName;
        }

    }
}

packages.config

默认配置,不管他。

<?xml version="1.0" encoding="utf-8"?>
<packages>
	<package id="Oracle.DataAccess.x86.4" version="4.112.3" targetFramework="net45" />
</packages>

ReadFile

读取文件的操作,与写 log 等相互配合。

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Text.RegularExpressions;

namespace APBackUpFilesToDisk
{
    class ReadFile
    {
        public static void Movefile(string filename, string type)
        {
            try
            {
                string sDir = ConfigurationManager.AppSettings[type];

                string sCommonPath = ConfigurationManager.AppSettings["Common"];

                string sDirSource = System.IO.Path.GetDirectoryName(filename);

                string[] sDirDetail = Regex.Split(sDirSource, sCommonPath);

                string sDirCus = sDirDetail[1];

                sDir = sDir + @"\" + sDirCus;

                string sFilename = System.IO.Path.GetFileName(filename);

                if (!Directory.Exists(sDir))
                {
                    Directory.CreateDirectory(sDir);

                }
                if (File.Exists(Path.Combine(sDir, sFilename)))
                {
                    File.Move(Path.Combine(sDir, sFilename), Path.Combine(sDir, sFilename + DateTime.Now.ToString().Trim().Replace("/", "").Replace(":", "")));
                }

                File.Move(filename, Path.Combine(sDir, sFilename));

            }
            catch (Exception ex)
            {
                WriteLog("ReaderMappingfile: " + ex.Message.ToString());

            }

        }





        public static void Backupfile(string filename)
        {
            try
            {
                string sDir = System.IO.Path.GetDirectoryName(filename);

                string sFilename = System.IO.Path.GetFileName(filename);

                if (!Directory.Exists(Path.Combine(sDir, "backup")))
                {
                    Directory.CreateDirectory(Path.Combine(sDir, "backup"));

                }
                if (File.Exists(Path.Combine(sDir, "backup\\" + sFilename)))
                {
                    File.Move(Path.Combine(sDir, "backup\\" + sFilename), Path.Combine(sDir, "backup\\" + sFilename + DateTime.Now.ToString().Trim().Replace("/", "").Replace(":", "")));
                }

                File.Move(filename, Path.Combine(sDir, "backup\\" + sFilename));
            }
            catch (Exception ex)
            {
                WriteLog("ReaderMappingfile: " + ex.Message.ToString());

            }


        }

        public Dictionary<string, string> NewOld2D(string filename)
        {
            Dictionary<string, string> DicMapping = new Dictionary<string, string>();
            try
            {
                string sBindetail = File.ReadAllText(filename);
                string[] s2DAll_list = Regex.Split(sBindetail.TrimEnd(), "");

                for (int i = 0; i < s2DAll_list.Length; i++)
                {
                    DicMapping.Add(s2DAll_list[i].Split(',')[0].ToString(), s2DAll_list[i].Split(',')[1].TrimEnd().ToString());
                }


            }

            catch (Exception ex)
            {
                WriteLog("NewOld2D: " + ex.Message.ToString());

            }

            return DicMapping;


        }

        public static void WriteLog(string smessage)
        {

            try
            {
                LogFile log1 = new LogFile();
                string sLogPath = System.AppDomain.CurrentDomain.BaseDirectory.ToString() + "\\LOG";
                if (!Directory.Exists(sLogPath))
                {
                    Directory.CreateDirectory(sLogPath);
                }

                log1.Logfile(sLogPath);
                log1.Log(smessage);
            }
            catch (Exception ex)
            {
            }

        }
    }
}

如何发布

将代码路径下的这四个文件复制到需要执行的 AP 上面即可。

直接双击 .exe 文件即可执行,如何设定任务计划程序参考此文:设定任务计划程序 

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

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

相关文章

遗传算法解决TSP旅行商问题(numpy、pandas)

努力是为了不平庸~ 学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。 目录 一、引言 原理&#xff1a; 问题&#xff1a; 二、思路步骤 三、代码编写步骤 A、代码各步骤的方法、目的及意义 1. 导入所需的库&…

测试人,你凭什么脱颖而出?

我们在软件测试面试时&#xff0c;可能经常会碰到HR这样问“与其他竞争者相比&#xff0c;你认为自己的优势在哪里&#xff1f;” 看似简单&#xff0c;但仔细深思可能心理陡然冰冰凉&#xff0c;因为自己难以有信心比他人突出&#xff08;除了腰间盘&#xff09;&#xff0c;看…

DBA 抓包神器 tshark 测评

想窥探神秘的网络世界的奥秘&#xff0c;tshark 助你一臂之力&#xff01; 作者&#xff1a;赵黎明 爱可生 MySQL DBA 团队成员&#xff0c;熟悉 Oracle、MySQL 等数据库&#xff0c;擅长数据库性能问题诊断、事务与锁问题的分析等&#xff0c;负责处理客户 MySQL 及我司自研 D…

chatgpt赋能python:Python火了原因分析

Python火了原因分析 Python语言是近年来最热门的编程语言之一&#xff0c;有很多原因可以解释它的成功。本文将介绍三个最重要的原因&#xff0c;以及如何利用这些原因来提高您的Python编程技能。 Python具有易学性和流行的库 Python的设计使它非常容易学习&#xff0c;尤其…

【机器学习】十大算法之一 “朴素贝叶斯”

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typeblog个…

Visual Studio Code Arduino资源占用和效率对比

Visual Studio Code&Arduino资源占用和效率对比 系统资源占用&#xff1a;编译效率&#xff1a; 这段时间在玩ESP32&#xff0c;闲来无事对比了一下Visual Studio Code后面简称VS和Arduino的效率和资源占用&#xff0c;只是大致的对比&#xff0c;没有斤斤计较。 配置为&am…

springboot集成swagger

文章目录 swagger概述swagger常用注解ApiImplicitParam swagger的集成方式集成swagger2.9集成swagger2.10集成swagger3 swagger概述 swagger是当下比较流行的实时接口文文档生成工具。接口文档是当前前后端分离项目中必不可少的工具&#xff0c;在前后端开发之前&#xff0c;后…

Mysql数据库初体验

Mysql数据库初体验 一、数据库的基本概念1.数据&#xff08;Data&#xff09;2.表3.数据库4.数据库管理系统&#xff08;DBMS)5.数据库系统 二、数据库系统发展史1.第一代数据库2.第二代数据库3.第三代数据库 三、当今主流数据库介绍四、数据库分类1.关系数据库2.关系型 SQL 数…

前端教程:Canvas怎样创建画布和绘制图形?

HTML5提供了一种全新的画布功能&#xff0c;即通过Canvas来让用户在网页中绘制图形、文字、图片等。Canvas表示画布&#xff0c;现实生活中的画布是用来作画的&#xff0c;HTML5中的Canvas与之类似&#xff0c;我们可以称它为“网页中的画布”。默认情况下&#xff0c;Canvas是…

【MySQL高级篇笔记-锁(下) 】

此笔记为尚硅谷MySQL高级篇部分内容 目录 一、概述 二、MySQL并发事务访问相同记录 1、读-读情况 2、写-写情况 3、读-写或写-读情况 4、并发问题的解决方案 三、锁的不同角度分类 1、从数据操作的类型划分&#xff1a;读锁、写锁 2、从数据操作的粒度划分&#xf…

攻防渗透第四章(谷歌语法)

一、常用谷歌黑客语法 制定网站的URL site: 包含特定字符的URL inurl: 网页标题中包含特定字符 intitle: 正文中指定字符 intext: 指定类型文件 filetype 开发语言判断 site:163.com filetype:php site:163.com filetype:jsp site:163.com filetype:asp site:163.com filetype…

工具篇--4 消息中间件-RabbitMq 模型介绍

1 介绍: RabbitMQ 是一个开源的消息中间件&#xff0c;它实现了 AMQP&#xff08;高级消息队列协议&#xff09;标准&#xff0c;并且支持多种语言和操作系统&#xff0c;包括 Java、Python、Ruby、PHP、.NET、MacOS、Windows、Linux 等等。RabbitMQ 提供了可靠的消息传递机制…

实战:单点登录的两种实现方式,你学会了吗?

概念 单点登录&#xff08;Single Sign-On&#xff0c;SSO&#xff09;是一种身份验证服务&#xff0c;允许用户使用单个标识来登录多个应用程序或系统。如下图所示&#xff0c;用户只需要用户名/密码登陆一次就可以访问系统A、系统B和系统C。 在传统的登录方式中&#xff0c;…

HTML5 progress和meter控件

在HTML5中&#xff0c;新增了progress和meter控件。progress控件为进度条控件&#xff0c;可表示任务的进度&#xff0c;如Windows系统中软件的安装、文件的复制等场景的进度。meter控件为计量条控件&#xff0c;表示某种计量&#xff0c;适用于温度、重量、金额等量化的表现。…

【CSS】文字扫光 | 渐变光

码来 可调整角度与颜色值来改变效果 <p class"gf-gx-color">我是帅哥</p> <style>.gf-gx-color {background: -webkit-linear-gradient(135deg,red,red 25%,red 50%,#fff 55%,red 60%,red 80%,red 95%,red);-webkit-text-fill-color: transparen…

中国物流成本高在哪里?怎么降低?

随着中国经济的快速发展&#xff0c;物流行业也得到了快速发展。然而&#xff0c;尽管中国物流行业的规模已经达到了世界领先水平&#xff0c;但中国物流成本也一直是业内关注的一个问题。那么&#xff0c;中国物流成本高在哪里&#xff1f;怎么降低呢&#xff1f;本文将从多个…

Surface渲染流程解析:如何实现车载智能座舱的高质量图像显示?

SurfaceFlinger简介 SurfaceFlinger是Android系统中负责图形渲染和显示的一个系统服务&#xff0c;SurfaceFlinger负责将来自多个应用程序的屏幕缓冲区组合成单个屏幕缓冲区&#xff0c;并将最终结果输出到系统的显示设备上。SurfaceFlinger在Android系统中是一个非常重要的服…

大数据分析案例-基于逻辑回归算法构建心脏病发作预测模型

🤵‍♂️ 个人主页:@艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏 📂加关注+ 喜欢大数据分析项目的小伙伴,希望可以多多支持该系列的其他文章 大数据分析案例合集…

C++基础:二维费用的背包问题

注意&#xff1a;如果你还没搞定&#xff08;指的是真正理解&#xff09;01背包&#xff0c;请不要看。看了脑壳更晕 什么是二维费用的背包问题&#xff1f;请看AcWing上的一道题&#xff1a; 有 N 件物品和一个容量是 V 的背包&#xff0c;背包能承受的最大重量是 M。 每件物…

【几分醉意赠书活动 - 05期】 | 《编程语言系丛图书》

个人主页&#xff1a; 陈老老老板的博客主页传送门 几分醉意.的博客主页传送门 赠书活动 | 第五期 本期好书推荐&#xff1a;《编程语言系列丛书》 粉丝福利&#xff1a;书籍赠送&#xff1a;共计送出30本 参与方式&#xff1a;关注公众号&#xff1a;码上天空 回复关键词&…