一文詳解Python如何處理無法解碼文件名
引言
在跨平臺文件處理、國際化應(yīng)用或系統(tǒng)管理工具開發(fā)中,我們經(jīng)常會遇到一個棘手的問題:文件名無法正確解碼。這種情況通常發(fā)生在不同操作系統(tǒng)、文件系統(tǒng)或區(qū)域設(shè)置之間傳輸文件時,特別是當(dāng)文件名包含非ASCII字符而編碼方式不匹配時。Python嘗試使用默認(rèn)文件系統(tǒng)編碼來解碼文件名,當(dāng)遇到無效字節(jié)序列時就會拋出UnicodeDecodeError。
處理無法解碼的文件名不僅是技術(shù)挑戰(zhàn),更是生產(chǎn)環(huán)境中必須妥善解決的問題。錯誤的處理方式可能導(dǎo)致文件丟失、數(shù)據(jù)不一致或應(yīng)用程序崩潰。從簡單的錯誤抑制到高級的編碼恢復(fù)策略,Python提供了多種方式來處理這一難題。
本文將深入探討Python中處理無法解碼文件名的方法,從基礎(chǔ)錯誤處理到高級恢復(fù)策略,通過大量實際示例展示如何在不同場景下選擇和應(yīng)用最合適的解決方案。我們將覆蓋os模塊、pathlib、自定義錯誤處理程序以及底層文件系統(tǒng)接口等多種技術(shù),幫助開發(fā)者構(gòu)建健壯的文件處理應(yīng)用。
一、理解文件名解碼問題
1.1 問題根源與常見場景
文件名解碼問題通常源于以下幾個方面:
import sys
import locale
def analyze_encoding_environment():
"""分析當(dāng)前環(huán)境的編碼設(shè)置"""
print("=== 編碼環(huán)境分析 ===")
print(f"文件系統(tǒng)編碼: {sys.getfilesystemencoding()}")
print(f"默認(rèn)編碼: {sys.getdefaultencoding()}")
print(f"區(qū)域設(shè)置編碼: {locale.getpreferredencoding()}")
# 檢查常見的問題場景
test_cases = [
# (描述, 字節(jié)序列, 可能編碼)
("中文文件名", "中文文件.txt".encode('gbk'), 'GBK'),
("日文文件名", "日本語.txt".encode('shift_jis'), 'Shift-JIS'),
("特殊字符", "café.txt".encode('iso-8859-1'), 'ISO-8859-1'),
("錯誤編碼", b'\xff\xfe\x00\x00invalid', '錯誤字節(jié)序列'),
]
print("\n=== 常見問題場景 ===")
for desc, bytes_data, encoding in test_cases:
try:
decoded = bytes_data.decode(sys.getfilesystemencoding())
status = "可解碼"
except UnicodeDecodeError:
status = "無法解碼"
print(f"{desc}: {status} (可能編碼: {encoding})")
# 運行分析
analyze_encoding_environment()1.2 解碼錯誤的類型與表現(xiàn)
文件名解碼錯誤主要表現(xiàn)為以下幾種形式:
- ??完全無法解碼??:字節(jié)序列與當(dāng)前編碼完全不匹配
- ??部分解碼錯誤??:部分字節(jié)可以解碼,但包含無效序列
- ??編碼不匹配??:解碼后的字符串顯示為亂碼但技術(shù)上是"成功"的解碼
- ??混合編碼??:文件名不同部分使用不同編碼
二、基礎(chǔ)錯誤處理策略
2.1 使用errors參數(shù)處理解碼錯誤
Python的字符串解碼方法提供了errors參數(shù)來控制解碼錯誤時的行為:
def demonstrate_error_handlers(problematic_bytes):
"""
演示不同的錯誤處理方式
"""
error_handlers = [
('strict', "嚴(yán)格模式(默認(rèn))"),
('ignore', "忽略錯誤字節(jié)"),
('replace', "替換錯誤字符"),
('backslashreplace', "使用反斜杠轉(zhuǎn)義"),
('surrogateescape', "代理轉(zhuǎn)義(特殊用途)"),
]
print("=== 錯誤處理策略比較 ===")
print(f"原始字節(jié): {problematic_bytes}")
print(f"字節(jié)長度: {len(problematic_bytes)}")
for handler, description in error_handlers:
try:
result = problematic_bytes.decode('utf-8', errors=handler)
print(f"{handler:15} {description:20} → '{result}'")
except Exception as e:
print(f"{handler:15} {description:20} → 錯誤: {e}")
# 測試用例
test_bytes = b'valid_part_\xff\xfe_invalid_part' # 混合有效和無效字節(jié)
demonstrate_error_handlers(test_bytes)2.2 安全的文件名打印函數(shù)
def safe_filename_display(filename):
"""
安全地顯示可能無法解碼的文件名
"""
if isinstance(filename, bytes):
# 字節(jié)文件名,需要謹(jǐn)慎處理
try:
# 首先嘗試系統(tǒng)編碼
decoded = filename.decode(sys.getfilesystemencoding())
return decoded
except UnicodeDecodeError:
# 系統(tǒng)編碼失敗,嘗試常見編碼
for encoding in ['utf-8', 'gbk', 'shift_jis', 'iso-8859-1']:
try:
decoded = filename.decode(encoding)
return f"{decoded} (檢測編碼: {encoding})"
except UnicodeDecodeError:
continue
# 所有編碼都失敗,使用安全表示
hex_representation = filename.hex()
if len(hex_representation) > 20:
hex_representation = hex_representation[:20] + "..."
return f"<無法解碼: {hex_representation}>"
else:
# 已經(jīng)是字符串,直接返回
return str(filename)
# 使用示例
test_filenames = [
"正常文件.txt",
"中文文件.txt".encode('gbk'),
"日本語.txt".encode('shift_jis'),
b'invalid_\xff\xfe_bytes.txt'
]
print("=== 安全文件名顯示 ===")
for filename in test_filenames:
display = safe_filename_display(filename)
print(f"原始: {filename!r} → 顯示: {display}")三、高級處理技術(shù)與策略
3.1 使用surrogateescape錯誤處理程序
Python的surrogateescape錯誤處理程序是一種高級技術(shù),允許保留無法解碼的字節(jié)信息:
def demonstrate_surrogateescape():
"""
演示surrogateescape錯誤處理程序的使用
"""
# 創(chuàng)建包含無效UTF-8字節(jié)的文件名
original_bytes = b'file_with_\xff\xfe_invalid_bytes.txt'
print("=== surrogateescape 演示 ===")
print(f"原始字節(jié): {original_bytes}")
# 使用surrogateescape解碼
decoded_with_escape = original_bytes.decode('utf-8', errors='surrogateescape')
print(f"解碼后: {decoded_with_escape!r}")
print(f"解碼長度: {len(decoded_with_escape)}")
# 檢查代理字符
for i, char in enumerate(decoded_with_escape):
if '\udc00' <= char <= '\udcff':
print(f"位置 {i}: 代理字符 {ord(char):04x}")
# 重新編碼恢復(fù)原始字節(jié)
try:
reencoded = decoded_with_escape.encode('utf-8', errors='surrogateescape')
print(f"重新編碼: {reencoded}")
print(f"匹配原始: {reencoded == original_bytes}")
except Exception as e:
print(f"重新編碼錯誤: {e}")
# 運行演示
demonstrate_surrogateescape()3.2 智能編碼檢測與恢復(fù)
import chardet
from pathlib import Path
class SmartFilenameDecoder:
"""
智能文件名解碼器,結(jié)合多種策略
"""
def __init__(self):
self.common_encodings = [
'utf-8', 'gbk', 'gb2312', 'shift_jis',
'euc-jp', 'iso-8859-1', 'windows-1252'
]
def decode_with_fallback(self, byte_filename):
"""
使用多種策略嘗試解碼文件名
"""
# 策略1: 嘗試系統(tǒng)默認(rèn)編碼
try:
return byte_filename.decode(sys.getfilesystemencoding()), 'system'
except UnicodeDecodeError:
pass
# 策略2: 嘗試常見編碼
for encoding in self.common_encodings:
try:
decoded = byte_filename.decode(encoding)
# 簡單驗證:檢查是否包含可打印字符
if any(c.isprintable() for c in decoded):
return decoded, encoding
except UnicodeDecodeError:
continue
# 策略3: 使用chardet自動檢測
try:
detection = chardet.detect(byte_filename)
if detection['confidence'] > 0.6:
decoded = byte_filename.decode(detection['encoding'])
return decoded, f"detected:{detection['encoding']}"
except:
pass
# 策略4: 使用替代表示
hex_repr = byte_filename.hex()
if len(hex_repr) > 30:
hex_repr = hex_repr[:30] + "..."
return f"<undecodable:{hex_repr}>", 'hex'
def safe_list_directory(self, directory_path):
"""
安全地列出目錄內(nèi)容,處理編碼問題
"""
directory = Path(directory_path)
results = []
try:
with directory.open('rb') as dir_fd:
# 使用底層接口獲取原始文件名
for entry_bytes in os.listdir(dir_fd):
decoded, method = self.decode_with_fallback(entry_bytes)
results.append((decoded, method, entry_bytes))
except Exception as e:
print(f"列出目錄錯誤: {e}")
return []
return results
# 使用示例
decoder = SmartFilenameDecoder()
test_dir = "/tmp" # 替換為測試目錄
print("=== 智能目錄列表 ===")
entries = decoder.safe_list_directory(test_dir)
for name, method, raw_bytes in entries[:10]: # 顯示前10個
print(f"{name:40} [方法: {method:15}] 原始: {raw_bytes!r}")四、實戰(zhàn)應(yīng)用案例
4.1 文件管理器中的安全顯示
class SafeFileManager:
"""
安全的文件管理器,處理編碼問題
"""
def __init__(self):
self.decoder = SmartFilenameDecoder()
def display_directory_tree(self, root_path, max_depth=3):
"""
安全地顯示目錄樹結(jié)構(gòu)
"""
root = Path(root_path)
def _display_tree(current_path, current_depth=0, prefix=""):
if current_depth > max_depth:
return
try:
# 安全獲取目錄內(nèi)容
with current_path.open('rb') as dir_fd:
entries = []
for entry_bytes in os.listdir(dir_fd):
decoded, method, _ = self.decoder.decode_with_fallback(entry_bytes)
entries.append((decoded, current_path / entry_bytes))
# 排序:目錄在前,文件在后
entries.sort(key=lambda x: (not x[1].is_dir(), x[0].lower()))
for i, (display_name, full_path) in enumerate(entries):
is_last = i == len(entries) - 1
# 當(dāng)前行的前綴
current_prefix = prefix + ("└── " if is_last else "├── ")
if full_path.is_dir():
# 目錄顯示
print(f"{current_prefix}{display_name}/")
# 遞歸顯示子目錄
new_prefix = prefix + (" " if is_last else "│ ")
_display_tree(full_path, current_depth + 1, new_prefix)
else:
# 文件顯示
try:
size = full_path.stat().st_size
size_str = f" ({size} bytes)"
except:
size_str = " (無法獲取大小)"
print(f"{current_prefix}{display_name}{size_str}")
except PermissionError:
print(f"{prefix}└── [權(quán)限拒絕]")
except Exception as e:
print(f"{prefix}└── [錯誤: {e}]")
print(f"{root_path}/")
_display_tree(root)
def safe_file_operation(self, operation_func, *args):
"""
安全的文件操作包裝器
"""
try:
return operation_func(*args)
except UnicodeError as e:
print(f"編碼錯誤: {e}")
# 嘗試使用字節(jié)路徑重試
byte_args = []
for arg in args:
if isinstance(arg, (str, Path)):
try:
byte_args.append(str(arg).encode(sys.getfilesystemencoding()))
except UnicodeEncodeError:
byte_args.append(str(arg).encode('utf-8', errors='replace'))
else:
byte_args.append(arg)
try:
return operation_func(*byte_args)
except Exception as retry_error:
print(f"重試失敗: {retry_error}")
raise
# 使用示例
file_manager = SafeFileManager()
file_manager.display_directory_tree("/path/to/directory") # 替換為實際路徑4.2 日志系統(tǒng)中的安全文件名記錄
import logging
from datetime import datetime
class EncodingAwareLogger:
"""
支持編碼問題文件名的日志系統(tǒng)
"""
def __init__(self, log_file=None):
self.decoder = SmartFilenameDecoder()
# 配置日志
self.logger = logging.getLogger(__name__)
self.logger.setLevel(logging.INFO)
# 清除現(xiàn)有處理器
self.logger.handlers.clear()
# 控制臺輸出
console_handler = logging.StreamHandler()
console_formatter = logging.Formatter('%(levelname)s: %(message)s')
console_handler.setFormatter(console_formatter)
self.logger.addHandler(console_handler)
# 文件輸出(如果提供)
if log_file:
try:
file_handler = logging.FileHandler(log_file, encoding='utf-8')
file_formatter = logging.Formatter(
'%(asctime)s - %(levelname)s - %(message)s'
)
file_handler.setFormatter(file_formatter)
self.logger.addHandler(file_handler)
except Exception as e:
self.logger.error(f"無法創(chuàng)建日志文件: {e}")
def log_file_operation(self, operation, path, success=True, additional_info=None):
"""
記錄文件操作日志,安全處理文件名
"""
# 安全處理路徑顯示
if isinstance(path, bytes):
display_path, method = self.decoder.decode_with_fallback(path)
encoding_info = f" [編碼: {method}]"
else:
display_path = str(path)
encoding_info = ""
# 構(gòu)建日志消息
status = "成功" if success else "失敗"
message = f"文件{operation} {status}: {display_path}{encoding_info}"
if additional_info:
message += f" | {additional_info}"
if success:
self.logger.info(message)
else:
self.logger.warning(message)
def log_directory_scan(self, directory_path, file_count, error_count):
"""
記錄目錄掃描結(jié)果
"""
display_path = safe_filename_display(directory_path)
self.logger.info(
f"目錄掃描完成: {display_path} | "
f"文件: {file_count} | 錯誤: {error_count}"
)
# 使用示例
def demo_logging():
"""日志系統(tǒng)演示"""
logger = EncodingAwareLogger("file_operations.log")
# 模擬各種文件操作
test_operations = [
("讀取", "正常文件.txt", True),
("寫入", "中文文件.txt".encode('gbk'), True),
("刪除", b'invalid_\xff\xfe_file.txt', False),
]
for operation, path, success in test_operations:
logger.log_file_operation(operation, path, success)
logger.log_directory_scan("/tmp", 150, 3)
demo_logging()五、底層文件系統(tǒng)接口
5.1 使用原始文件描述符
import os
import errno
class LowLevelFileHandler:
"""
底層文件系統(tǒng)接口,繞過Python的文件名解碼
"""
def __init__(self):
self.decoder = SmartFilenameDecoder()
def raw_list_directory(self, directory_path):
"""
使用原始文件描述符列出目錄
"""
try:
# 獲取目錄的文件描述符
dir_fd = os.open(directory_path, os.O_RDONLY)
entries = []
try:
# 讀取目錄內(nèi)容(原始字節(jié))
with os.fdopen(dir_fd, 'rb') as f:
# 注意:這種方法在不同系統(tǒng)上可能表現(xiàn)不同
raw_entries = f.read()
# 簡單的目錄條目解析(簡化版)
# 實際實現(xiàn)需要處理系統(tǒng)特定的目錄格式
pointer = 0
while pointer < len(raw_entries):
# 嘗試解析目錄條目(這是一個簡化示例)
# 實際實現(xiàn)需要處理具體的文件系統(tǒng)格式
try:
# 假設(shè)條目以null字節(jié)結(jié)尾
null_pos = raw_entries.find(b'\x00', pointer)
if null_pos == -1:
break
entry_bytes = raw_entries[pointer:null_pos]
if entry_bytes: # 非空條目
entries.append(entry_bytes)
pointer = null_pos + 1
except:
break
except Exception as e:
os.close(dir_fd)
raise e
return entries
except OSError as e:
if e.errno == errno.EACCES:
print("權(quán)限拒絕")
elif e.errno == errno.ENOENT:
print("目錄不存在")
else:
print(f"系統(tǒng)錯誤: {e}")
return []
def safe_file_operations(self, directory_path):
"""
安全的文件操作演示
"""
print(f"=== 底層目錄列表: {directory_path} ===")
# 獲取原始目錄條目
raw_entries = self.raw_list_directory(directory_path)
for entry_bytes in raw_entries:
try:
# 嘗試解碼顯示
display_name, method = self.decoder.decode_with_fallback(entry_bytes)
print(f"條目: {display_name} [方法: {method}]")
# 可以在這里進(jìn)行文件操作,使用entry_bytes作為路徑
# 例如:stat操作
try:
full_path = os.path.join(directory_path, entry_bytes)
stat_info = os.stat(full_path)
print(f" 大小: {stat_info.st_size} bytes")
except OSError as e:
print(f" 無法獲取信息: {e}")
except Exception as e:
print(f"處理條目失敗: {e}")
print(f"原始字節(jié): {entry_bytes.hex()}")
# 使用示例(注意:需要測試環(huán)境)
# handler = LowLevelFileHandler()
# handler.safe_file_operations("/tmp")5.2 跨平臺兼容的底層訪問
def cross_platform_low_level():
"""
跨平臺兼容的底層文件訪問策略
"""
strategies = []
# 策略1: 使用os.scandir的字節(jié)能力(Python 3.5+)
if hasattr(os, 'scandir'):
def strategy_scandir(path):
entries = []
try:
with os.scandir(path) as it:
for entry in it:
# 獲取原始名稱(如果可用)
if hasattr(entry, 'name_bytes'):
entries.append(entry.name_bytes)
else:
# 回退到字符串編碼
entries.append(entry.name.encode(sys.getfilesystemencoding()))
except Exception as e:
print(f"scandir錯誤: {e}")
return entries
strategies.append(('os.scandir', strategy_scandir))
# 策略2: 使用os.listdir的字節(jié)形式
def strategy_listdir_bytes(path):
try:
dir_fd = os.open(path, os.O_RDONLY)
try:
return os.listdir(dir_fd)
finally:
os.close(dir_fd)
except Exception as e:
print(f"listdir字節(jié)錯誤: {e}")
return []
strategies.append(('os.listdir(bytes)', strategy_listdir_bytes))
# 策略3: 使用pathlib的原始接口
def strategy_pathlib_raw(path):
try:
path_obj = Path(path)
entries = []
for entry in path_obj.iterdir():
# 嘗試獲取原始名稱
try:
entries.append(str(entry.name).encode(sys.getfilesystemencoding()))
except:
entries.append(str(entry.name).encode('utf-8', errors='replace'))
return entries
except Exception as e:
print(f"pathlib錯誤: {e}")
return []
strategies.append(('pathlib', strategy_pathlib_raw))
return strategies
# 策略測試
def test_strategies(directory_path):
"""
測試不同的底層訪問策略
"""
print("=== 底層訪問策略比較 ===")
strategies = cross_platform_low_level()
results = {}
for name, strategy in strategies:
try:
entries = strategy(directory_path)
results[name] = {
'count': len(entries),
'success': True,
'sample': entries[:3] if entries else []
}
except Exception as e:
results[name] = {
'count': 0,
'success': False,
'error': str(e)
}
# 顯示結(jié)果
for name, result in results.items():
status = "成功" if result['success'] else f"失敗: {result['error']}"
print(f"{name:20}: {status} | 條目數(shù): {result['count']}")
if result['success'] and result['sample']:
print(f" 樣例: {result['sample'][:3]}")
# 測試(需要實際目錄路徑)
# test_strategies("/tmp")六、生產(chǎn)環(huán)境最佳實踐
健壯的文件名處理框架
class ProductionReadyFilenameHandler:
"""
生產(chǎn)環(huán)境使用的文件名處理器
"""
def __init__(self, config=None):
self.config = config or {
'default_encoding': sys.getfilesystemencoding(),
'fallback_encodings': ['utf-8', 'gbk', 'shift_jis', 'iso-8859-1'],
'max_hex_display': 20,
'enable_caching': True,
'cache_size': 1000
}
self.decoder = SmartFilenameDecoder()
self.cache = {} if self.config['enable_caching'] else None
def safe_display(self, filename, context="display"):
"""
安全地顯示文件名,根據(jù)上下文調(diào)整策略
"""
cache_key = None
if self.cache is not None and isinstance(filename, bytes):
cache_key = filename.hex()
if cache_key in self.cache:
return self.cache[cache_key]
if isinstance(filename, bytes):
# 字節(jié)文件名處理
try:
# 首先嘗試默認(rèn)編碼
decoded = filename.decode(self.config['default_encoding'])
result = decoded
except UnicodeDecodeError:
# 嘗試備選編碼
for encoding in self.config['fallback_encodings']:
try:
decoded = filename.decode(encoding)
# 基本驗證
if any(c.isprintable() for c in decoded):
result = f"{decoded} ({encoding})"
break
except UnicodeDecodeError:
continue
else:
# 所有編碼都失敗
hex_str = filename.hex()
if len(hex_str) > self.config['max_hex_display']:
hex_str = hex_str[:self.config['max_hex_display']] + "..."
if context == "debug":
result = f"<undecodable: {hex_str}>"
else:
result = f"<invalid_filename>"
else:
# 字符串文件名
result = str(filename)
# 緩存結(jié)果
if cache_key is not None:
if len(self.cache) >= self.config['cache_size']:
self.cache.clear() # 簡單的緩存清理策略
self.cache[cache_key] = result
return result
def batch_process(self, file_list, processor_func):
"""
批量處理文件列表,帶有錯誤處理
"""
results = []
errors = []
for file_path in file_list:
try:
# 安全顯示用于日志
display_name = self.safe_display(file_path, "log")
# 處理文件
result = processor_func(file_path)
results.append((file_path, result, None))
except UnicodeError as e:
# 編碼錯誤
error_info = {
'type': 'encoding_error',
'message': str(e),
'bytes': file_path.hex() if isinstance(file_path, bytes) else None
}
errors.append((file_path, None, error_info))
except OSError as e:
# 文件系統(tǒng)錯誤
error_info = {
'type': 'os_error',
'errno': e.errno,
'message': str(e)
}
errors.append((file_path, None, error_info))
except Exception as e:
# 其他錯誤
error_info = {
'type': 'other_error',
'message': str(e)
}
errors.append((file_path, None, error_info))
return {
'successful': results,
'failed': errors,
'success_rate': len(results) / len(file_list) if file_list else 0
}
# 使用示例
def demo_production_handler():
"""生產(chǎn)環(huán)境處理器演示"""
handler = ProductionReadyFilenameHandler()
# 測試文件列表
test_files = [
"normal_file.txt",
"中文文件.txt".encode('gbk'),
"日本語.txt".encode('shift_jis'),
b'invalid_\xff\xfe_bytes.txt',
"another_normal.py"
]
# 簡單的處理器函數(shù)
def simple_processor(filepath):
return f"processed_{safe_filename_display(filepath)}"
# 批量處理
results = handler.batch_process(test_files, simple_processor)
print("=== 批量處理結(jié)果 ===")
print(f"成功率: {results['success_rate']:.1%}")
print(f"成功: {len(results['successful'])}")
print(f"失敗: {len(results['failed'])}")
print("\n失敗詳情:")
for file_path, result, error in results['failed']:
display = handler.safe_display(file_path)
print(f" {display}: {error['type']} - {error['message']}")
demo_production_handler()總結(jié)
處理無法解碼的文件名是Python文件處理中的一個高級但至關(guān)重要的技能。通過本文的探討,我們了解了問題的根源、各種解決方案以及在實際環(huán)境中的應(yīng)用策略。
??關(guān)鍵要點總結(jié):??
1.??問題復(fù)雜性??:文件名編碼問題源于操作系統(tǒng)、文件系統(tǒng)和區(qū)域設(shè)置的差異
2.??多層次解決方案??:
- 基礎(chǔ):使用
errors參數(shù)控制解碼行為 - 中級:實現(xiàn)編碼檢測和回退機制
- 高級:使用代理轉(zhuǎn)義和底層文件系統(tǒng)接口
??3.生產(chǎn)環(huán)境考慮??:需要健壯的錯誤處理、日志記錄和性能優(yōu)化
4.??跨平臺兼容性??:不同操作系統(tǒng)需要不同的處理策略
??最佳實踐建議:??
- 始終假設(shè)文件名可能包含編碼問題
- 實現(xiàn)多層次的錯誤處理和恢復(fù)策略
- 在生產(chǎn)環(huán)境中使用安全的顯示和日志記錄方法
- 考慮性能影響,適當(dāng)使用緩存和批量處理
- 測試各種邊緣情況,包括混合編碼和完全無效的字節(jié)序列
通過掌握這些技術(shù)和最佳實踐,開發(fā)者可以構(gòu)建出能夠正確處理各種文件名編碼問題的健壯應(yīng)用程序,為用戶提供更好的體驗并減少維護(hù)負(fù)擔(dān)。
以上就是一文詳解Python如何處理無法解碼文件名的詳細(xì)內(nèi)容,更多關(guān)于Python解碼文件名的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Golang HTTP請求Json響應(yīng)解析方法以及解讀失敗的原因
這篇文章主要介紹了Golang HTTP請求Json響應(yīng)解析方法以及解讀失敗的原因,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
Go語言使用goroutine及通道實現(xiàn)并發(fā)詳解
這篇文章主要為大家介紹了Go語言使用goroutine及通道實現(xiàn)并發(fā)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08

