Path.Combine容易被忽略的细节

Path.Combine这个方法是很常用的一个方法,通常用它来拼接路径。尤其是存在对路径有跨平台的场景,更应该使用它来处理路径拼接。

那Path.Combine会存在怎么样的一个问题呢?


private class TestClass
{
  public void Test()
  {
    var result= Path.Combine("C:\Users\Desktop\tmp","/image.png")
  }
}

以上代码中 result 结果会是什么呢?

result = C:\Users\Desktop\tmp/image.png 吗?

实际上,结果是 /image.png。

为什么会这样子?

看下微软的注解:

        此方法旨在将单个字符串连接到表示文件路径的单个字符串中。但是,    如果第一个以外的参数包含根路径,则忽略以前的任何路径组件,并且返回    的字符串以该根路径组件开头。 作为 方法的 Combine 替代方法,请考虑    使用 Join 或 TryJoin 方法。

有这段注解应该就很好理解了,因为我们需要拼接的字符串中,以/或'\'开头,那么它将忽略前面的参数。

所以我们在处理路径拼接的时候,一定要注意下这种场景,它会导致隐藏的BUG。

import os import math from datetime import datetime, date from openpyxl import load_workbook, Workbook from openpyxl.drawing.image import Image as OpenpyxlImage from openpyxl.styles import Font # ================== 配置路径 ================== folder_path = r'D:\Class\能管比对\导出文件_月' folder_path2 = r'D:\Class\能管比对\导出文件合并' output_result = r'D:\Class\能管比对\每日结果\高变异列_CV大于0.3_整列分析.xlsx' # 创建输出目录 os.makedirs(os.path.dirname(output_result), exist_ok=True) # 获取今天零点时间用于过滤 today = datetime.combine(date.today(), datetime.min.time()) # ========== 第一阶段:清洗数据并保存到 folder_path2 ========== processed_count = 0 for filename in os.listdir(folder_path): if not filename.endswith('.xlsx') or filename.startswith('~$'): continue src_file = os.path.join(folder_path, filename) dst_file = os.path.join(folder_path2, filename) try: wb = load_workbook(src_file) ws = wb.active data = [list(row) for row in ws.iter_rows(values_only=True)] if len(data) <= 1: continue header, rows = data[0], data[1:] cleaned_rows = [header] # 保留表头 for row in rows: if not row: continue cell_val = row[0] try: # 统一解析为 datetime 类型 if isinstance(cell_val, datetime): dt = cell_val else: # 处理字符串格式如 '2025/4/1' 或 '2025-04-01' str_val = str(cell_val).strip() dt = datetime.fromisoformat(str_val.replace('/', '-')) if dt >= today: continue # 排除今天及以后的数据 except Exception: continue # 解析失败则跳过该行 cleaned_rows.append(row) # 保存清洗后的数据 new_wb = Workbook() new_ws = new_wb.active for r in cleaned_rows: new_ws.append(r) new_wb.save(dst_file) processed_count += 1 except Exception as e: print(f"⚠️ 处理 {filename} 时出错:{e}") print(f"✅ 共清洗并保存了 {processed_count} 个文件") # ========== 第二阶段:分析 CV > 0.3 的列,并记录图像来源 ========== results = [] image_sources = [] for filename in os.listdir(folder_path2): if not filename.endswith('.xlsx') or filename.startswith('~$'): continue file_path = os.path.join(folder_path2, filename) filename_no_ext = os.path.splitext(filename)[0] png_path = os.path.join(folder_path2, f"{filename_no_ext}.png") try: wb = load_workbook(file_path) data = [list(row) for row in wb.active.iter_rows(values_only=True)] if len(data) < 2: continue header, rows = data[0], data[1:] # 提取各列数值数据 col_data = [[] for _ in header] for row in rows: for i, v in enumerate(row): try: col_data[i].append(float(v)) except (TypeError, ValueError): pass # 非数值跳过 # 分析第2列开始(索引1起)的变异系数 for idx, col_name in enumerate(header[1:], start=1): vals = col_data[idx] n = len(vals) if n < 2: continue mean_val = sum(vals) / n if abs(mean_val) < 1e-8: # 避免除以0 continue variance = sum((x - mean_val) ** 2 for x in vals) / n std_val = math.sqrt(variance) cv = std_val / mean_val if cv > 0.3: max_val = max(vals) min_val = min(vals) # 构建待添加项 item = { '来源文件': filename_no_ext, '列名': col_name, '有效数据点数': n, '均值': round(mean_val, 6), '标准差': round(std_val, 6), '变异系数(CV)': round(cv, 6), '最大值': round(max_val, 6), '最小值': round(min_val, 6) } # === 特殊列白名单过滤逻辑 === # 替换原来的 if 判断 col_name_clean = str(col_name).strip() # 确保转字符串并去空格 if ( ('1st DI耗用量' in col_name_clean and max_val <= 1500) # ('CCoolingTower用水量' in col_name_clean and max_val <= 15000) or # ('低温热水系统' in col_name_clean and max_val <= 300000) ): continue # 跳过这些“伪异常” results.append(item) image_sources.append({ 'source_file': filename, 'png_path': png_path, 'exists': os.path.exists(png_path) }) except Exception as e: print(f"⚠️ 分析 {filename} 时出错:{e}") # ========== 第三阶段:生成最终结果 Excel ========== if results: result_wb = Workbook() sheet1 = result_wb.active sheet1.title = "高变异列数据" sheet1.append(list(results[0].keys())) for r in results: sheet1.append(list(r.values())) # 第二个工作表:展示图表 sheet2 = result_wb.create_sheet("对应图表展示") sheet2.cell(row=1, column=1, value="来源文件") sheet2.cell(row=1, column=2, value="图表展示") current_row = 2 inserted_images_count = 0 seen_files = set() # 去重,避免重复插入同一文件图表 for item in image_sources: source_file = item['source_file'] if source_file in seen_files: continue seen_files.add(source_file) # 写入来源文件名(A列) sheet2.cell(row=current_row, column=1, value=os.path.splitext(source_file)[0]) # 插入图片或错误提示(B列) if item['exists']: try: img = OpenpyxlImage(item['png_path']) img.width *= 0.5 # 缩放图片防止过大 img.height *= 0.5 sheet2.add_image(img, f'B{current_row}') inserted_images_count += 1 height_in_rows = int(img.height / 15) + 3 # 动态调整行高 except Exception as e: sheet2.cell(row=current_row, column=2, value=f"❌ 加载失败: {e}") sheet2.cell(row=current_row, column=2).font = Font(color="FF0000", size=9) height_in_rows = 5 else: sheet2.cell(row=current_row, column=2, value="❌ 图像未找到") sheet2.cell(row=current_row, column=2).font = Font(italic=True, color="888888", size=9) height_in_rows = 5 # 设置当前区域行高 for i in range(current_row, current_row + height_in_rows): sheet2.row_dimensions[i].height = 15 current_row += height_in_rows # 设置列宽 sheet2.column_dimensions['A'].width = 50 sheet2.column_dimensions['B'].width = 80 # 保存最终结果 result_wb.save(output_result) print(f"\n✅ 分析完成!共 {len(results)} 个高变异列已保存至:\n {output_result}") print(f"📊 共尝试插入 {len(seen_files)} 张图像,成功插入 {inserted_images_count} 张。") else: print("\n🟡 未发现变异系数大于 0.3 的列。") ——这里的特殊白名单过滤逻辑是什么
11-26
private SiffEntity ReadToSiffEntity(FileInfo fileInfo) { SiffEntity siffentity = new SiffEntity(); string testprogram_pattern = @"Device Name *: (\S*)"; string lotno_pattern = @"(Lot No.|LotNo) *: ([0-9A-Z]*)"; string waferid_pattern = @"Wafer ID *: \S*-(\d{2})"; string flat_pattern = @"Flat/Notch *: (\w*)"; string operator_pattern = @"Operator Id *: (.*)"; string probercard_pattern = @"Card Id *: (.*)"; string loadboard_pattern = @"Tester id *: (.*)"; string station_pattern = @"Probe id *: (.*)"; string measuretime_pattern = @"Testing Finish *: (.*)"; using(FileStream fs = new FileStream(fileInfo.FullName,FileMode.Open,FileAccess.Read,FileShare.Read)) using(StreamReader reader = new StreamReader(fs)) { while (!reader.EndOfStream) { var lineContent = reader.ReadLine(); if (Regex.IsMatch(lineContent, testprogram_pattern, RegexOptions.IgnoreCase)) siffentity.TestProgram = Regex.Match(lineContent, testprogram_pattern, RegexOptions.IgnoreCase).Groups[1].ToString(); else if (Regex.IsMatch(lineContent, lotno_pattern, RegexOptions.IgnoreCase)) siffentity.Lot = Regex.Match(lineContent, lotno_pattern, RegexOptions.IgnoreCase).Groups[2].ToString(); else if (Regex.IsMatch(lineContent, waferid_pattern, RegexOptions.IgnoreCase)) siffentity.WaferNumber = Regex.Match(lineContent, waferid_pattern, RegexOptions.IgnoreCase).Groups[1].ToString(); else if (Regex.IsMatch(lineContent, flat_pattern, RegexOptions.IgnoreCase)) siffentity.FlatOrientation = Regex.Match(lineContent, flat_pattern, RegexOptions.IgnoreCase).Groups[1].ToString(); else if (Regex.IsMatch(lineContent, operator_pattern, RegexOptions.IgnoreCase)) siffentity.Operator = Regex.Match(lineContent, operator_pattern, RegexOptions.IgnoreCase).Groups[1].ToString(); else if (Regex.IsMatch(lineContent, probercard_pattern, RegexOptions.IgnoreCase)) siffentity.ProbeCard = Regex.Match(lineContent, probercard_pattern, RegexOptions.IgnoreCase).Groups[1].ToString(); else if (Regex.IsMatch(lineContent, loadboard_pattern, RegexOptions.IgnoreCase)) siffentity.LoadBoard = Regex.Match(lineContent, loadboard_pattern, RegexOptions.IgnoreCase).Groups[1].ToString(); else if (Regex.IsMatch(lineContent, station_pattern, RegexOptions.IgnoreCase)) siffentity.Station = Regex.Match(lineContent, station_pattern, RegexOptions.IgnoreCase).Groups[1].ToString(); else if (Regex.IsMatch(lineContent, measuretime_pattern, RegexOptions.IgnoreCase)) { string measureTimeString = Regex.Match(lineContent, measuretime_pattern, RegexOptions.IgnoreCase).Groups[1].ToString(); if (measureTimeString.Length == 14) { siffentity.MeasureTime = ("20" + measureTimeString).Replace(" ", "_").Replace("-", "/")+":00"; } else if (measureTimeString.Length == 17) { siffentity.MeasureTime = ("20" + measureTimeString).Replace(" ", "_").Replace("-", "/"); } else if (measureTimeString.Length == 16) { siffentity.MeasureTime = measureTimeString.Replace(" ", "_").Replace("-", "/") + ":00"; } else { siffentity.MeasureTime = (measureTimeString).Replace(" ", "_").Replace("-", "/"); } } else if (!lineContent.Contains(":")) { if (siffentity.BinDefinition == null) { string bindefFile = Path.Combine(BinDefinitionFolder, string.Format("{0} Jade Bin Definiton.csv", siffentity.Product.Substring(0, 4))); siffentity.BinDefinition = ReadBinDefinition(bindefFile); } StringBuilder sb = new StringBuilder(); foreach (var c in lineContent) { string cString = c.ToString(); if (siffentity.BinDefinition.Keys.Contains(cString)) { string binNum = siffentity.BinDefinition[cString].BinNumber; if (siffentity.BinSummary.ContainsKey(binNum)) { siffentity.BinSummary[binNum]++; } else { siffentity.BinSummary.Add(binNum, 1); } sb.Append(binNum); } else if (NoValueDieCharArray.Contains(cString)) { sb.Append(SiffEntity.NoValueDie); } else if (NoDieCharArray.Contains(cString)) { sb.Append(SiffEntity.NoDie); } else { string binNumber = GetBinNumber(cString); if (!binNumber.Equals("")) { //定义为出现在Bindef中的Bin BinDef binDef = new BinDef() { BinName = cString, BinSpec = "B", BinNumber = binNumber, Description = cString + "?" }; siffentity.BinDefinition.Add(cString, binDef); siffentity.BinSummary.Add(binNumber, 1); sb.Append(binNumber); } } } siffentity.WaferMapStr.Add(sb.ToString()); } } } return siffentity; } 详解上述代码
最新发布
11-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷眼Σ(-᷅_-᷄๑)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值