Java SHA算法实战:选型、编码、文件校验与安全边界
说实话看到“SHA加密算法”这个标题我第一反应是这又是一个被写烂的入门Demo。但实际在项目里接手过几个跟数据校验、安全存储相关的模块之后我觉得“SHA”这一块值得聊的东西其实非常多——很多人止步于会用MessageDigest.getInstance(SHA-256)算个哈希但真正到了生产环境选哪个变体、怎么处理编码、文件流要怎么读、加了盐之后为什么还是不够这些问题如果不提前想清楚后面返工的成本会很高。这篇文章我不打算堆叠官方文档那套说法而是从实际开发的角度把这几年做Java后端时跟SHA打交道踩过的坑、沉淀下来的经验一次讲透。内容包括SHA家族的整体选型思路、MessageDigest的核心机制、字符串与文件场景的完整代码实现、加盐和HMAC的实际用法以及一张可以直接收藏的常见问题排查表。不管你是刚接触摘要算法的新手还是已经写过几版工具类但想确认有没有写错的老手这篇文章应该都能帮你省下一点试错时间。1. 先想清楚算法选型再写第一行代码很多人一上来就写SHA-256这本身没错但你要知道自己为什么选它。SHA这个家族里头SHA-1、SHA-256、SHA-512是三种完全不同的安全水位选错了场景轻则被安全评审打回重则给线上系统埋雷。1.1 为什么默认方案通常是SHA-256SHA-1输出160位20字节的哈希值在2005年就已经被理论碰撞攻击攻破2017年谷歌和一家安全机构联合制造了真实的SHA-1碰撞实例。所以只要你的系统跟“对抗恶意输入”沾边就不该再用SHA-1。SHA-256输出256位32字节目前没有实际可行的碰撞攻击而且计算性能相当好无论是纯软件实现还是硬件加速它都是性价比最高的选择。SHA-512虽然更长但在64位处理器上它的计算速度甚至可能比SHA-256更快因为SHA-512使用64位字长、更大的消息块和轮数结构。不过SHA-512的摘要长度是64字节比SHA-256长一倍存储和传输开销也随之变大。这里给大家一个实际表格把SHA家族里的主流变体摆在一起平时选型对照着看就行。算法输出长度位/字节内部结构安全状态典型场景SHA-1160 / 20Merkle-Damgård已实际碰撞不可用于安全场景仅兼容旧系统、数据去重SHA-224224 / 28Merkle-Damgård安全但较少使用需要更短摘要时折中SHA-256256 / 32Merkle-Damgård安全主流默认文件校验、消息摘要、数字签名SHA-384384 / 48Merkle-Damgård安全阶数更高兼容性要求较高的协议SHA-512512 / 64Merkle-Damgård安全64位平台性能好高安全要求的存储SHA-3可变Keccak海绵结构安全结构与SHA-2完全不同新型系统、需要算法多样化时1.2 JDK自带的摘要算法全家桶Java的java.security.MessageDigest从JDK 1.1开始就是标准API了你在生产环境里几乎不需要额外引第三方库就能完成99%的SHA需求。JDK根据运行平台的不同底层会通过SPI机制选择一个可用的安全提供者大多数情况下是SUN或SunJCE这些提供者原生支持SHA-1、SHA-224、SHA-256、SHA-384、SHA-512、SHA3-224、SHA3-256、SHA3-384、SHA3-512。有个容易忽略的点是算法名称字符串是大小写不敏感的但推荐严格写成标准的连字符大写形式比如SHA-256因为某些第三方安全提供者比如一些硬件加密模块对算法名的解析可能比较严格。注意MessageDigest不是线程安全的。同一个实例在多线程环境下调用digest()方法会导致结果错乱甚至抛出异常。正确的做法是每个线程单独创建实例或者用ThreadLocalMessageDigest去做线程级缓存。1.3 选型时容易踩的认知误区第一个误区是觉得SHA-512一定比SHA-256安全一倍。哈希安全性取决于抗碰撞能力的位长256位和512位的差距确实存在但SHA-512的膨胀也带来了两倍存储开销而SHA-256在当前算力下的安全性对绝大多数业务场景已经绰绰有余。除非是安全等级要求极高的政务、金融核心链路或者需要通过算法套件多样化来满足合规要求否则没必要为了“看起来更安全”去选SHA-512。第二个误区是把SHA加密挂在嘴边。严格来说SHA是摘要算法不是加密算法。加密是可逆的摘要不可逆。这个概念要是跟产品经理或安全评审解释不清楚后面往往会被要求“把哈希解开”你没法解这就是需求理解层面的问题。你可以在团队内部文档里统一把它叫“哈希/摘要算法”避免歧义。2. 动手之前先吃透MessageDigest核心机制我见过不少同事写哈希工具类时代码能跑但总有一种“临时拼凑”感比如每次循环都重新getInstance一次或者干脆把digest(byte[])和toString()混在一起用。想要写出稳、快、不出问题的代码得先理解MessageDigest的生命周期和使用机制。2.1 初始化、更新与一次性结算MessageDigest使用起来是个三段式流程getInstance创建实例update喂数据digest结算结果。核心设计意图是支持流式数据的增量哈希——你不需要一次性把所有数据加载进内存可以分批把数据块通过update(byte[], int, int)喂进去最后统一digest()得到完整摘要。MessageDigest digest MessageDigest.getInstance(SHA-256); digest.update(Hello, .getBytes(StandardCharsets.UTF_8)); digest.update(World!.getBytes(StandardCharsets.UTF_8)); byte[] hash digest.digest();这个例子看起来简单但注意digest()在执行时做两件事一是把已经喂进来的所有数据做最终填充和摘要计算二是同时重置内部状态。也就是说digest()之后这个实例不需要重新创建就能再次使用但如果你在digest()之后继续update()那是在一个重置后的新上下文中追加数据结果跟连续一次性输入是不等价的。所以实践上我建议一个实例结算完之后尤其是单线程场景下最保险的做法是直接重新getInstance避免状态心智负担。2.2 为什么JDK有现成的摘要计算方法还要自己处理Hex编码digest()返回的是byte[]也就是原始二进制摘要。很多初学者直接对这个字节数组做toString()得到一个类似[B1b6d3586的对象地址然后一脸懵。这是因为Java字节数组没有重写toString()你要的是可读的十六进制字符串JDK标准库并没有直接提供byte[] - Hex的便捷方法直到较新的JDK版本也仍然没有但HexFormat在JDK 17之后出现了。所以实际开发里需要自己写一个Hex转换或者用现成的库。我推荐在项目里统一封装下面这段是稳定高效的写法用了查表法比逐字节拼接String.format(%02x)快得多private static final char[] HEX_ARRAY 0123456789abcdef.toCharArray(); public static String bytesToHex(byte[] bytes) { char[] hexChars new char[bytes.length * 2]; for (int i 0; i bytes.length; i) { int v bytes[i] 0xFF; hexChars[i * 2] HEX_ARRAY[v 4]; hexChars[i * 2 1] HEX_ARRAY[v 0x0F]; } return new String(hexChars); }这里有一个要点bytes[i] 0xFF这一操作目的是把有符号的byte转成无符号的0到255范围因为Java的byte是带符号的负数的二进制表示在转十六进制时如果不做掩码处理会得到ffffffff这样的错误结果。这个细节是哈希工具类最常见的Bug点之一。2.3 开发中必须明确的三个编码细节第一个细节是字符串编码。同一个字符串用getBytes()平台默认字符集和getBytes(StandardCharsets.UTF_8)去计算哈希结果可能是不同的。在中文Windows环境下默认字符集是GBK在Linux服务器上默认字符集通常是UTF-8。你本地算出来的哈希到了服务器上对不上先查这里。// 推荐显式指定字符集 byte[] input text.getBytes(StandardCharsets.UTF_8);第二个细节是大小写。十六进制字符串输出时用大写还是小写本身不影响哈希的“值”但会影响对比的一致性。如果你跟外部系统对接必须先确认对方用的是大写还是小写。建议项目内部统一用小写因为小写十六进制在URL、文件名、数据库索引中更常见也避免了很多不必要的大小写转换。第三个细节是Base64与Hex的选择。同样的32字节摘要Base64表达为43个字符左右Hex表达为64个字符。如果你要存数据库或传输Base64更省空间但可读性差如果要给人看、打日志、做文件名Hex更好。我在做文件完整性校验时习惯用Hex在把哈希值塞进消息头或Token里时则用Base64。没有绝对标准但一定要统一。3. 完整实操从字符串哈希扩展到文件校验与批量计算理论说再多不如直接把能用的代码贴出来。这一节我会从最常用的字符串哈希工具类写起然后处理大文件校验时的内存优化问题再补上批量计算和HMAC的进阶写法。3.1 单字符串SHA-256工具类五段代码写完下面的工具类封装了最核心的流程获取实例、喂入字节、转Hex、输出。生产环境里我一般还会增加一个静态工厂方法允许调用方传入算法名这样想从SHA-256切换到SHA-512时不用改调用方代码。import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public final class ShaUtils { private ShaUtils() {} public static String sha256Hex(String text) { return hashHex(SHA-256, text.getBytes(StandardCharsets.UTF_8)); } public static String hashHex(String algorithm, byte[] data) { try { MessageDigest digest MessageDigest.getInstance(algorithm); byte[] hash digest.digest(data); return bytesToHex(hash); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(Unsupported algorithm: algorithm, e); } } private static final char[] HEX_ARRAY 0123456789abcdef.toCharArray(); public static String bytesToHex(byte[] bytes) { char[] hexChars new char[bytes.length * 2]; for (int i 0; i bytes.length; i) { int v bytes[i] 0xFF; hexChars[i * 2] HEX_ARRAY[v 4]; hexChars[i * 2 1] HEX_ARRAY[v 0x0F]; } return new String(hexChars); } }这段代码看起来简单但已经考虑了三个问题一是捕获了NoSuchAlgorithmException并转成了运行时异常调用方不会被强制try-catch烦扰二是显式使用UTF-8编码消除跨平台乱码三是Hex转换用查表法性能比String.format高出一个量级。实测在普通笔记本上这段代码计算一万次短字符串SHA-256耗时在几十毫秒级别完全够用。3.2 大文件哈希校验怎么优化内存计算文件SHA-256有一个非常经典的坑直接用Files.readAllBytes()把整个文件读进内存再哈希。这在几十MB的小文件上没问题但一旦文件到了几个GB内存就爆了。正确的姿势是开一个缓冲区循环读文件块每读一块就update一次最后digest。public static String sha256File(File file) throws IOException { try (InputStream in new BufferedInputStream(new FileInputStream(file))) { MessageDigest digest MessageDigest.getInstance(SHA-256); byte[] buffer new byte[8192]; int len; while ((len in.read(buffer)) ! -1) { digest.update(buffer, 0, len); } return bytesToHex(digest.digest()); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException(SHA-256 algorithm not available, e); } }缓冲区大小选8192字节是基于常见磁盘块大小和JVM默认IO缓冲折算出来的。你可以试着调成16KB或64KB在某些文件系统上吞吐会更好但8192是实测稳定且内存占用优雅的组合。这里有一个进阶优化点update(buffer, 0, len)比update(buffer)更安全因为最后一次read返回的字节数可能小于缓冲区长度如果直接update(buffer)会把上次遗留的无用数据也计算进去。重要提示文件哈希建议配合CRC32或文件大小一起使用。SHA-256只能确保内容一致如果文件元数据比如文件名、修改时间也需要校验那些数据不属于文件字节内容需要单独处理。3.3 批量计算时的并发处理和开销分析批量哈希的场景常见于数据同步、重命名去重或者构建增量索引。一次处理几万个字符串时如果循环里每次都重新getInstanceJVM创建对象的开销和GC压力会明显上升。我的做法是根据CPU核数开一个固定大小线程池用ThreadLocal缓存MessageDigest实例。private static final ThreadLocalMessageDigest DIGEST_HOLDER ThreadLocal.withInitial(() - { try { return MessageDigest.getInstance(SHA-256); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException(e); } }); public static String sha256Concurrent(String text) { MessageDigest digest DIGEST_HOLDER.get(); digest.reset(); byte[] hash digest.digest(text.getBytes(StandardCharsets.UTF_8)); return bytesToHex(hash); }注意这里我在使用前主动调了reset()目的就是防止上一个任务留下的内部状态污染当前结果。ThreadLocal加上reset()的组合既消灭了并发问题又避免了频繁创建实例。实测在四核机器上处理100万次短字符串哈希这个写法比同步单线程快3倍左右。不过要提醒你如果每个数据体量很小批量计算的瓶颈往往不在CPU而在对象创建和IO上。不要盲目上多线程先用单线程测一下耗时分布确认CPU密集后再做并发优化否则只是为了“看起来高性能”而陷入过度设计。3.4 用HMAC-SHA256解决密钥参与摘要的问题有时候你需要算的不是简单的哈希而是带密钥的摘要典型场景是API签名、Webhook回调验签。直接SHA-256(secret data)有长度扩展攻击等隐患正确的做法是用HMAC。JDK里Mac类支持HmacSHA256用法跟MessageDigest非常像只是初始化时需要传入SecretKeySpec。import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; public static String hmacSha256Hex(String data, String secretKey) { try { Mac mac Mac.getInstance(HmacSHA256); SecretKeySpec keySpec new SecretKeySpec( secretKey.getBytes(StandardCharsets.UTF_8), HmacSHA256); mac.init(keySpec); byte[] rawHmac mac.doFinal(data.getBytes(StandardCharsets.UTF_8)); return bytesToHex(rawHmac); } catch (Exception e) { throw new IllegalStateException(HMAC computation failed, e); } }这段代码里SecretKeySpec的第二个参数必须是HmacSHA256它告诉JVM这是一把用于HMAC-SHA256的密钥。密钥本身的长度建议至少32字节256位如果密钥太短虽然算法不会报错但抗暴力破解能力会下降。另外注意HMAC的密钥是敏感数据不要在日志里打印也不要在代码仓库里写死明文密钥要放到配置中心或环境变量里管理。4. 说“安全”之前得先明白SHA解决什么问题不解决什么问题既然标题里有“加密”两个字我觉得有必要把安全的边界讲透。SHA是一个很基础的密码学原语它本身不“加密”任何东西也不保证“安全”。你在项目里到底该怎么用它取决于你面对的是哪种威胁模型。4.1 密码存储只用SHA是典型的反面教材我在代码评审时看到太多类似的实现注册的时候把密码sha256Hex(password)存进数据库登录的时候再算一次比对。这种方案在安全测试面前不堪一击——因为你没有加盐同一个密码在所有系统里都得到同一个哈希值。攻击者拿到数据库后只需要用彩虹表预先算好的海量密码哈希表一匹配弱密码立刻原形毕露。正确做法是给每个用户生成独立的随机盐至少16字节然后把盐 密码的哈希结果存下来。更稳妥的做法是使用专门的慢哈希算法比如PBKDF2、bcrypt、scrypt或Argon2这些算法通过迭代计算加大暴力破解的成本。Java标准库自带PBKDF2实现一个加盐密码哈希其实并不复杂。// 生成带盐的PBKDF2哈希比单纯SHA-256更适合密码存储 public static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int keyLength) throws Exception { PBEKeySpec spec new PBEKeySpec(password, salt, iterations, keyLength); SecretKeyFactory factory SecretKeyFactory.getInstance(PBKDF2WithHmacSHA256); return factory.generateSecret(spec).getEncoded(); }如果你在维护一个旧系统密码已经是普通SHA-256了也不建议立刻全量重算因为用户不会告诉你明文密码。通常的做法是在登录验证逻辑里如果发现当前用户还是旧的哈希方案用输入的明文做一次升级算出新的加盐哈希再覆盖旧值。这叫做“渐进式哈希迁移”。4.2 文件完整性校验与发布校验的差异文件下载站的SHA-256校验值跟你在数据同步系统里算文件哈希目的完全不同。前者对抗的是“下载过程被篡改”前提是哈希值本身是通过可信渠道获得的后者对抗的是“传输或存储中的意外损坏”。同样是SHA-256这两类场景的信任模型不一样。做文件发布校验时哈希值最好跟发布包分开渠道传播。如果攻击者同时篡改了文件内容和官网上展示的哈希值那校验就形同虚设。实际项目中我一般把哈希值放到签名文件中或者直接从构建服务器读取并配合HTTPS传输。进一步说如果发布流程里有可信任的签名私钥建议对哈希值再做一次数字签名这样校验方就能确认“哈希值来自官方”。4.3 在实际项目里SHA需要配合哪些机制第一是时间戳。很多场景不只是要验证内容没变还要验证“在某个时间点之前内容就是这个样子”这需要可信时间戳服务配合。第二是随机数。如果你的系统需要一个防碰撞的标识比如生成短链接或唯一文件名用SHA-256对“随机数内容”做哈希可以降低碰撞概率但主要随机性还是要依赖安全的随机源。第三是审计日志。哈希值本身只能检测内容是否变化不能告诉你谁在什么时候改了内容所以要有配套的日志和权限系统。我不建议你把SHA当成一个万能安全组件。它是密码学工具箱里的一块积木只有跟其他机制组合起来才能撑起一个完整的安全边界。5. 常见问题与排查技巧实录写哈希工具类看似容易实际一跑起来问题一堆。这一节我把这些年频率最高的问题和排查思路整理成一个速查清单。每个问题都是我在实际项目里真遇到过的不是凭空想的。5.1 同一个字符串为什么我算出来和工具站不一样八成是字符集问题。你代码里用的是平台默认字符集而某些在线工具站默认用UTF-8如果你的运行环境是GBK结果当然不一样。排查方法很简单在代码里显式打印出text.getBytes()的字节长度跟工具站的输入字节长度对比。如果字节数都不一样说明底层编码已经错了。还有一个小概率原因是在线工具站把输入当成Base64解码后再哈希这种情况需要你先确认对方工具的输入处理逻辑。5.2 每次启动计算结果不同是怎么回事正常业务里同一个输入得到同一个哈希是基本要求如果结果不稳定第一检查点是你有没有往输入里混入随机盐。盐本身是随机的如果你在计算用户密码哈希时每次生成新盐当然每次都不同——这其实是正确行为。但如果你确认输入完全一致却得到不同结果那就要看是不是MessageDigest实例被多线程共享了。前面说过它不是线程安全的两个线程同时digest会导致内部状态互相覆盖。建议每个计算入口都新建实例或者用ThreadLocal隔离。5.3 文件哈希校验不通过先检查这三处第一文件传输过程中是否被转换过换行符。Windows的\r\n和Linux的\n是不同字节上传下载工具有时会自动转换这会让哈希完全变掉。第二文件尾部是否有额外数据。很多下载工具会给文件追加.part后缀或者元数据段直接改后缀名续传可能导致字节不一致。第三你的缓冲区读取是否漏掉了最后一次不满一个缓冲区的数据。如果代码里用了update(buffer)而不是update(buffer, 0, len)结果必错。5.4 性能“真慢”先看是不是在代码结构上犯浑我见过最夸张的一个案例某个服务计算短字符串哈希时每次请求都新建MessageDigest实例同时用String.format去拼接Hex结果在双核小机器上TPS只能跑到几百。排查后发现瓶颈根本不在算法本身而在Hex转换和对象创建上。把String.format换掉之后性能直接翻了十几倍。所以如果你觉得SHA-256慢先别急着上并发先用JMH或简单的System.nanoTime()做个基准测试看看CPU时间到底花在哪。5.5 排查方法清单与工具推荐我现在排查哈希问题有一套固定流程先固定输入编码强制UTF-8再固定输出格式统一小写Hex最后固定算法名连字符大写。按这个顺序检查90%的问题都能定位。如果还找不到问题就写一个最小复现类把输入、中间字节、输出全部打印出来跟开源工具站逐一比对很容易看出差异在哪一步。工具方面除了在线哈希工具站我常用openssl命令行在Linux环境中做交叉验证echo -n Hello, World! | sha256sum echo -n Hello, World! | openssl dgst -sha256注意echo -n不能丢丢了会多算一个换行符结果就跟程序里算了Hello, World!\n一样这是另一个经典坑。最后给一个常见问题速查表建议截图或收藏现象可能原因解决方案字符串哈希结果与工具站不一致字符集编码不同显式使用UTF-8取字节返回[Bxxxx直接对byte[]调用toString()用Hex转换工具类大文件计算OOM一次性readAllBytes改用缓冲区update并发下偶发结果错误MessageDigest被多线程共享改用ThreadLocal或新实例密码哈希被破解没有加盐或使用快速哈希改用PBKDF2/bcrypt/Argon2文件哈希总跟发布方不同换行符转换或尾部附加数据检查传输工具配置比对字节数我个人在实际操作中的体会是SHA算法本身没有太多可钻研的黑魔法真正的复杂度都藏在工程细节里——字符集、缓冲区、线程隔离、安全边界。你把这几个细节打磨好了一个看似简单的哈希工具类也会变得很可靠。如果你后续打算做文件秒传系统或者要在分布式环境里做内容寻址存储这篇文章里提到的思路完全可以作为起点只需要把文件块大小的策略和哈希索引的结构再往深处设计一层就行。

相关新闻

JsLeakWatcher 报出一批对象,真的是内存泄漏吗:页面缓存、监听器和可达路径怎么分

JsLeakWatcher 报出一批对象,真的是内存泄漏吗:页面缓存、监听器和可达路径怎么分

JsLeakWatcher 报出一批对象,真的是内存泄漏吗:页面缓存、监听器和可达路径怎么分 页面退出后 JsLeakWatcher 报出几十个对象,团队立刻把所有缓存清掉,结果二次进入变慢,告警却仍然存在。工具发现“对象仍可达”&…

2026/10/18 15:00:54 阅读更多 →
Aspose.Slides 25.5 JDK 16 集成指南:License校验与模块化配置

Aspose.Slides 25.5 JDK 16 集成指南:License校验与模块化配置

简介:本资源是面向Java开发者的企业级PowerPoint文档处理解决方案,适用于需在Spring Boot、Servlet等后台架构中实现PPT/PPTX自动化生成、格式转换与深度编辑的中高级开发场景。压缩包共2个文件(1个JAR组件 1个XML许可证)&#x…

2026/10/18 15:00:54 阅读更多 →
2026批量查快递轨迹用什么工具好:从预算成本看,小中大团队各自该花多少钱

2026批量查快递轨迹用什么工具好:从预算成本看,小中大团队各自该花多少钱

先说结论:批量查快递轨迹这件事,预算从48元/天到1288元/年,覆盖了所有规模的团队。关键不是花多少钱,是花的钱能不能对应上你的业务规模。下面用需求对照矩阵,把不同预算档位该匹配什么业务量讲清楚。固乔快递批量查询…

2026/10/18 15:00:54 阅读更多 →

最新新闻

hostapd-2.10源码解析:从编译到二次开发实战指南

hostapd-2.10源码解析:从编译到二次开发实战指南

简介:hostapd-2.10源码包面向Linux无线开发与嵌入式网络工程师,用于在Linux系统上以软件方式创建和管理WiFi热点,替代硬件AP实现主机模式接入点。包内共655个文件,以363个C源文件和235个头文件为核心,覆盖nl80211驱动、…

2026/10/18 15:50:15 阅读更多 →
LISREL验证性因素分析完整指南:从模型识别到拟合判读

LISREL验证性因素分析完整指南:从模型识别到拟合判读

简介:一份面向社会科学、心理学及教育学研究者与学生的LISREL软件验证性因素分析教学PPT,系统讲解结构方程模型中验证性因素分析的核心逻辑与实操要点。资源从“准确Vs简洁”的数据处理两难切入,说明如何输入相关矩阵、设定理论模型、输出再生…

2026/10/18 15:50:15 阅读更多 →
通义千问Qwen3本地部署实战:MoE架构、硬件选型与性能调优

通义千问Qwen3本地部署实战:MoE架构、硬件选型与性能调优

前几天有个朋友来问我,说他拿到一台旧工作站,想跑一个新出的开源模型,问我到底值不值得折腾。我第一反应是问他:你要跑的模型是哪个?他回答说在想跑通义千问 Qwen3 系列。我说那就很值得,Qwen3 这一代把 Mo…

2026/10/18 15:50:15 阅读更多 →
AI原生应用人机共创成功案例:用TaoToken统一Key打通多模型协作链路

AI原生应用人机共创成功案例:用TaoToken统一Key打通多模型协作链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 15:50:15 阅读更多 →
翁恺C语言习题集刷题指南:环境搭建、题型拆解与避坑要点

翁恺C语言习题集刷题指南:环境搭建、题型拆解与避坑要点

简介:浙江大学翁恺教授C语言课程习题与源码合集,专门面向C语言初学者、备考计算机等级考试或自学编程的读者,覆盖从基础语法到典型算法的多层次练习。资源共4个文件,包含txt题解文档、Python辅助脚本、inscode在线交互文件和html页…

2026/10/18 15:50:15 阅读更多 →
红色党建风工作总结PPT模板:从空白页到成稿的工程化流程

红色党建风工作总结PPT模板:从空白页到成稿的工程化流程

简介:这是一套面向党政部门的工作总结PPT模板,整体采用红色党建风格,视觉庄重且富有感染力,适合年终总结、阶段汇报、主题教育展示等场合。模板内置完整汇报逻辑,共分为工作目标与背景、工作成果与亮点、挑战与解决方案…

2026/10/18 15:49:14 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →