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

Python图片格式批量转换器教程


📚 前言

编程基础第一期《11-30》-- 在图像处理工作中,我们经常需要将大量图片从一种格式转换为另一种格式。本教程将介绍如何使用Python的Pillow库开发一个简单但功能强大的图片格式批量转换器,帮助你高效处理图片格式转换任务。

目录

    • 📚 前言
    • 🛠️ 开发环境准备
    • 💡 核心功能
    • 🧩 技术要点
      • 1. Pillow库基础
      • 2. 文件系统操作
      • 3. 用户界面
    • 📝 代码实现与解析
      • 1. 导入必要的库
      • 2. 图片格式转换核心函数
      • 3. 批量转换功能
      • 4. 命令行界面
      • 5. 图形用户界面
      • 6. 主函数
    • 🎮 使用方法
      • 命令行方式
      • GUI方式
    • 🔍 进阶知识点
      • 1. 图像处理基础
      • 2. Pillow高级特性
      • 3. 性能优化
    • 🚀 可扩展功能
    • 📝 总结

🛠️ 开发环境准备

  • Python 3.6+
  • Pillow库 (PIL的fork版本)

安装Pillow库:

pip install pillow

💡 核心功能

  1. 支持多种常见图片格式之间的转换(JPG, PNG, BMP, GIF, TIFF等)
  2. 批量处理指定文件夹中的所有图片
  3. 可选择保留原始图片或仅保留转换后的图片
  4. 支持调整图片质量和大小
  5. 简单的命令行界面和图形用户界面(GUI)两种使用方式

🧩 技术要点

1. Pillow库基础

Pillow是Python图像处理库(PIL)的一个分支,提供了丰富的图像处理功能。主要用到的模块:

  • Image: 图像对象的创建、读取和保存
  • ImageOps: 图像操作,如调整大小、翻转等
  • ImageEnhance: 图像增强,如亮度、对比度调整

2. 文件系统操作

  • 使用ospathlib模块处理文件路径
  • 递归遍历目录
  • 文件类型判断

3. 用户界面

  • 命令行参数解析
  • 简单GUI界面构建(使用tkinter)

📝 代码实现与解析

1. 导入必要的库

from PIL import Image
import os
import sys
import argparse
from pathlib import Path
import tkinter as tk
from tkinter import filedialog, messagebox, ttk

知识点

  • PIL.Image: Pillow的核心模块,用于图像处理
  • ospathlib: 文件系统操作
  • argparse: 命令行参数解析
  • tkinter: Python标准GUI库

2. 图片格式转换核心函数

def convert_image(input_path, output_path, format, quality=95, resize=None):"""转换单个图片的格式参数:input_path - 输入图片路径output_path - 输出图片路径format - 目标格式 (如 'JPEG', 'PNG')quality - 图片质量 (1-100, 仅对JPEG格式有效)resize - 调整大小的元组 (width, height) 或 None返回:bool - 转换是否成功"""try:# 打开图片img = Image.open(input_path)# 如果是RGBA模式且转换为JPEG,需要转换为RGB模式if img.mode == 'RGBA' and format.upper() == 'JPEG':img = img.convert('RGB')# 调整大小if resize:img = img.resize(resize, Image.LANCZOS)# 保存转换后的图片if format.upper() == 'JPEG':img.save(output_path, format=format, quality=quality)else:img.save(output_path, format=format)return Trueexcept Exception as e:print(f"转换图片 {input_path} 时出错: {e}")return False

知识点

  • Image.open(): 打开图片文件
  • 图像模式转换: RGBA转RGB(JPEG不支持透明通道)
  • Image.LANCZOS: 高质量的图像缩放算法
  • 异常处理: 捕获并处理可能的错误

3. 批量转换功能

def batch_convert(input_dir, output_dir, target_format, quality=95, resize=None, recursive=False, keep_original=True):"""批量转换指定目录中的图片参数:input_dir - 输入目录output_dir - 输出目录target_format - 目标格式quality - 图片质量resize - 调整大小的元组recursive - 是否递归处理子目录keep_original - 是否保留原始图片返回:tuple - (成功数量, 失败数量)"""# 支持的图片格式supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff']# 创建输出目录os.makedirs(output_dir, exist_ok=True)success_count = 0failed_count = 0# 遍历目录for root, dirs, files in os.walk(input_dir):# 如果不递归处理子目录且不是根目录,则跳过if not recursive and root != input_dir:continue# 创建对应的输出子目录rel_path = os.path.relpath(root, input_dir)if rel_path != '.':current_output_dir = os.path.join(output_dir, rel_path)os.makedirs(current_output_dir, exist_ok=True)else:current_output_dir = output_dir# 处理文件for file in files:# 检查文件扩展名ext = os.path.splitext(file)[1].lower()if ext not in supported_formats:continue# 构建输入和输出路径input_path = os.path.join(root, file)output_filename = os.path.splitext(file)[0] + '.' + target_format.lower()output_path = os.path.join(current_output_dir, output_filename)# 转换图片if convert_image(input_path, output_path, target_format, quality, resize):success_count += 1# 如果不保留原始图片且不是在原目录操作,则删除原始图片if not keep_original and input_dir != output_dir:try:os.remove(input_path)except:passelse:failed_count += 1return (success_count, failed_count)

知识点

  • os.walk(): 递归遍历目录
  • os.path.relpath(): 获取相对路径
  • os.makedirs(): 创建多级目录
  • 文件扩展名处理: 使用os.path.splitext()分离文件名和扩展名

4. 命令行界面

def setup_cli():"""设置命令行参数解析器"""parser = argparse.ArgumentParser(description='批量转换图片格式')parser.add_argument('input', help='输入目录或文件')parser.add_argument('output', help='输出目录')parser.add_argument('format', help='目标格式 (如: jpg, png, bmp)')parser.add_argument('-q', '--quality', type=int, default=95, help='图片质量 (1-100, 默认: 95)')parser.add_argument('-r', '--recursive', action='store_true', help='递归处理子目录')parser.add_argument('-k', '--keep', action='store_true', help='保留原始图片')parser.add_argument('--resize', nargs=2, type=int, metavar=('WIDTH', 'HEIGHT'),help='调整图片大小')return parser.parse_args()

知识点

  • argparse: 命令行参数解析
  • 参数类型: 位置参数、可选参数、标志参数
  • 参数类型转换: 使用type=int将字符串转换为整数

5. 图形用户界面

class ImageConverterGUI:def __init__(self, root):self.root = rootself.root.title("图片格式批量转换器")self.root.geometry("600x450")self.root.resizable(True, True)# 创建主框架main_frame = ttk.Frame(root, padding="10")main_frame.pack(fill=tk.BOTH, expand=True)# 输入目录ttk.Label(main_frame, text="输入目录:").grid(column=0, row=0, sticky=tk.W, pady=5)self.input_dir = tk.StringVar()ttk.Entry(main_frame, width=50, textvariable=self.input_dir).grid(column=1, row=0, pady=5)ttk.Button(main_frame, text="浏览...", command=self.browse_input).grid(column=2, row=0, padx=5, pady=5)# 输出目录ttk.Label(main_frame, text="输出目录:").grid(column=0, row=1, sticky=tk.W, pady=5)self.output_dir = tk.StringVar()ttk.Entry(main_frame, width=50, textvariable=self.output_dir).grid(column=1, row=1, pady=5)ttk.Button(main_frame, text="浏览...", command=self.browse_output).grid(column=2, row=1, padx=5, pady=5)# 目标格式ttk.Label(main_frame, text="目标格式:").grid(column=0, row=2, sticky=tk.W, pady=5)self.format_var = tk.StringVar(value="JPEG")formats = ["JPEG", "PNG", "BMP", "GIF", "TIFF"]ttk.Combobox(main_frame, textvariable=self.format_var, values=formats, width=10).grid(column=1, row=2, sticky=tk.W, pady=5)# 图片质量ttk.Label(main_frame, text="图片质量:").grid(column=0, row=3, sticky=tk.W, pady=5)self.quality_var = tk.IntVar(value=95)quality_frame = ttk.Frame(main_frame)quality_frame.grid(column=1, row=3, sticky=tk.W, pady=5)ttk.Scale(quality_frame, from_=1, to=100, variable=self.quality_var, orient=tk.HORIZONTAL, length=200).pack(side=tk.LEFT)ttk.Label(quality_frame, textvariable=self.quality_var).pack(side=tk.LEFT, padx=5)# 调整大小ttk.Label(main_frame, text="调整大小:").grid(column=0, row=4, sticky=tk.W, pady=5)resize_frame = ttk.Frame(main_frame)resize_frame.grid(column=1, row=4, sticky=tk.W, pady=5)self.resize_enabled = tk.BooleanVar(value=False)ttk.Checkbutton(resize_frame, text="启用", variable=self.resize_enabled).pack(side=tk.LEFT)ttk.Label(resize_frame, text="宽:").pack(side=tk.LEFT, padx=(10, 0))self.width_var = tk.IntVar(value=800)ttk.Entry(resize_frame, width=5, textvariable=self.width_var).pack(side=tk.LEFT, padx=(0, 5))ttk.Label(resize_frame, text="高:").pack(side=tk.LEFT)self.height_var = tk.IntVar(value=600)ttk.Entry(resize_frame, width=5, textvariable=self.height_var).pack(side=tk.LEFT)# 递归处理self.recursive_var = tk.BooleanVar(value=False)ttk.Checkbutton(main_frame, text="递归处理子目录", variable=self.recursive_var).grid(column=1, row=5, sticky=tk.W, pady=5)# 保留原始图片self.keep_original_var = tk.BooleanVar(value=True)ttk.Checkbutton(main_frame, text="保留原始图片", variable=self.keep_original_var).grid(column=1, row=6, sticky=tk.W, pady=5)# 转换按钮ttk.Button(main_frame, text="开始转换", command=self.start_conversion).grid(column=1, row=7, pady=10)# 进度条self.progress_var = tk.DoubleVar()ttk.Progressbar(main_frame, variable=self.progress_var, maximum=100).grid(column=0, row=8, columnspan=3, sticky=(tk.W, tk.E), pady=5)# 状态标签self.status_var = tk.StringVar(value="就绪")ttk.Label(main_frame, textvariable=self.status_var).grid(column=0, row=9, columnspan=3, sticky=tk.W, pady=5)def browse_input(self):directory = filedialog.askdirectory()if directory:self.input_dir.set(directory)def browse_output(self):directory = filedialog.askdirectory()if directory:self.output_dir.set(directory)def start_conversion(self):input_dir = self.input_dir.get()output_dir = self.output_dir.get()target_format = self.format_var.get()quality = self.quality_var.get()recursive = self.recursive_var.get()keep_original = self.keep_original_var.get()# 检查输入if not input_dir or not output_dir:messagebox.showerror("错误", "请指定输入和输出目录")return# 检查调整大小参数resize = Noneif self.resize_enabled.get():try:width = self.width_var.get()height = self.height_var.get()if width <= 0 or height <= 0:raise ValueError("宽度和高度必须大于0")resize = (width, height)except:messagebox.showerror("错误", "调整大小参数无效")return# 开始转换self.status_var.set("转换中...")self.root.update()try:success, failed = batch_convert(input_dir, output_dir, target_format, quality,resize, recursive, keep_original)self.status_var.set(f"转换完成。成功: {success}, 失败: {failed}")messagebox.showinfo("完成", f"转换完成\n成功: {success}\n失败: {failed}")except Exception as e:self.status_var.set(f"转换出错: {str(e)}")messagebox.showerror("错误", f"转换过程中出错:\n{str(e)}")

知识点

  • tkinter: Python标准GUI库
  • 布局管理: 使用grid布局
  • 控件使用: 标签、输入框、按钮、复选框、组合框、进度条等
  • 事件处理: 按钮点击事件
  • 文件对话框: 使用filedialog选择目录

6. 主函数

def main():# 检查是否有命令行参数if len(sys.argv) > 1:# 命令行模式args = setup_cli()# 检查输入和输出目录if not os.path.exists(args.input):print(f"错误: 输入路径 '{args.input}' 不存在")return# 调整大小参数resize = tuple(args.resize) if args.resize else None# 开始转换print(f"开始转换图片从 {args.input}{args.output},格式: {args.format}")success, failed = batch_convert(args.input, args.output, args.format.upper(),args.quality, resize, args.recursive, args.keep)print(f"转换完成。成功: {success}, 失败: {failed}")else:# GUI模式root = tk.Tk()app = ImageConverterGUI(root)root.mainloop()if __name__ == "__main__":main()

总代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-"""
图片格式批量转换器
功能: 批量将图片从一种格式转换为另一种格式,支持调整大小和质量
作者: Python开发者
"""from PIL import Image
import os
import sys
import argparse
from pathlib import Path
import tkinter as tk
from tkinter import filedialog, messagebox, ttkdef convert_image(input_path, output_path, format, quality=95, resize=None):"""转换单个图片的格式参数:input_path - 输入图片路径output_path - 输出图片路径format - 目标格式 (如 'JPEG', 'PNG')quality - 图片质量 (1-100, 仅对JPEG格式有效)resize - 调整大小的元组 (width, height) 或 None返回:bool - 转换是否成功"""try:# 打开图片img = Image.open(input_path)# 如果是RGBA模式且转换为JPEG,需要转换为RGB模式if img.mode == 'RGBA' and format.upper() == 'JPEG':img = img.convert('RGB')# 调整大小if resize:img = img.resize(resize, Image.LANCZOS)# 保存转换后的图片if format.upper() == 'JPEG':img.save(output_path, format=format, quality=quality)else:img.save(output_path, format=format)return Trueexcept Exception as e:print(f"转换图片 {input_path} 时出错: {e}")return Falsedef batch_convert(input_dir, output_dir, target_format, quality=95,resize=None, recursive=False, keep_original=True):"""批量转换指定目录中的图片参数:input_dir - 输入目录output_dir - 输出目录target_format - 目标格式quality - 图片质量resize - 调整大小的元组recursive - 是否递归处理子目录keep_original - 是否保留原始图片返回:tuple - (成功数量, 失败数量)"""# 支持的图片格式supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff']# 创建输出目录os.makedirs(output_dir, exist_ok=True)success_count = 0failed_count = 0# 遍历目录for root, dirs, files in os.walk(input_dir):# 如果不递归处理子目录且不是根目录,则跳过if not recursive and root != input_dir:continue# 创建对应的输出子目录rel_path = os.path.relpath(root, input_dir)if rel_path != '.':current_output_dir = os.path.join(output_dir, rel_path)os.makedirs(current_output_dir, exist_ok=True)else:current_output_dir = output_dir# 处理文件for file in files:# 检查文件扩展名ext = os.path.splitext(file)[1].lower()if ext not in supported_formats:continue# 构建输入和输出路径input_path = os.path.join(root, file)output_filename = os.path.splitext(file)[0] + '.' + target_format.lower()output_path = os.path.join(current_output_dir, output_filename)# 转换图片if convert_image(input_path, output_path, target_format, quality, resize):success_count += 1# 如果不保留原始图片且不是在原目录操作,则删除原始图片if not keep_original and input_dir != output_dir:try:os.remove(input_path)except:passelse:failed_count += 1return (success_count, failed_count)def setup_cli():"""设置命令行参数解析器"""parser = argparse.ArgumentParser(description='批量转换图片格式')parser.add_argument('input', help='输入目录或文件')parser.add_argument('output', help='输出目录')parser.add_argument('format', help='目标格式 (如: jpg, png, bmp)')parser.add_argument('-q', '--quality', type=int, default=95,help='图片质量 (1-100, 默认: 95)')parser.add_argument('-r', '--recursive', action='store_true',help='递归处理子目录')parser.add_argument('-k', '--keep', action='store_true',help='保留原始图片')parser.add_argument('--resize', nargs=2, type=int, metavar=('WIDTH', 'HEIGHT'),help='调整图片大小')return parser.parse_args()class ImageConverterGUI:def __init__(self, root):self.root = rootself.root.title("图片格式批量转换器")self.root.geometry("600x450")self.root.resizable(True, True)# 创建主框架main_frame = ttk.Frame(root, padding="10")main_frame.pack(fill=tk.BOTH, expand=True)# 输入目录ttk.Label(main_frame, text="输入目录:").grid(column=0, row=0, sticky=tk.W, pady=5)self.input_dir = tk.StringVar()ttk.Entry(main_frame, width=50, textvariable=self.input_dir).grid(column=1, row=0, pady=5)ttk.Button(main_frame, text="浏览...", command=self.browse_input).grid(column=2, row=0, padx=5, pady=5)# 输出目录ttk.Label(main_frame, text="输出目录:").grid(column=0, row=1, sticky=tk.W, pady=5)self.output_dir = tk.StringVar()ttk.Entry(main_frame, width=50, textvariable=self.output_dir).grid(column=1, row=1, pady=5)ttk.Button(main_frame, text="浏览...", command=self.browse_output).grid(column=2, row=1, padx=5, pady=5)# 目标格式ttk.Label(main_frame, text="目标格式:").grid(column=0, row=2, sticky=tk.W, pady=5)self.format_var = tk.StringVar(value="JPEG")formats = ["JPEG", "PNG", "BMP", "GIF", "TIFF"]ttk.Combobox(main_frame, textvariable=self.format_var, values=formats, width=10).grid(column=1, row=2,sticky=tk.W, pady=5)# 图片质量ttk.Label(main_frame, text="图片质量:").grid(column=0, row=3, sticky=tk.W, pady=5)self.quality_var = tk.IntVar(value=95)quality_frame = ttk.Frame(main_frame)quality_frame.grid(column=1, row=3, sticky=tk.W, pady=5)ttk.Scale(quality_frame, from_=1, to=100, variable=self.quality_var, orient=tk.HORIZONTAL, length=200).pack(side=tk.LEFT)ttk.Label(quality_frame, textvariable=self.quality_var).pack(side=tk.LEFT, padx=5)# 调整大小ttk.Label(main_frame, text="调整大小:").grid(column=0, row=4, sticky=tk.W, pady=5)resize_frame = ttk.Frame(main_frame)resize_frame.grid(column=1, row=4, sticky=tk.W, pady=5)self.resize_enabled = tk.BooleanVar(value=False)ttk.Checkbutton(resize_frame, text="启用", variable=self.resize_enabled).pack(side=tk.LEFT)ttk.Label(resize_frame, text="宽:").pack(side=tk.LEFT, padx=(10, 0))self.width_var = tk.IntVar(value=800)ttk.Entry(resize_frame, width=5, textvariable=self.width_var).pack(side=tk.LEFT, padx=(0, 5))ttk.Label(resize_frame, text="高:").pack(side=tk.LEFT)self.height_var = tk.IntVar(value=600)ttk.Entry(resize_frame, width=5, textvariable=self.height_var).pack(side=tk.LEFT)# 递归处理self.recursive_var = tk.BooleanVar(value=False)ttk.Checkbutton(main_frame, text="递归处理子目录", variable=self.recursive_var).grid(column=1, row=5,sticky=tk.W, pady=5)# 保留原始图片self.keep_original_var = tk.BooleanVar(value=True)ttk.Checkbutton(main_frame, text="保留原始图片", variable=self.keep_original_var).grid(column=1, row=6,sticky=tk.W, pady=5)# 转换按钮ttk.Button(main_frame, text="开始转换", command=self.start_conversion).grid(column=1, row=7, pady=10)# 进度条self.progress_var = tk.DoubleVar()ttk.Progressbar(main_frame, variable=self.progress_var, maximum=100).grid(column=0, row=8, columnspan=3,sticky=(tk.W, tk.E), pady=5)# 状态标签self.status_var = tk.StringVar(value="就绪")ttk.Label(main_frame, textvariable=self.status_var).grid(column=0, row=9, columnspan=3, sticky=tk.W, pady=5)def browse_input(self):directory = filedialog.askdirectory()if directory:self.input_dir.set(directory)def browse_output(self):directory = filedialog.askdirectory()if directory:self.output_dir.set(directory)def start_conversion(self):input_dir = self.input_dir.get()output_dir = self.output_dir.get()target_format = self.format_var.get()quality = self.quality_var.get()recursive = self.recursive_var.get()keep_original = self.keep_original_var.get()# 检查输入if not input_dir or not output_dir:messagebox.showerror("错误", "请指定输入和输出目录")return# 检查调整大小参数resize = Noneif self.resize_enabled.get():try:width = self.width_var.get()height = self.height_var.get()if width <= 0 or height <= 0:raise ValueError("宽度和高度必须大于0")resize = (width, height)except:messagebox.showerror("错误", "调整大小参数无效")return# 开始转换self.status_var.set("转换中...")self.root.update()try:success, failed = batch_convert(input_dir, output_dir, target_format, quality,resize, recursive, keep_original)self.status_var.set(f"转换完成。成功: {success}, 失败: {failed}")messagebox.showinfo("完成", f"转换完成\n成功: {success}\n失败: {failed}")except Exception as e:self.status_var.set(f"转换出错: {str(e)}")messagebox.showerror("错误", f"转换过程中出错:\n{str(e)}")def main():# 检查是否有命令行参数if len(sys.argv) > 1:# 命令行模式args = setup_cli()# 检查输入和输出目录if not os.path.exists(args.input):print(f"错误: 输入路径 '{args.input}' 不存在")return# 调整大小参数resize = tuple(args.resize) if args.resize else None# 开始转换print(f"开始转换图片从 {args.input}{args.output},格式: {args.format}")success, failed = batch_convert(args.input, args.output, args.format.upper(),args.quality, resize, args.recursive, args.keep)print(f"转换完成。成功: {success}, 失败: {failed}")else:# GUI模式root = tk.Tk()app = ImageConverterGUI(root)root.mainloop()if __name__ == "__main__":main()

知识点

  • 命令行模式和GUI模式的切换
  • sys.argv: 获取命令行参数
  • tkinter主循环: root.mainloop()

🎮 使用方法

命令行方式

# 基本用法
python image_converter.py 输入目录 输出目录 目标格式# 示例: 将input_folder中的图片转换为PNG格式并保存到output_folder
python image_converter.py input_folder output_folder png# 高级用法
python image_converter.py input_folder output_folder jpg -q 85 -r --resize 800 600

GUI方式

直接运行程序,不带任何参数:

python image_converter.py

然后在图形界面中:

  1. 选择输入目录
  2. 选择输出目录
  3. 设置目标格式和其他选项
  4. 点击"开始转换"按钮
    在这里插入图片描述

🔍 进阶知识点

1. 图像处理基础

  • 像素: 图像的基本单位
  • 颜色模式: RGB, RGBA, CMYK, 灰度等
  • 图像格式特点:
    • JPEG: 有损压缩,不支持透明度,适合照片
    • PNG: 无损压缩,支持透明度,适合图标和截图
    • GIF: 支持动画,有限的颜色数量
    • BMP: 无压缩,文件较大
    • TIFF: 高质量,支持多页,常用于专业印刷

2. Pillow高级特性

  • 图像增强: 亮度、对比度、锐化等调整
  • 滤镜效果: 模糊、锐化、边缘检测等
  • 图像合成: 图层混合、水印等
  • 批处理: 多进程处理提高效率

3. 性能优化

  • 使用生成器减少内存占用
  • 多线程/多进程处理提高转换速度
  • 缩略图生成优化

🚀 可扩展功能

  1. 批量水印添加:为图片添加文字或图片水印

  2. 图片批量裁剪:自动裁剪图片到指定比例或尺寸

  3. 批量图片优化:自动调整亮度、对比度和图片锐化

  4. 批量重命名:根据规则批量重命名图片文件

  5. 元数据处理:保留或清除EXIF信息

📝 总结

通过这个图片格式批量转换器项目,我们学习了以下Python编程知识:

  1. Pillow库的基本使用
  2. 文件系统操作
  3. 命令行参数解析
  4. GUI界面开发
  5. 批处理和异常处理
  6. 图像处理基础知识

物物而不物于物,念念而不念于念

http://www.xdnf.cn/news/730315.html

相关文章:

  • 【仿生机器人】仿生机器人系统架构设计2.0——具备可执行性
  • MySQL事务及其原理
  • 【Java】mybatis-plus乐观锁-基本使用
  • 高效微调大模型:LoRA技术详解
  • python里的Matplotlib库
  • C#面试问题41-60
  • 嵌入式(1):STM32 GPIO与AFIO深度解析:从原理到高阶应用实战
  • YOLO使用SAHI进行小目标检测
  • 深度剖析Node.js的原理及事件方式
  • AgenticSeek,开源本地通用AI Agent,自主执行任务
  • 从零开始手写一个Promise,彻底理解异步编程的核心原理
  • 如何获取Minio元数据
  • 每日八股文5.30
  • 谷云科技发布业内首份 Oracle OSB 迁移到 iPaaS 技术白皮书
  • 40. 自动化异步测试开发之编写异步业务函数、测试函数和测试类(类写法)
  • Delphi读写Mifare Desfire Ev1 Ev2 EV3卡修改AES密钥源码
  • 39. 自动化异步测试开发之编写异步业务函数、测试函数和测试类(函数写法)
  • 逆向分析基础总结
  • HTML 文件反编译指南:优化与学习网页代码
  • 【容器docker】启动容器kibana报错:“message“:“Error: Cannot find module ‘./logs‘
  • STUSB4500 PPS(PD3.0)快充SINK模块——应用 解析
  • [学习] C语言的回调函数(代码示例)
  • 数据基座觉醒!大数据+AI如何重构企业智能决策金字塔(下)
  • 【Linux 学习计划】-- 命令行参数 | 环境变量
  • 【目标检测】【AAAI-2022】Anchor DETR
  • 【Golang进阶】第八章:并发编程基础——从Goroutine调度到Channel通信实战
  • Redis持久化机制
  • MPC5744P——eTimer简介
  • Github 2025-05-30Java开源项目日报Top10
  • 《深入解析Go语言结构:简洁高效的工程化设计》