图片压缩与格式转换:优化应用资源加载

news/2025/11/30 23:40:48/文章来源:https://www.cnblogs.com/Autumnfish/p/19290841

图片压缩与格式转换:优化应用资源加载

引言

在 HarmonyOS 应用开发中,图片资源的管理对应用性能至关重要。不合理的图片处理会导致应用体积膨胀、加载速度变慢,甚至引发内存溢出问题。本文将深入讲解如何在 HarmonyOS Next(API 10+)中进行高效的图片压缩和格式转换,帮助开发者优化应用资源加载体验。

官方参考资料:

  • HarmonyOS API 参考
  • 媒体服务开发指南

图片处理基础概念

图片格式选择策略

在 HarmonyOS 应用开发中,选择合适的图片格式直接影响应用性能:

  • JPEG 格式:适用于照片类图片,支持高压缩比
  • PNG 格式:适用于需要透明度的图标和图形
  • WebP 格式:现代格式,在相同质量下体积更小
  • HEIC 格式:高效图像格式,iOS 生态常用

图片压缩级别

// 压缩质量级别定义示例
const CompressionLevel = {LOW: 0.3, // 低质量,高压缩MEDIUM: 0.6, // 中等质量HIGH: 0.8, // 高质量,低压缩LOSSLESS: 1.0, // 无损压缩
} as const;

HarmonyOS 图片处理 API 概览

核心图像处理类

HarmonyOS Next 提供了丰富的图像处理 API:

  • ImageSource:图像数据源管理
  • ImagePacker:图像打包和压缩
  • PixelMap:像素级图像操作
  • ImageReceiver:图像接收和处理

支持的图像格式

格式类型 编码支持 解码支持 特性说明
JPEG 有损压缩,适合照片
PNG 无损压缩,支持透明
WebP 现代格式,压缩率高
HEIC 高效图像格式
GIF 仅支持解码
BMP 仅支持解码

图片压缩实战

基础压缩方法

import image from '@ohos.multimedia.image';
import fileIo from '@ohos.file.fs';// 基础图片压缩函数
async function compressImage(sourceUri: string, targetUri: string, quality: number): Promise<boolean> {try {// 1. 创建ImageSource实例const sourceFile = await fileIo.open(sourceUri, fileIo.OpenMode.READ_ONLY);const imageSource = image.createImageSource(sourceFile.fd);// 2. 创建解码选项const decodingOptions: image.DecodingOptions = {desiredSize: { width: 1024, height: 1024 }, // 限制最大尺寸desiredRegion: { size: { width: 1024, height: 1024 }, x: 0, y: 0 },desiredPixelFormat: image.PixelMapFormat.RGBA_8888} catch (error) {console.error('内存优化处理失败:', error);return false;} finally {// 确保资源释放if (originalPixelMap) {originalPixelMap.release();}if (processedPixelMap && processedPixelMap !== originalPixelMap) {processedPixelMap.release();}if (sourceFile) {fileIo.close(sourceFile).catch(e => console.error('关闭文件失败:', e));}}}
}## 图片缓存策略### 内存缓存实现```typescript
// 内存缓存管理器
class ImageMemoryCache {private cache: Map<string, { pixelMap: image.PixelMap, timestamp: number }>;private maxSize: number;private memoryUsage: number;constructor(maxSizeBytes: number = 20 * 1024 * 1024) { // 默认20MBthis.cache = new Map();this.maxSize = maxSizeBytes;this.memoryUsage = 0;}async put(key: string, pixelMap: image.PixelMap): Promise<void> {// 估算内存使用const imageInfo = await pixelMap.getImageInfo();const pixelFormat = await pixelMap.getPixelFormat();const bytesPerPixel = this.getBytesPerPixel(pixelFormat);const estimatedSize = imageInfo.size.width * imageInfo.size.height * bytesPerPixel;// 检查是否需要清理缓存while (this.memoryUsage + estimatedSize > this.maxSize && this.cache.size > 0) {this.evictOldest();}// 存储到缓存this.cache.set(key, { pixelMap, timestamp: Date.now() });this.memoryUsage += estimatedSize;}get(key: string): image.PixelMap | null {const cached = this.cache.get(key);if (cached) {// 更新访问时间cached.timestamp = Date.now();return cached.pixelMap;}return null;}private evictOldest(): void {let oldestKey = '';let oldestTime = Infinity;this.cache.forEach((value, key) => {if (value.timestamp < oldestTime) {oldestTime = value.timestamp;oldestKey = key;}});if (oldestKey) {const removed = this.cache.get(oldestKey);if (removed) {removed.pixelMap.release();}this.cache.delete(oldestKey);// 注意:这里简化了内存计算,实际应该记录每个缓存项的大小}}private getBytesPerPixel(format: number): number {// 根据不同像素格式返回每像素字节数switch (format) {case image.PixelMapFormat.ARGB_8888:case image.PixelMapFormat.RGBA_8888:return 4;case image.PixelMapFormat.RGB_565:return 2;default:return 4; // 默认保守估计}}
}// 使用示例
const imageCache = new ImageMemoryCache();async function loadImageWithCache(imageUri: string): Promise<image.PixelMap | null> {// 尝试从缓存获取const cachedImage = imageCache.get(imageUri);if (cachedImage) {console.log('从缓存加载图片:', imageUri);return cachedImage;}// 缓存未命中,加载并缓存try {const file = await fileIo.open(imageUri, fileIo.OpenMode.READ_ONLY);const imageSource = image.createImageSource(file.fd);const pixelMap = await imageSource.createPixelMap();await fileIo.close(file);// 存入缓存await imageCache.put(imageUri, pixelMap);console.log('加载并缓存图片:', imageUri);return pixelMap;} catch (error) {console.error('加载图片失败:', error);return null;}
}

磁盘缓存实现

// 磁盘缓存管理器
class ImageDiskCache {private cacheDir: string;private maxSize: number;constructor(cacheDirectory: string,maxSizeBytes: number = 100 * 1024 * 1024) {// 默认100MBthis.cacheDir = cacheDirectory;this.maxSize = maxSizeBytes;// 确保缓存目录存在this.ensureCacheDirExists();}private async ensureCacheDirExists(): Promise<void> {try {const fileStat = await fileIo.stat(this.cacheDir);if (!fileStat.isDirectory) {await fileIo.mkdir(this.cacheDir, { recursive: true });}} catch (error) {// 目录可能不存在,创建它await fileIo.mkdir(this.cacheDir, { recursive: true });}}async put(key: string, imageData: Uint8Array): Promise<void> {const cachePath = this.getKeyPath(key);try {// 写入文件const file = await fileIo.open(cachePath,fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.CREATE);await fileIo.write(file.fd, imageData);await fileIo.close(file);// 更新最后修改时间await fileIo.utimes(cachePath, Date.now() / 1000, Date.now() / 1000);// 检查缓存大小并清理await this.cleanupIfNeeded();} catch (error) {console.error("写入缓存失败:", error);}}async get(key: string): Promise<Uint8Array | null> {const cachePath = this.getKeyPath(key);try {// 检查文件是否存在await fileIo.access(cachePath);// 读取文件内容const file = await fileIo.open(cachePath, fileIo.OpenMode.READ_ONLY);const fileStat = await fileIo.stat(cachePath);const buffer = new ArrayBuffer(fileStat.size);await fileIo.read(file.fd, buffer);await fileIo.close(file);// 更新最后访问时间await fileIo.utimes(cachePath, Date.now() / 1000, Date.now() / 1000);return new Uint8Array(buffer);} catch (error) {// 文件不存在或读取失败return null;}}private getKeyPath(key: string): string {// 使用简单的哈希方式生成文件名let hash = 0;for (let i = 0; i < key.length; i++) {hash = (hash << 5) - hash + key.charCodeAt(i);hash |= 0; // 转换为32位整数}return `${this.cacheDir}/img_cache_${hash}.bin`;}private async cleanupIfNeeded(): Promise<void> {try {// 获取缓存目录中的所有文件const files = await fileIo.readdir(this.cacheDir);// 计算总大小let totalSize = 0;const fileStats: Array<{ path: string; size: number; mtime: number }> =[];for (const file of files) {const filePath = `${this.cacheDir}/${file}`;const stat = await fileIo.stat(filePath);if (!stat.isDirectory) {totalSize += stat.size;fileStats.push({path: filePath,size: stat.size,mtime: stat.mtime * 1000, // 转换为毫秒});}}// 如果超过最大大小,删除最旧的文件if (totalSize > this.maxSize) {// 按修改时间排序fileStats.sort((a, b) => a.mtime - b.mtime);while (totalSize > this.maxSize && fileStats.length > 0) {const oldest = fileStats.shift();if (oldest) {await fileIo.unlink(oldest.path);totalSize -= oldest.size;}}}} catch (error) {console.error("清理缓存失败:", error);}}
}

实际应用案例

列表图片优化加载

// 图片列表优化管理器
class OptimizedImageListManager {private diskCache: ImageDiskCache;private memoryCache: ImageMemoryCache;private pendingOperations: Map<string, Promise<image.PixelMap | null>>;constructor() {this.diskCache = new ImageDiskCache("internal://app/image_cache");this.memoryCache = new ImageMemoryCache();this.pendingOperations = new Map();}async loadImageForList(imageUri: string,targetSize: { width: number; height: number }): Promise<image.PixelMap | null> {// 生成缓存键,包含目标尺寸const cacheKey = `${imageUri}_${targetSize.width}x${targetSize.height}`;// 检查是否有相同的请求正在进行if (this.pendingOperations.has(cacheKey)) {return this.pendingOperations.get(cacheKey);}// 创建加载操作const loadOperation = this.doLoadImage(cacheKey, imageUri, targetSize);this.pendingOperations.set(cacheKey, loadOperation);try {return await loadOperation;} finally {// 移除已完成的操作this.pendingOperations.delete(cacheKey);}}private async doLoadImage(cacheKey: string,originalUri: string,targetSize: { width: number; height: number }): Promise<image.PixelMap | null> {// 1. 尝试从内存缓存获取const memoryCached = this.memoryCache.get(cacheKey);if (memoryCached) {return memoryCached;}// 2. 尝试从磁盘缓存获取const diskCached = await this.diskCache.get(cacheKey);if (diskCached) {// 从缓存数据创建PixelMapconst pixelMap = await this.createPixelMapFromData(diskCached);if (pixelMap) {await this.memoryCache.put(cacheKey, pixelMap);}return pixelMap;}// 3. 加载原图并处理try {const file = await fileIo.open(originalUri, fileIo.OpenMode.READ_ONLY);const imageSource = image.createImageSource(file.fd);// 解码选项,按目标尺寸缩放const decodingOptions: image.DecodingOptions = {desiredSize: targetSize,desiredPixelFormat: image.PixelMapFormat.RGBA_8888,};// 创建缩放后的PixelMapconst pixelMap = await imageSource.createPixelMap(decodingOptions);await fileIo.close(file);// 编码处理后的图片用于缓存const imagePacker = image.createImagePacker();const packingOptions: image.PackingOption = {format: "image/webp",quality: 80,};const packedData = await imagePacker.packing(pixelMap, packingOptions);// 保存到缓存await this.diskCache.put(cacheKey, packedData);await this.memoryCache.put(cacheKey, pixelMap);return pixelMap;} catch (error) {console.error("加载并处理图片失败:", error);return null;}}private async createPixelMapFromData(data: Uint8Array): Promise<image.PixelMap | null> {try {// 创建内存缓冲区const buffer = new ArrayBuffer(data.length);const view = new Uint8Array(buffer);for (let i = 0; i < data.length; i++) {view[i] = data[i];}// 从缓冲区创建ImageSourceconst imageSource = image.createImageSource(buffer);return await imageSource.createPixelMap();} catch (error) {console.error("从缓存数据创建PixelMap失败:", error);return null;}}
}

性能优化最佳实践

图片资源优化建议

  1. 选择合适的图片格式

    • 照片类图片使用 JPEG 格式
    • 图标和需要透明度的图片使用 PNG 或 WebP
    • 追求最佳压缩率时使用 WebP
  2. 合理设置图片质量

    • 列表图片: 60-70%
    • 详情页图片: 75-85%
    • 高清展示图片: 85-95%
  3. 预加载和懒加载结合

    • 预加载可见区域附近的图片
    • 懒加载远离可视区域的图片
  4. 避免重复解码

    • 使用缓存机制减少重复解码
    • 相同图片只解码一次
  5. 资源释放时机

    • 页面离开时清理缓存
    • 组件销毁时释放相关图片资源

代码优化建议

// 图片资源管理器 - 全局单例
class ImageResourceManager {private static instance: ImageResourceManager;private memoryCache: ImageMemoryCache;private diskCache: ImageDiskCache;private activeResources: Set<string>;private constructor() {this.memoryCache = new ImageMemoryCache();this.diskCache = new ImageDiskCache("internal://app/image_cache");this.activeResources = new Set();}public static getInstance(): ImageResourceManager {if (!ImageResourceManager.instance) {ImageResourceManager.instance = new ImageResourceManager();}return ImageResourceManager.instance;}// 注册使用中的资源public registerResource(resourceId: string): void {this.activeResources.add(resourceId);}// 注销不再使用的资源public unregisterResource(resourceId: string): void {this.activeResources.delete(resourceId);// 可以在这里添加资源清理逻辑}// 清理未使用的资源public async cleanupUnused(): Promise<void> {// 实现资源清理逻辑console.log("清理未使用的图片资源");}// 应用退出时释放所有资源public async releaseAll(): Promise<void> {// 释放所有缓存资源console.log("释放所有图片资源");}
}

结语

本文详细介绍了在 HarmonyOS 应用开发中进行图片压缩与格式转换的技术要点。通过合理运用这些技术,可以显著提升应用的性能表现,减少资源消耗,改善用户体验。

在实际开发过程中,建议结合应用的具体场景和需求,选择合适的图片处理策略。同时,也要注意在追求性能优化的同时,保证图片的显示质量,找到性能与质量之间的平衡点。

随着 HarmonyOS 的不断发展,相信未来会有更多高效的图片处理 API 和技术出现,让开发者能够更轻松地优化应用资源加载。;

// 3. 解码图片
const pixelMap = await imageSource.createPixelMap(decodingOptions);// 4. 创建打包选项
const packingOptions: image.PackingOption = {format: "image/jpeg",quality: quality // 压缩质量 0-100
};// 5. 创建ImagePacker并打包
const imagePacker = image.createImagePacker();
const packResult = await imagePacker.packing(pixelMap, packingOptions);// 6. 保存压缩后的图片
const targetFile = await fileIo.open(targetUri, fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.CREATE);
await fileIo.write(targetFile.fd, packResult);// 7. 释放资源
await fileIo.close(sourceFile);
await fileIo.close(targetFile);
pixelMap.release();return true;

} catch (error) {
console.error('图片压缩失败:', error);
return false;
}
}


### 智能尺寸压缩```typescript
// 根据目标尺寸智能压缩
async function smartCompressBySize(sourceUri: string,targetUri: string,maxWidth: number,maxHeight: number
): Promise<boolean> {try {const sourceFile = await fileIo.open(sourceUri, fileIo.OpenMode.READ_ONLY);const imageSource = image.createImageSource(sourceFile.fd);// 获取图片原始尺寸const imageInfo = await imageSource.getImageInfo();const originalWidth = imageInfo.size.width;const originalHeight = imageInfo.size.height;// 计算缩放比例const scale = Math.min(maxWidth / originalWidth, maxHeight / originalHeight, 1);const targetWidth = Math.round(originalWidth * scale);const targetHeight = Math.round(originalHeight * scale);const decodingOptions: image.DecodingOptions = {desiredSize: { width: targetWidth, height: targetHeight },desiredPixelFormat: image.PixelMapFormat.RGBA_8888};const pixelMap = await imageSource.createPixelMap(decodingOptions);const imagePacker = image.createImagePacker();const packingOptions: image.PackingOption = {format: "image/jpeg",quality: 85 // 保持较好质量的压缩};const packResult = await imagePacker.packing(pixelMap, packingOptions);const targetFile = await fileIo.open(targetUri, fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.CREATE);await fileIo.write(targetFile.fd, packResult);await fileIo.close(sourceFile);await fileIo.close(targetFile);pixelMap.release();console.log(`图片从 ${originalWidth}x${originalHeight} 压缩到 ${targetWidth}x${targetHeight}`);return true;} catch (error) {console.error('智能压缩失败:', error);return false;}
}

批量图片压缩

// 批量处理多张图片
class BatchImageCompressor {private maxConcurrent: number;constructor(maxConcurrent: number = 3) {this.maxConcurrent = maxConcurrent;}async compressImages(imageList: Array<{ source: string; target: string }>,quality: number): Promise<Array<{ source: string; target: string; success: boolean }>> {const results: Array<{ source: string; target: string; success: boolean }> =[];// 控制并发数量for (let i = 0; i < imageList.length; i += this.maxConcurrent) {const batch = imageList.slice(i, i + this.maxConcurrent);const batchPromises = batch.map(async (item) => {const success = await compressImage(item.source, item.target, quality);return { ...item, success };});const batchResults = await Promise.all(batchPromises);results.push(...batchResults);}return results;}
}// 使用示例
const compressor = new BatchImageCompressor(2);
const imagesToCompress = [{source: "internal://app/images/photo1.jpg",target: "internal://app/compressed/photo1.jpg",},{source: "internal://app/images/photo2.png",target: "internal://app/compressed/photo2.jpg",},{source: "internal://app/images/photo3.webp",target: "internal://app/compressed/photo3.jpg",},
];compressor.compressImages(imagesToCompress, 75).then((results) => {results.forEach((result) => {console.log(`图片 ${result.source} 压缩${result.success ? "成功" : "失败"}`);});
});

图片格式转换

基础格式转换

// 通用格式转换函数
async function convertImageFormat(sourceUri: string,targetUri: string,targetFormat: string,quality: number = 80
): Promise<boolean> {try {const sourceFile = await fileIo.open(sourceUri, fileIo.OpenMode.READ_ONLY);const imageSource = image.createImageSource(sourceFile.fd);// 解码原图const pixelMap = await imageSource.createPixelMap();// 格式转换打包选项const packingOptions: image.PackingOption = {format: targetFormat,quality: quality,};const imagePacker = image.createImagePacker();const packResult = await imagePacker.packing(pixelMap, packingOptions);// 保存转换后的图片const targetFile = await fileIo.open(targetUri,fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.CREATE);await fileIo.write(targetFile.fd, packResult);await fileIo.close(sourceFile);await fileIo.close(targetFile);pixelMap.release();console.log(`格式转换完成: ${sourceUri} -> ${targetUri} (${targetFormat})`);return true;} catch (error) {console.error("格式转换失败:", error);return false;}
}

PNG 转 WebP 优化

// PNG转WebP专项优化
async function pngToWebPOptimized(sourceUri: string,targetUri: string,quality: number = 75
): Promise<{ success: boolean; originalSize: number; compressedSize: number }> {try {// 获取原文件大小const fileStats = await fileIo.stat(sourceUri);const originalSize = fileStats.size;const sourceFile = await fileIo.open(sourceUri, fileIo.OpenMode.READ_ONLY);const imageSource = image.createImageSource(sourceFile.fd);// 对于PNG转WebP,可以优化解码选项const decodingOptions: image.DecodingOptions = {desiredPixelFormat: image.PixelMapFormat.RGBA_8888,};const pixelMap = await imageSource.createPixelMap(decodingOptions);// WebP特定打包选项const packingOptions: image.PackingOption = {format: "image/webp",quality: quality,};const imagePacker = image.createImagePacker();const packResult = await imagePacker.packing(pixelMap, packingOptions);const targetFile = await fileIo.open(targetUri,fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.CREATE);await fileIo.write(targetFile.fd, packResult);// 获取压缩后文件大小const compressedStats = await fileIo.stat(targetUri);const compressedSize = compressedStats.size;const compressionRatio = (((originalSize - compressedSize) / originalSize) *100).toFixed(2);console.log(`压缩率: ${compressionRatio}% (${originalSize} -> ${compressedSize} bytes)`);await fileIo.close(sourceFile);await fileIo.close(targetFile);pixelMap.release();return {success: true,originalSize,compressedSize,};} catch (error) {console.error("PNG转WebP失败:", error);return { success: false, originalSize: 0, compressedSize: 0 };}
}

支持的目标格式配置

// 支持的转换格式配置
const SupportedConversions = {JPEG: {format: "image/jpeg",extensions: [".jpg", ".jpeg"],maxQuality: 100,supportsLossless: false,},PNG: {format: "image/png",extensions: [".png"],maxQuality: 100,supportsLossless: true,},WEBP: {format: "image/webp",extensions: [".webp"],maxQuality: 100,supportsLossless: true,},
} as const;// 格式转换管理器
class FormatConversionManager {async convertWithOptions(sourceUri: string,targetUri: string,options: {targetFormat: keyof typeof SupportedConversions;quality?: number;maxWidth?: number;maxHeight?: number;}): Promise<boolean> {const formatConfig = SupportedConversions[options.targetFormat];const effectiveQuality = Math.min(options.quality || 80,formatConfig.maxQuality);try {const sourceFile = await fileIo.open(sourceUri,fileIo.OpenMode.READ_ONLY);const imageSource = image.createImageSource(sourceFile.fd);// 动态设置解码选项const decodingOptions: image.DecodingOptions = {desiredPixelFormat: image.PixelMapFormat.RGBA_8888,};if (options.maxWidth && options.maxHeight) {decodingOptions.desiredSize = {width: options.maxWidth,height: options.maxHeight,};}const pixelMap = await imageSource.createPixelMap(decodingOptions);const imagePacker = image.createImagePacker();const packingOptions: image.PackingOption = {format: formatConfig.format,quality: effectiveQuality,};const packResult = await imagePacker.packing(pixelMap, packingOptions);const targetFile = await fileIo.open(targetUri,fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.CREATE);await fileIo.write(targetFile.fd, packResult);await fileIo.close(sourceFile);await fileIo.close(targetFile);pixelMap.release();return true;} catch (error) {console.error(`格式转换失败 [${options.targetFormat}]:`, error);return false;}}
}

高级优化技巧

渐进式加载优化

// 渐进式JPEG生成
async function createProgressiveJPEG(sourceUri: string,targetUri: string,quality: number = 75
): Promise<boolean> {try {const sourceFile = await fileIo.open(sourceUri, fileIo.OpenMode.READ_ONLY);const imageSource = image.createImageSource(sourceFile.fd);const pixelMap = await imageSource.createPixelMap();const imagePacker = image.createImagePacker();// 渐进式JPEG配置const packingOptions: image.PackingOption = {format: "image/jpeg",quality: quality,// 注意:HarmonyOS API 10中渐进式JPEG支持需要检查具体实现};const packResult = await imagePacker.packing(pixelMap, packingOptions);const targetFile = await fileIo.open(targetUri,fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.CREATE);await fileIo.write(targetFile.fd, packResult);await fileIo.close(sourceFile);await fileIo.close(targetFile);pixelMap.release();return true;} catch (error) {console.error("生成渐进式JPEG失败:", error);return false;}
}

内存优化处理

// 内存优化的图片处理
class MemoryOptimizedImageProcessor {private readonly MAX_MEMORY_USAGE = 50 * 1024 * 1024; // 50MBasync processWithMemoryLimit(sourceUri: string,processingCallback: (pixelMap: image.PixelMap) => Promise<image.PixelMap>): Promise<boolean> {let sourceFile: fileIo.File | null = null;let originalPixelMap: image.PixelMap | null = null;let processedPixelMap: image.PixelMap | null = null;try {sourceFile = await fileIo.open(sourceUri, fileIo.OpenMode.READ_ONLY);const imageSource = image.createImageSource(sourceFile.fd);// 获取图片信息评估内存使用const imageInfo = await imageSource.getImageInfo();const estimatedMemory = imageInfo.size.width * imageInfo.size.height * 4; // RGBAif (estimatedMemory > this.MAX_MEMORY_USAGE) {// 大图片需要先缩放const scale = Math.sqrt(this.MAX_MEMORY_USAGE / estimatedMemory);const decodingOptions: image.DecodingOptions = {desiredSize: {width: Math.round(imageInfo.size.width * scale),height: Math.round(imageInfo.size.height * scale)}};originalPixelMap = await imageSource.createPixelMap(decodingOptions);} else {originalPixelMap = await imageSource.createPixelMap();}// 执行处理回调processedPixelMap = await processingCallback(originalPixelMap);return true;}

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

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

相关文章

86 [深度解析] 系统的产生依赖于什么?

[深度解析] 系统的产生依赖于什么? 我们或许有一种常规的想法:这个电脑C盘没有安装系统,那么这个电脑里面没有系统. 这种说法准确吗?我们拿到一台电脑,也就是拿到了这台电脑的硬件. 这个硬件里面,包含了一个内嵌的软…

ArkTS 泛型编程指南:提升代码复用性与类型安全

ArkTS 泛型编程指南:提升代码复用性与类型安全 引言 在 HarmonyOS ArkTS 开发中,泛型是一种强大的编程工具,它允许我们编写可重用的代码,同时保持类型安全。通过泛型,我们可以创建适用于多种数据类型的组件、函数…

87 Windows 系统安装的本质是什么?

Windows 系统安装的本质是什么? 安装 Windows 系统,步骤复杂,方法多样,工具纷繁,变幻莫测.但是万变不离其宗. Windows 系统安装的本质,其实就是两点:解压wim 建立引导解压wim Windows系统安装所需的所有文件都被保存在…

内存溢出问题

内存溢出问题 最近在项目中遇到上传多图片到后端,进行压缩等比缩放,内存溢出的问题

140 Windows 11 新系统一分钟打不开一个软件?原来卡顿的真凶在这里!

Windows 11 新系统一分钟打不开一个软件?原来卡顿的真凶在这里! 前两天安装Windows11虚拟机,发现新系统竟然连一个geek都需要等待1分钟才能打开.这在Windows10中秒开的软件,为什么在Windows11中变得唯唯诺诺?幕后真凶…

124 禁用Windows更新有bug?不如先暂停它2000年!

禁用Windows更新有bug?不如先暂停它2000年! 你是否同样被Windows更新困扰?明明好端端的系统,更新后C盘爆满,出现新的bug,更新时间还长,更可怕的是还可能出现更新失败的情况,直接导致系统崩溃,重要的数据丢失.每天看见…

43 微软官方安装Windows途径

微软官方安装Windows途径 和大家讲了这么多,好像从来没讲过微软希望我们用什么方法安装Windows系统.(偷笑) 那今天就浅浅的介绍一下微软官方提供的安装Windows系统的方法吧! 1.原系统为Windows7及以下: 下载Windows10的…

82 深入解析 Windows RE:系统维护的强大工具

深入解析 Windows RE:系统维护的强大工具 在日常使用 Windows 的过程中, 用户难免会遇到系统启动故障、无法正常操作等问题.这时, 一个熟悉又陌生的工具——Windows Recovery Environment (Windows RE)——往往能够扭转…

126 激活Windows系统的四种终极方法

激活Windows系统的四种终极方法 今天讨论一个敏感话题,如何破解激活Windows系统? 要知道,我们可是从来不用正版的 : ) 我们在网上搜索Windows激活,可以搜出一大堆东西.那么,这么多眼花缭乱的激活方法,有没有一个鼻祖呢…

99 如何破解 Windows 系统密码?

如何破解 Windows 系统密码?请注意:本文不是教非法的事情.而是教实用技术.Windows系统开机密码忘了,怎么办? 下面说说一般情况下Windows系统登录的时候都有哪些情况:使用本地账户登录 使用微软账户登录无论使用本地账…

讲讲django的文件对象

一、django文件对象是什么? Django 抽象出了一套“文件处理体系”,核心是:Django 所有文件类的基类 提供统一的接口用于:读取写入迭代存储到 Storage 后端(本地/OSS/S3)使用FileField / ImageField来构造:class…

香港中文大学(深圳) PHY1001 - Mechanics 笔记

笔记包括2025年秋学期该课程的知识点笔记包括2025年秋学期该课程的知识点 不包含高中物理中有的一些常见知识点Idealized Models 理想模型 为了研究最重要的性质而建立的比现实简单的模型,如研究物体下落轨迹时会忽略…

P9606 ABB

点击查看代码 #include<bits/stdc++.h>using namespace std;const int N=8e5+10; char str[N]; int ne[N];int main() {int n;string s;cin>>n>>s;//构造反转拼接字符串for(int i=0;i<n;i++){str…

微PE的磁盘化启动:不再使用WEPE64.WIM,直接从分区启动PE系统!

微PE的磁盘化启动:不再使用WEPE64.WIM,直接从分区启动PE系统 我们曾经学习过,PE系统的启动模式是Ramdisk.这是一种通过将内存虚拟成一块磁盘分区的方式启动的模式. (具体内容详见我的第25篇文章:《25Ramdisk 启动模式简…

73 Windows系统磁盘与分区知识详解

Windows系统磁盘与分区知识详解 在日常使用Windows操作系统的过程中,我们常常会接触到磁盘管理,磁盘分区等操作.然而,许多人可能并不完全理解磁盘和分区的运作原理以及如何高效管理它们. 本篇文章将探讨Windows系统中关…

不说废话,硬核干货:重装系统方法大总结!

不说废话,硬核干货:重装系统方法大总结! 重装系统到底有多少种方法?每种方法都怎么操作?本文列举出所有可行的重装系统方法,不讲原理,就是实操! 任何新系统的产生,都是依赖于它之前的系统.使用ISO直接装系统 我们从微…

isnumeric() 和 isdigit() 的区别

在 Python 中,isnumeric() 和 isdigit() 都是字符串方法,用于检查字符串中的字符是否属于特定类别(如数字)。虽然它们功能相似,但在处理某些字符时存在区别。以下是主要差异和适用场景:1. isdigit()定义:检查字…

109 C盘又变红了?清理C盘的便捷方法!

C盘又变红了?清理C盘的便捷方法! C 盘空间不足,是大多数 Windows 用户的“常见病”。当系统盘告急,不仅影响软件安装和系统更新,还可能拖慢整机速度。今天,我们就以“细致、系统、易上手”为原则全面清理 C 盘,让…

79 对系统迁移几种方案的经验之谈

对系统迁移几种方案的经验之谈声明: 本文由@CDsidi大佬所作,感谢CDsidi大佬为公众号贡献技术文章!!!最近笔记本电脑硬盘空间不够用了,于是打算换一个新硬盘,把原来的旧硬盘换下来.为了保持使用习惯的连续性,决定采用全…

108 彻底卸载Windows Defender的开源小工具

彻底卸载Windows Defender的开源小工具 在 Windows 系统中,内置的 Windows Defender(微软安全中心)虽然能够提供基本防护,但在某些场景下会影响性能或与第三方安全/虚拟化软件产生冲突。对于需要彻底移除或禁用 De…