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() { return Encoding.GetEncoding(Gb2312CodePage); } private readonly record struct DrillTapeLine(string Text, string LineEnding); } }