0

我正在尝试编写一个读取大文件的解析器,尝试在包含更多寄存器的行上定位 XYZ 值,而不仅仅是 XYZ(如 M 代码和其他驱动 CNC 机器的命令)。

我成功地阅读了代码并从每一行中分离了数据。现在我被困在一个函数中,该函数应该分析这个处理过的块并查找 XY 和 Z 坐标,不一定按这个顺序,不一定包含所有 3 个轴。

好消息是轴名称总是在给定轴的值之前,所以即使线可能有 XYZ 乱序(例如 ZYX 或 YZX),或者只有 X 和 Y 而没有 Z,轴的字母是总是在值之前。

我需要提取每个轴的值并对其进行处理,然后将其保存回来。我可以处理并将其保存回来,但我不知道如何编写一个可以解析 XY 和 Z 的函数,即使它们无序或缺少寄存器(即 Z 不存在于块中, 或 Y, 或 X)。

我只想提取传递给函数ParseAndChangeNCBlocks的字符串strNewLine中的 XYZ 值,并忽略该行中的所有其他内容。

这是我的代码:

Imports System.IO

Module Module1

    Public DebugMode As Boolean = True

    Sub Main()

        Dim path As String = "C:\8888.nc"

        ' This text is added only once to the file.
        If File.Exists(path) = False Then

            ' Create a file to write to.
            Dim createText() As String = {"Hello", "And", "Welcome"}
            File.WriteAllLines(path, createText)
        End If

        ' This text is always added, making the file longer over time
        ' if it is not deleted.
        Dim appendText As String = "This is extra text" + Environment.NewLine
        File.AppendAllText(path, appendText)

        ' Open the file to read from.
        Dim NCProgram() As String = File.ReadAllLines(path)
        Dim NCBlock As String
        For Each NCBlock In NCProgram
            Console.WriteLine(CleanUpAndSeparateBlocks(NCBlock))
        Next
    End Sub

    Function CleanUpAndSeparateBlocks(ByVal NCBlock As String) As String
        Dim strBlockLength As Integer = 0       'Comprimento do bloco
        Dim strNewLine As String = ""           'Linha tratada
        Dim strMotionText = ""                  'Parte anterior ao comentário
        Dim strCommentText = ""                 'Comentário do bloco
        Dim intCommentStartIndex As Integer = 0 'Index inicial do comentário
        Dim intCommentEndIndex As Integer = 0   'Index final do comentário
        Dim intCommentLength As Integer = 0     'Comprimento do comentário

        strNewLine = NCBlock.Trim               'Remove blanks esq/dir
        strNewLine = strNewLine.ToUpper         'Converte pra maiúsculas

        intCommentStartIndex = strNewLine.IndexOf("(") 'Armazena o início do comentário
        intCommentEndIndex = strNewLine.IndexOf(")")   'Armazena o fim do comentário

        If intCommentStartIndex > -1 And intCommentEndIndex > -1 Then    'Se um comentário for detectado
            strBlockLength = strNewLine.Length                           'Captura o comprimento do bloco
            strCommentText = strNewLine.Remove(0, intCommentStartIndex)  'Remove a string anterior ao seu início
            strCommentText = strCommentText.Trim                         'Remove blanks esq/dir
            strMotionText = strNewLine.Remove(intCommentStartIndex, strBlockLength - intCommentStartIndex) 'Separa a parte anterior ao comentário
            strMotionText = strMotionText.Trim                           'Remove blanks esq/dir
            strMotionText = strMotionText.Replace(Chr(32), "")           'Remove blanks do meio da string
            strNewLine = strMotionText + Chr(32) + strCommentText        'Forma o novo bloco

            If DebugMode = True Then                                     'Se depuração estiver ativa
                MsgBox(strNewLine)                                       'Exibe a nova linha 
            End If

        Else                                                             'Bloco não contém comentários
            strNewLine = strNewLine.Replace(Chr(32), "")                 'Remove blanks do meio da string
        End If

        ParseAndChangeNCBlocks(strNewLine)                               'Converte coordenadas para interpolação cilíndrica

        Return strNewLine
    End Function

    Function ParseAndChangeNCBlocks(ByVal NCBlock As String) As String
        Dim XCoord As Double = 0
        Dim YCoord As Double = 0
        Dim ZCoord As Double = 0


        Return NCBlock
    End Function

End Module

函数 CleanUpAndSeparateBlocks结束时,我调用ParseAndChangeNCBlocks。最后一个是我应该分析已传递给函数的字符串并开始提取每个轴的函数。

我想过用它来提取每个值:在这里找到它:VB.net Set x,y,z values from text file into separate arrays

Dim values As String() = line.Split(","c)
Dim x As Integer = Integer.Parse(values(0))
Dim y As Integer = Integer.Parse(values(1))
Dim z As Integer = Integer.Parse(values(2))

但是,此解决方案假定 XYZ 始终按此顺序排列,并且它们前面没有轴名称,在我的情况下,轴名称总是出现,但是轴可能无序显示,甚至没有出现在行中。

这里有一些要在“C:\8888.nc”中使用的测试数据

%
o8888(usinagem helice)   
g00g21g40g80g99 
g49 
g69.1 
m05 
m46 
m246
m45 
n10 g28u0.
n20 g28w0.
n30 g28h0.
n40 g330 
n50 (#5222=0)
n60 g7.1y0. 
n70 m69
n80 m46
n90 g98g18 
n100 m45

n110 (desbasta perfil - parte 1)

n120 t1025
n130 g361b0d0 
n140 g43h25.
n150 g54
n160 s3714m13 

n170 g01z440.#0.x13.258y-276.689f10000.
n180 g19w0h0
n190 g1 y-276.689
n200 g7.1y188.
n210 g01z376.

n220 goto 2843850 (jump to contour finish - using cutcom and cylindrical interpolation)

n230 g03 x7.809 y-271.766 r87.496
n240 g01 x7.804 y-271.758 f1485.
n250 y-271.756
n260 x7.846 y-271.75
n270 x7.902 y-271.743
n280 x7.974 y-271.734
n290 x8.064 y-271.725
n300 x8.175 y-271.713
n310 x8.311 y-271.701
n320 x8.477 y-271.688
n330 x8.68 y-271.673
n340 x8.927 y-271.656
n350 x9.232 y-271.639
n360 x9.613 y-271.62
n370 x10.097 y-271.6
n380 x10.69 y-271.581
n390 x11.284 y-271.566
n400 x11.879 y-271.554
n410 x12.055 y-271.551
n420 x12.449 y-271.553
n430 x12.837 y-271.573
n440 x13.207 y-271.61
n450 x13.55 y-271.664
n460 x13.856 y-271.731
n470 x14.118 y-271.812
n480 x14.328 y-271.903
n490 x14.48 y-272.002
n500 x14.571 y-272.107
n510 g03 x13.711 y-272.547 r1.606 f10000.
n520 x7.804 y-271.758 r4.1
n530 g01 x7.78 y-271.714 f1485.
n540 z100. x7.779 y-271.711
n550 x7.835 y-271.7
n560 x7.898 y-271.687
n570 x7.972 y-271.674
n580 Z200. x8.052 y-271.659

我只想提取每行的 X、Y、Z 值,无论它们出现的顺序或组合(XYZ、Z、YX 或 Y 等)如何。有人可以阐明我如何构造函数ParseAndChangeNCBlocks来做到这一点吗?

非常感谢!

4

3 回答 3

2

使用正则表达式很容易做到这一点。您只需要制定一个匹配数字的正则表达式,然后根据需要在其前面加上 x、y 或 z:

Imports System.Text.RegularExpressions

Module Module1

    Function ExtractAndOrderXYZ(s As String) As String
        Dim num = "([+-]?[0-9.]+)" ' regex to match a number

        Dim xMatch = Regex.Match(s, "x" & num, RegexOptions.IgnoreCase)
        Dim yMatch = Regex.Match(s, "y" & num, RegexOptions.IgnoreCase)
        Dim zMatch = Regex.Match(s, "z" & num, RegexOptions.IgnoreCase)

        Dim orderedString = ""

        If xMatch.Success Then
            orderedString = xMatch.Captures(0).Value
        End If

        If yMatch.Success Then
            orderedString &= yMatch.Captures(0).Value
        End If

        If zMatch.Success Then
            orderedString &= zMatch.Captures(0).Value
        End If

        Return orderedString

    End Function

    Sub Main()
        ' Following line outputs x13.258y-276.689z440.
        Console.WriteLine(ExtractAndOrderXYZ("n170 g01z440.#0.x13.258y-276.689f10000."))

        ' Following line outputs y-276.689
        Console.WriteLine(ExtractAndOrderXYZ("n190 g1 y-276.689"))

        ' Following line outputs x7.809y-271.766
        Console.WriteLine(ExtractAndOrderXYZ("n230 g03 x7.809 y-271.766 r87.496"))

        Console.ReadLine()

    End Sub

End Module

在 regex([+-]?[0-9.]+)中,括号指示要捕获的内容。[+-]?表示可选符号,[0-9.]+表示一位或多位数字或小数点。

于 2015-12-26T09:23:52.100 回答
0

试试这个从一行中获取 X 值。你可以对 y 和 z 做同样​​的事情

function getX(byval line as string) as string 
 Dim val as String = ""

 if(line.indexOf("X") >= 0) 
      val = line.subString(line.indexOf("X") + 1)
      val = val.subString(0, val.indexOf(" ")
end if
return val 

end function 
于 2015-12-26T07:48:39.810 回答
0

你可以这样做。代码中的注释。

Function ParseAndChangeNCBlocks(ByVal NCBlock As String) As String
    Dim XCoord As Double = 0
    Dim YCoord As Double = 0
    Dim ZCoord As Double = 0
    Dim values As String() = NCBlock.Split(" "c)
    'iterate through each item and check what char it starts with
    For Each value As String In values
        If value.StartsWith("x") Then
            XCoord = Val(value.Substring(1))
        ElseIf value.StartsWith("y") Then
            YCoord = Val(value.Substring(1))
        ElseIf value.StartsWith("z") Then
            ZCoord = Val(value.Substring(1))
        End If
    Next
    'Do all your calculation here for the x y z 

    'don't know what return you want
    'this just puts it back in the order
    Return String.Format("x{0} y{1} z{2}", XCoord, YCoord, ZCoord)
End Function

注意:如果您希望 xyz 的大小写字母,那么您应该使用如下比较。

value.StartsWith("x", StringComparison.InvariantCultureIgnoreCase)
于 2015-12-26T07:51:11.317 回答