diff --git a/App.xaml.cs b/App.xaml.cs index d7b2f21..bf033df 100644 --- a/App.xaml.cs +++ b/App.xaml.cs @@ -34,7 +34,8 @@ namespace DrillTools // 防止选择窗口关闭后触发 OnLastWindowClose 导致应用退出 ShutdownMode = ShutdownMode.OnExplicitShutdown; - var selectionWindow = new StartupSelectionWindow(filePath); + bool canClearParameters = CanClearDrillTapeParameters(filePath); + var selectionWindow = new StartupSelectionWindow(filePath, canClearParameters); selectionWindow.ShowDialog(); switch (selectionWindow.SelectedAction) @@ -47,6 +48,10 @@ namespace DrillTools PerformHeadlessExport(filePath); Shutdown(); break; + case StartupAction.ClearParameters: + PerformParameterCleanup(filePath); + Shutdown(); + break; default: Shutdown(); break; @@ -97,6 +102,37 @@ namespace DrillTools } } + private static bool CanClearDrillTapeParameters(string filePath) + { + try + { + string content = CommandTypeFileReader.ReadAllText(filePath); + return DrillTapeParameterCleaner.CanClearParameters(content); + } + catch + { + return false; + } + } + + private static void PerformParameterCleanup(string filePath) + { + try + { + DrillTapeParameterCleaner.ClearParametersAndSave(filePath); + System.Windows.MessageBox.Show( + $"参数已清空,原文件已备份为:\n{Path.GetFileName(filePath)}.bak", + "清空参数完成", + MessageBoxButton.OK, + MessageBoxImage.Information); + } + catch (Exception ex) + { + System.Windows.MessageBox.Show($"清空参数失败:\n{ex.Message}", + "错误", MessageBoxButton.OK, MessageBoxImage.Error); + } + } + /// /// 验证是否为有效的钻带文件 /// diff --git a/DrillTapeParameterCleaner.cs b/DrillTapeParameterCleaner.cs new file mode 100644 index 0000000..a43d782 --- /dev/null +++ b/DrillTapeParameterCleaner.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; + +namespace DrillTools +{ + internal static class DrillTapeParameterCleaner + { + private const int Gb2312CodePage = 936; + private static readonly char[] LineEndChars = { '\r', '\n' }; + private static readonly Regex HeaderToolDefinitionStartPattern = new( + @"^T\d+C", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex ToolDefinitionPattern = new( + @"^(?\s*T\d+C\d+(?:\.\d+)?)(?H.+)$", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + + public static bool CanClearParameters(string drillTapeContent) + { + var lines = SplitLines(drillTapeContent); + if (lines.Count < 2) + return false; + + string secondLine = lines[1].Text.Trim(); + if (!secondLine.StartsWith(";") || secondLine.Length == 1) + return false; + + var toolDefinitionLines = GetHeaderToolDefinitionLines(lines); + if (toolDefinitionLines.Count == 0) + return false; + + foreach (var line in toolDefinitionLines) + { + if (!ToolDefinitionPattern.IsMatch(line.Text.TrimEnd())) + return false; + } + + return true; + } + + public static string ClearParameters(string drillTapeContent) + { + if (!CanClearParameters(drillTapeContent)) + throw new InvalidOperationException("钻带文件不符合清空参数条件"); + + var lines = SplitLines(drillTapeContent); + var builder = new StringBuilder(drillTapeContent.Length); + + for (int i = 0; i < lines.Count; i++) + { + if (i == 1) + continue; + + string text = lines[i].Text; + var match = ToolDefinitionPattern.Match(text.TrimEnd()); + if (match.Success && IsBeforeHeaderEnd(lines, i)) + { + int trailingWhitespaceLength = text.Length - text.TrimEnd().Length; + string trailingWhitespace = trailingWhitespaceLength > 0 ? text[^trailingWhitespaceLength..] : string.Empty; + text = match.Groups["prefix"].Value + trailingWhitespace; + } + + builder.Append(text); + builder.Append(lines[i].LineEnding); + } + + return builder.ToString(); + } + + public static void ClearParametersAndSave(string filePath) + { + string content = CommandTypeFileReader.ReadAllText(filePath); + string cleanedContent = ClearParameters(content); + + string backupFilePath = filePath + ".bak"; + File.Copy(filePath, backupFilePath, true); + + using var writer = new StreamWriter(filePath, false, CreateAnsiEncoding()); + writer.Write(cleanedContent); + } + + private static List SplitLines(string content) + { + var lines = new List(); + int index = 0; + + while (index < content.Length) + { + int lineEndIndex = content.IndexOfAny(LineEndChars, index); + if (lineEndIndex < 0) + { + lines.Add(new DrillTapeLine(content[index..], string.Empty)); + return lines; + } + + string text = content[index..lineEndIndex]; + string lineEnding; + if (content[lineEndIndex] == '\r' && lineEndIndex + 1 < content.Length && content[lineEndIndex + 1] == '\n') + { + lineEnding = "\r\n"; + index = lineEndIndex + 2; + } + else + { + lineEnding = content[lineEndIndex].ToString(); + index = lineEndIndex + 1; + } + + lines.Add(new DrillTapeLine(text, lineEnding)); + } + + if (content.Length == 0) + lines.Add(new DrillTapeLine(string.Empty, string.Empty)); + + return lines; + } + + private static List GetHeaderToolDefinitionLines(IReadOnlyList lines) + { + var toolDefinitionLines = new List(); + + foreach (var line in lines) + { + string trimmedLine = line.Text.Trim(); + if (trimmedLine == "%") + break; + + if (HeaderToolDefinitionStartPattern.IsMatch(trimmedLine)) + toolDefinitionLines.Add(line); + } + + return toolDefinitionLines; + } + + private static bool IsBeforeHeaderEnd(IReadOnlyList lines, int lineIndex) + { + for (int i = 0; i < lineIndex; i++) + { + if (lines[i].Text.Trim() == "%") + return false; + } + + return true; + } + + private static Encoding CreateAnsiEncoding() + { + try + { + return Encoding.GetEncoding(Gb2312CodePage); + } + catch + { + return Encoding.Default; + } + } + + private readonly record struct DrillTapeLine(string Text, string LineEnding); + } +} diff --git a/StartupSelectionWindow.xaml b/StartupSelectionWindow.xaml index a4192df..b002d92 100644 --- a/StartupSelectionWindow.xaml +++ b/StartupSelectionWindow.xaml @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="选择功能" - Width="300" + Width="430" SizeToContent="Height" ResizeMode="NoResize" WindowStartupLocation="CenterScreen"> @@ -18,7 +18,8 @@