当前位置: 首页 > news >正文

实现HBase表和RDB表的转化(附Java源码资源)

实现HBase表和RDB表的转化

在这里插入图片描述
在这里插入图片描述

一、引入

转化为HBase表的三大来源:RDB Table、Client API、Files

在这里插入图片描述
如何构造通用性的代码模板实现向HBase表的转换,是一个值得考虑的问题。这篇文章着重讲解RDB表向HBase表的转换。

首先,我们需要分别构造rdb和hbase的对象,根据批处理的思想,我们可以考虑批量将rdb中的数据导出,并且转化为List<Put>的格式,直接导入HBase表中,最后释放资源,伪代码模板如下:

rdb=...
hbase=...
rdb.init();
hbase.init();
while(rdb.hasNextBatch()){List<Put> batch = rdb.nextBatch();hbase.putBatch(batch);
}
hbase.close();
rdb.close();

二、代码讲解

1. 目录结构

在这里插入图片描述

2. 具体实现
  • transfer.properties
    在这里插入图片描述

内含HBase和RDB转换所有配置信息的配置文件,因为该配置文件是在启动时就需要进行配置,因此我们需要按以下图片进行配置导入配置文件:
在这里插入图片描述

  1. Run/Debug Configurations中,新建一个Application
  2. 配置好主类
  3. 配置好配置文件的具体路径
  • RDB 接口
public interface RDB extends Com {// 要提升性能,需要使用批处理boolean hasNextBatch() throws SQLException;// 是否存在下一个批次List<Put> nextBatch() throws SQLException;// 一个put代表往一个hbase表的一行的一个列族的一个列插入一条数据,对Hbase来说,批次就是List<Put>
}
  • RDB 实现类
public class RDBImpl implements RDB {private static Logger logger = Logger.getLogger(RDBImpl.class);// JDBC 的基本元素:连接对象(装载[驱动]、[URL]、[账号]、[密码])->执行对象(SQL语句)->结果集private Properties config;/*** 它们需要设置成全局变量的原因是它们需要共享*/private Connection con;private PreparedStatement pst;private ResultSet rst;// 定义每个批次处理的记录数的最大数量private int batchSize;// hbase的行键对应rdb的列的列名private String hbaseRowKeyRdbCol;private Map<String,Map<String,String>> hbaseRdbColMapping;// RDB配置可以灵活地从外部传入(构造方法),从内部读取(config())public RDBImpl(Properties config) {this.config = config;}@Overridepublic Properties config() {return config;}/*** 内部资源初始化*/@Overridepublic void init() throws Exception{con = getConnection();logger.info("RDB 创建 [ 连接 ] 对象成功");pst = getStatement(con);logger.info("RDB 创建 [ 执行 ] 对象成功");rst = getResult(pst);logger.info("RDB 创建 [ 结果集 ] 成功");batchSize = batchSize();hbaseRdbColMapping = hbaseRdbColumnsMapping();}@Overridepublic void close() {closeAll(rst,pst,con);}private String driver(){return checkAndGetConfig("rdb.driver");}private String url(){return checkAndGetConfig("rdb.url");}private String username(){return checkAndGetConfig("rdb.username");}private String password(){return checkAndGetConfig("rdb.password");}private String sql(){return checkAndGetConfig("rdb.sql");}private int batchSize(){return Integer.parseInt(checkAndGetConfig("rdb.batchSize"));}// java.sql下的Connectionprivate Connection getConnection() throws ClassNotFoundException, SQLException {// 装载驱动Class.forName(driver());// 获取并返回连接对象return DriverManager.getConnection(url(),username(),password());}private PreparedStatement getStatement(Connection con) throws SQLException {return con.prepareStatement(sql());}private ResultSet getResult(PreparedStatement statement) throws SQLException {return statement.executeQuery();}/*** hbase 列族和列与rdb中列的映射关系*             hbase列族   hbase列  rdb列* @return Map<String,Map<String,String>>*/private Map<String, Map<String,String>> hbaseRdbColumnsMapping(){String mapping = checkAndGetConfig("rdb.hbase.columns.mapping");Map<String,Map<String,String>> map = new HashMap<>();String[] pss = mapping.split(",");for(String ps : pss){String[] pp = ps.split("->");String[] p = pp[0].split(":");String rdbCol = pp[1],hbaseColFamily,hbaseColName;if(p.length==1){hbaseRowKeyRdbCol = pp[1];}else {hbaseColFamily = p[0];hbaseColName = p[1];if(!map.containsKey(hbaseColFamily)){map.put(hbaseColFamily,new HashMap<>());}map.get(hbaseColFamily).put(hbaseColName,rdbCol);}}return map;}/*** 将RDB的列转化为字节数组(需要确定列的数据类型)* @param rdbColumn* @return* @throws SQLException*/private byte[] toBytesFromRdb(String rdbColumn) throws SQLException {Object obj = rst.getObject(rdbColumn);if(obj instanceof String){return Bytes.toBytes((String)obj);} else if(obj instanceof Float){return Bytes.toBytes(((Float)obj).floatValue());} else if(obj instanceof Double){return Bytes.toBytes(((Double)obj).doubleValue());} else if(obj instanceof BigDecimal){return Bytes.toBytes((BigDecimal)obj);} else if(obj instanceof Short){return Bytes.toBytes(((Short) obj).shortValue());} else if(obj instanceof Integer){return Bytes.toBytes(((Integer)obj).intValue());} else if(obj instanceof Boolean){return Bytes.toBytes((Boolean)((Boolean) obj).booleanValue());} else {throw new SQLException("HBase不支持转化为字节数组的类型:"+obj.getClass().getName());}}/*** 将HBase的列名或列族名转化为字节数组* @param name* @return*/private byte[] toBytes(String name){return Bytes.toBytes(name);}// 最后一个批次的数据最少有一条@Overridepublic boolean hasNextBatch() throws SQLException{return rst.next();}@Overridepublic List<Put> nextBatch() throws SQLException{// 预先分配容量List<Put> list = new ArrayList<>(batchSize);int count = 0;do{/*** 如何将一行解析为多个put(结合配置文件)* 对每条数据,创建一个带行键的put,向put中放入HBase列族名,HBase列名,RDB列名*/Put put = new Put(toBytesFromRdb(hbaseRowKeyRdbCol));for (Map.Entry<String, Map<String, String>> e : hbaseRdbColMapping.entrySet()) {String columnFamily = e.getKey();for (Map.Entry<String, String> s : e.getValue().entrySet()) {String hbaseColumn = s.getKey();String rdbColumn = s.getValue();// 需要将内容转变为字节数组传入方法put.addColumn(toBytes(columnFamily),toBytes(hbaseColumn),toBytesFromRdb(rdbColumn));}}list.add(put);}while(++count<batchSize && rst.next());return list;}}

如何理解一行转化为多个put?
在这里插入图片描述
结果集的实质?
在这里插入图片描述
rst.next() 的两个作用

rst.next();
// 1.判定是否存在下一个有效行
// 2.若存在下一个有效行,则指向该有效行

a. 只通过config作为参数构造rdb
b. 以JDBC为核心,需要连接对象(驱动,URL,账号,密码)=>执行对象(SQL)=>结果集,这些都需要被设计为全局变量(因为需要被共享)
c. 既实现了RDB接口,还实现了RDB的继承接口Com中的init()、close()进行资源的初始化和释放,checkAndGetConfig()根据传入的配置文件获取配置信息并且赋值给全局变量。
d. 重点:我们还需要对RDB和HBase的映射关系进行解析,最终解析出RDB列名,HBase列族名,HBase列名,具体如何解析参考配置文件transfer.properties,并将解析出来的名字构造成一个Put对象,由于构造Put对象只能放字节数组,所以需要转化为字节数组的方法,又因为解析RDB的列名需要考虑列的数据类型,而解析HBase的列族或列名不需要考虑,因此需要有两个转换方法==ToBytesFromRDB()和ToBytes()==分别实现两种情况的字节数组转化。

  • HBase接口
public interface HBase extends Com {// RDBImpl的nextBatch()返回的就是List<Put>,直接放入HBase表即可。void putBatch(List<Put> batch) throws IOException;
}
  • HBase实现类
public class HBaseImpl implements HBase {private static Logger loggerHBase = Logger.getLogger(HBaseImpl.class);private Properties config;private Connection con;private Table hbaseTable;public HBaseImpl(Properties config) {this.config = config;}@Overridepublic Properties config() {return config;}@Overridepublic void init() throws Exception {con = getCon();loggerHBase.info("HBase 创建 [ 连接 ] 成功");hbaseTable = checkAndGetTable(con);loggerHBase.info("HBase 创建 [ 数据表 ] 成功");}@Overridepublic void close() {closeAll(hbaseTable,con);}private String tableName(){return checkAndGetConfig("hbase.table.name");}private String zkUrl(){return checkAndGetConfig("hbase.zk");}private Connection getCon() throws IOException {// hadoop.conf的configurationConfiguration config = HBaseConfiguration.create();config.set("hbase.zookeeper.quorum",zkUrl());return ConnectionFactory.createConnection(config);}private Table checkAndGetTable(Connection con) throws IOException {/*** Admin : HBase DDL*/Admin admin = con.getAdmin();TableName tableName = TableName.valueOf(tableName());// 通过tableName判定表是否存在if(!admin.tableExists(tableName)){throw new IOException("HBase表不存在异常:"+tableName);}/*** Table : HBase DML & DQL*/// 传入的参数可以是TableName tableName,ExecutorService pool(表操作可以并发)return con.getTable(tableName);}@Overridepublic void putBatch(List<Put> batch) throws IOException{hbaseTable.put(batch);}
}

HBase的实现类和RDB的实现类也非常类似:
先重写HBase接口中的方法和Com接口中的方法,发现往里放数据需要构造一个Table对象,而Table对象的构建需要一个连接对象和TableName,因此在构造了两个方法tableName()获取配置信息中的TableName(注意:此时的TableName是字符串类型),zkUrl()获取zk.url作为配置构造连接对象。

  • Com接口
public interface Com {Logger logger = Logger.getLogger(Com.class);// 获取配置对象Properties config();// 初始化资源void init() throws Exception;// 释放资源void close();default String checkAndGetConfig(String key){if(!config().containsKey(key)){// 因为该方法可能被用于HBase和RDBthrow new RuntimeException("配置项缺失异常:"+key);}String item = config().getProperty(key);logger.info(String.format("获取配置项 %s : %s",key,item));return item;}default void closeAll(AutoCloseable...acs){for (AutoCloseable ac : acs) {if (Objects.nonNull(ac)) {try {ac.close();logger.info(String.format("释放 %s 成功",ac.getClass().getName()));} catch (Exception e) {logger.error("释放资源异常:"+e);}}}}
}

在Com接口中,设计了一些普通方法config()实现配置的导出,init()、close()资源的初始化和关闭;同样还设计了一些无需实现的默认方法便于实现init()和close()方法。这些方法适用于RDB和HBase的实现类。

  • RDBToHBase接口
public interface RDBToHBase {// 创建一个RDB对象void setRDB(RDB rdb);// 创建一个HBase对象void setHBase(HBase hbase);// 进行数据的传输void startTransfer();
}
  • RDBToHBase实现类
public class RDBToHBaseImpl implements RDBToHBase {// 日志显示private static Logger loggerRH = Logger.getLogger(RDBToHBaseImpl.class);private RDB rdb;private HBase hbase;@Overridepublic void setRDB(RDB rdb) {this.rdb = rdb;}@Overridepublic void setHBase(HBase hbase) {this.hbase = hbase;}@Overridepublic void startTransfer() {try {rdb.init();loggerRH.info("RDB 初始化成功");hbase.init();loggerRH.info("HBase 初始化成功");loggerRH.info("数据从 RDB 迁移至 HBase 开始...");int count = 0;while (rdb.hasNextBatch()) {final List<Put> batch = rdb.nextBatch();hbase.putBatch(batch);loggerRH.info(String.format("第 %d 批:%d 条数据插入成功",++count,batch.size()));}loggerRH.info("数据从 RDB 迁移至 HBase 结束...");} catch (Exception e){loggerRH.error("将 RDB 数据批量迁移至 HBase 异常",e);} finally{hbase.close();rdb.close();}}
}
  • AppRDBToHBase 实现类
public class AppRDBToHBase
{private static Logger logger = Logger.getLogger(AppRDBToHBase.class);private static void start(String[] args){try {if (Objects.isNull(args) || args.length == 0 || Objects.isNull(args[0])) {throw new NullPointerException("配置文件路径空指针异常");}final String PATH = args[0];final File file = new File(PATH);if (!file.exists() || file.length() == 0 || !file.canRead()) {throw new IOException("配置文件不存在、不可读、空白");}Properties config = new Properties();// final String path = args[0];config.load(new FileReader(file));RDB rdb = new RDBImpl(config);HBase hBase = new HBaseImpl(config);RDBToHBase rdbToHBase = new RDBToHBaseImpl();rdbToHBase.setRDB(rdb);rdbToHBase.setHBase(hBase);rdbToHBase.startTransfer();}catch(Exception e){logger.error("配置异常",e);}}public static void main( String[] args ) {start(args);}
}

对于传入的配置文件路径,既要检查路径本身,也要检查路径代表的文件本身。
通过流的方式将文件进行配置,并且利用该配置构造RDB和HBase并进行数据的传输

其他:日志文件系统Log.4j的应用
  • 准备:需要在Resources模块下配置log4j.properties文件
  • 注意:
    • 日志文件信息的输出方式有三种logger.error()、logger.info()、logger.warn() ,除了对错误信息进行输出之外,也要习惯于补充正常信息的输出,以增强代码的可读性。
    • log.4j除了在控制台打印日志信息之外,还能在磁盘下的日志文件中打印日志信息,因此在导入log4j.properties文件之后需要修改日志文件的路径。
    • 对于不同类或接口下的logger,需要注意进行名字的区分。

相关文章:

实现HBase表和RDB表的转化(附Java源码资源)

实现HBase表和RDB表的转化 一、引入 转化为HBase表的三大来源&#xff1a;RDB Table、Client API、Files 如何构造通用性的代码模板实现向HBase表的转换&#xff0c;是一个值得考虑的问题。这篇文章着重讲解RDB表向HBase表的转换。 首先&#xff0c;我们需要分别构造rdb和hba…...

10:00面试,10:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到8月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…...

【Python】: Django Web开发实战(详细教程)

Python Django全面介绍 Django是一个非常强大的Python Web开发框架&#xff0c;它以"快速开发"和"干净、实用的设计"为设计宗旨。本文将从Django的基本概念开始&#xff0c;逐渐引导大家理解如何使用Django构建复杂的web应用程序。 Django基本概念与原理…...

突破编程_C++_C++11新特性(tuple)

1 std::tuple 简介 1.1 std::tuple 概述 std::tuple 是一个固定大小的不同类型值的集合&#xff0c;可以看作 std::pair 的泛化&#xff0c;即 std::pair 是 std::tuple 的一个特例&#xff0c;其长度受限为 2。与 C# 中的 tuple 类似&#xff0c;但 std::tuple 的功能更为强…...

xss.pwnfunction(DOM型XSS)靶场

环境进入该网站 Challenges (pwnfunction.com) 第一关&#xff1a;Ma Spaghet! 源码&#xff1a; <!-- Challenge --> <h2 id"spaghet"></h2> <script>spaghet.innerHTML (new URL(location).searchParams.get(somebody) || "Somebo…...

安装 docker 和 jenkins

安装 docker #安装 软件包 docker yum install -y yum-utils device-mapper-persistent-data lvm2#设置 yum 源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-c…...

jni入门学习 CMakeLists脚本

在 Android Studio 中使用 CMake 可以编译 C/C 代码&#xff0c;这为开发者提供了在 Android 应用中嵌入本地代码的能力。下面是关于在 Android Studio 中使用 CMake 编译的详细说明&#xff1a; 1. 创建 CMakeLists.txt 文件&#xff1a; 首先&#xff0c;你需要在项目的根目…...

如何在没有向量数据库的情况下使用知识图谱实现RAG

引言 传统上&#xff0c;为大型语言模型&#xff08;LLMs&#xff09;提供长期记忆通常涉及到使用检索增强生成&#xff08;RAG&#xff09;解决方案&#xff0c;其中向量数据库作为长期记忆的存储机制。然而&#xff0c;我们是否能在没有向量数据库的情况下达到相同效果呢&am…...

6.如何判断数据库搜索是否走索引?

判断是否使用索引搜索 索引在数据库中是一个不可或缺的存在&#xff0c;想让你的查询结果快准狠&#xff0c;还是需要索引的来帮忙&#xff0c;那么在mongo中如何判断搜索是不是走索引呢&#xff1f;通常使用执行计划&#xff08;解释计划、Explain Plan&#xff09;来查看查询…...

Java并发编程的性能优化方案中,哪些方法比较常用

在Java并发编程的性能优化方案中&#xff0c;以下是一些常用的方法&#xff1a; 线程池的使用&#xff1a; 线程池可以复用线程&#xff0c;避免频繁地创建和销毁线程&#xff0c;从而提高系统性能。常用的线程池有FixedThreadPool、CachedThreadPool等。根据任务特性选择合适…...

AcWing 2867. 回文日期(每日一题)

原题链接&#xff1a;2867. 回文日期 - AcWing题库 2020 年春节期间&#xff0c;有一个特殊的日期引起了大家的注意&#xff1a;2020 年 2 月 2 日。 因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202&#xff0c;恰好是一个回文数。 我们称这样的日期是…...

学习笔记-华为IPD转型2020:3,IPD的实施

3. IPD的实施 1999 年开始的 IPD 转型是计划中的多个转型项目中的第一个&#xff08;Liu&#xff0c;2015&#xff09;。华为为此次转型成立了一个专门的团队&#xff0c;从大约20人开始&#xff0c;他们是华为第一产业的高层领导。董事会主席孙雅芳是这个团队的负责人。该团…...

2024腾龙杯web签到题-初识jwt(签到:这是一个登录页面)

什么是 jwt? 它是 JSON Web Token 的缩写&#xff0c;是一个开放标准&#xff0c;定义了一种紧凑的、自包含的方式&#xff0c;用于作为JSON对象在各方之间安全地传输信息&#xff0c;该信息可以被验证和信任&#xff0c;因为它是数字签名的。它就是一种认证机制&#xff0c;…...

Monaco Editor系列(一)启动项目与入门示例解析

前言&#xff1a;作为一名程序员&#xff0c;我们工作中的每一天都在与代码编辑器打交道&#xff0c;相信各位前端程序员对 VS Code 一定都不陌生&#xff0c;VS Code 可以为我们提供代码高亮、代码对比等等功能&#xff0c;让我们在开发的时候&#xff0c;不需要对着暗淡无光的…...

DNA存储技术原理是什么?

随着大数据和人工智能的发展&#xff0c;全球每天产生的数据量剧增&#xff0c;对存储设备的需求也随之增长&#xff0c;数据存储问题日益凸显。传统的硬盘驱动器&#xff08;HDD&#xff09;、磁带等冷存和深度归档存储占据数据中心存储的60-70%&#xff0c;由于它们的访问频率…...

多维时序 | Matlab实现VMD-CNN-GRU变分模态分解结合卷积神经网络门控循环单元多变量时间序列预测

多维时序 | Matlab实现VMD-CNN-GRU变分模态分解结合卷积神经网络门控循环单元多变量时间序列预测 目录 多维时序 | Matlab实现VMD-CNN-GRU变分模态分解结合卷积神经网络门控循环单元多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现VMD-CN…...

基于springboot+vue的毕业论文管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…...

JavaWeb后端——分层解耦 IOC DI

分层/三层架构概述 三层架构&#xff1a;Controller、Service、Dao 解耦/IOC&DI概述 分层解耦 容器称为&#xff1a;IOC容器/Spring容器 IOC 容器中创建&#xff0c;管理的对象&#xff0c;称为&#xff1a;bean 对象 IOC&DI入门 实现 IOC&DI 需要的注解&#…...

短视频矩阵系统技术交付

短视频矩阵系统技术交付&#xff0c;短视频矩阵剪辑矩阵分发系统现在在来开发这个市场单个项目来说&#xff0c;目前基本上已经沉淀3年了&#xff0c;那么我们来就技术短视频矩阵剪辑系统开发来聊聊 短视频矩阵系统经过315大会以后&#xff0c;很多违规的技术开发肯定有筛选到了…...

Halcon 凹坑检测案例

* 使用元组的方法 ImageFile:[] ImageFile[0]:D:/Halcon/产品上的凹坑检测/1.bmp ImageFile[1]:D:/Halcon/产品上的凹坑检测/2.bmp for Index : 0 to |ImageFile|-1 by 1read_image (Image, ImageFile[Index])* 二值化threshold (Image, Region, 100, 255)* 连通性connection (…...

基于深度确定性策略梯度的 PID 控制器实时自适应优化仿真研究(Matlab代码、Simulink仿真实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

告别手动拉框!用Label Studio + YOLOv5实现图像标注自动化(保姆级教程)

智能标注革命&#xff1a;用Label Studio与YOLOv5打造零基础自动化标注系统 在计算机视觉项目的生命周期中&#xff0c;数据标注往往成为制约项目进度的最大瓶颈。传统人工标注不仅耗时费力&#xff0c;还容易因疲劳导致标注质量下降。想象一下&#xff0c;当你面对数万张待标注…...

【AGI可信性生死线】:从Gödel不完备到Isabelle/HOL自动化证明,2026奇点大会首次披露6层验证协议栈

第一章&#xff1a;2026奇点智能技术大会&#xff1a;AGI与数学证明 2026奇点智能技术大会(https://ml-summit.org) AGI驱动的自动定理证明新范式 本届大会首次公开展示了基于混合符号-神经架构的AGI定理证明系统FormalMind-7B&#xff0c;该系统在Coq 8.18与Lean 4.8环境中实…...

[CTF实战]从数字密文到Flag:Base与凯撒的联合破译

1. 数字密文的初步观察 拿到这道CTF题目时&#xff0c;首先映入眼帘的是一串长达百位的数字&#xff1a;3207357975641587136122466514425152961654613410728337142271750273124995105747053991640817066352343657398947248938255086358418100814441196784643527787764297。这…...

用C语言模拟‘爬井的蠕虫’:一个生动的循环结构教学案例(含时间计算陷阱分析)

用C语言模拟‘爬井的蠕虫’&#xff1a;循环结构的生动教学案例 想象一下&#xff0c;你正在教授C语言的循环结构&#xff0c;而学生们面对枯燥的while和for语句昏昏欲睡。这时&#xff0c;一条蠕虫的故事可以瞬间点燃课堂——它每分钟向上爬几寸&#xff0c;又滑下几寸&#x…...

2026最权威的AI论文网站实际效果

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 要切实有效地把文本里 AI 生成的特征予以降低&#xff0c;就得从词汇挑选、句式架构以及逻辑…...

仅剩17%头部AGI项目采用纯自注意力架构:2024 Q2全球23家AGI实验室架构迁移路线图全曝光

第一章&#xff1a;AGI的注意力机制与认知架构 2026奇点智能技术大会(https://ml-summit.org) 注意力机制已从Transformer中的序列建模工具&#xff0c;演进为AGI系统中支撑多模态感知、工作记忆调度与元认知调控的核心神经符号接口。在具备自主目标生成与跨任务迁移能力的AGI…...

USB-Disk-Ejector:重新定义Windows设备管理的终极革命

USB-Disk-Ejector&#xff1a;重新定义Windows设备管理的终极革命 【免费下载链接】USB-Disk-Ejector A program that allows you to quickly remove drives in Windows. It can eject USB disks, Firewire disks and memory cards. It is a quick, flexible, portable alterna…...

Altium Designer 20 画效果器原理图:从模块拆分到封装选择的保姆级避坑指南

Altium Designer 20 画效果器原理图&#xff1a;从模块拆分到封装选择的保姆级避坑指南 第一次用Altium Designer画电吉他效果器原理图时&#xff0c;我盯着空白的画布发呆了半小时——不是不会用软件&#xff0c;而是不知道从哪下手。直到把整个电路拆分成AMP、SWITCH等模块&a…...

G-Helper实战指南:华硕笔记本性能控制与系统优化的开源解决方案

G-Helper实战指南&#xff1a;华硕笔记本性能控制与系统优化的开源解决方案 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, …...