C#에서 텍스트 파일을 구문 분석하는 가장 좋은 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/13963

  •  08-06-2019
  •  | 
  •  

문제

다음과 같이 구성 파일을 구문 분석하고 싶습니다.

[KEY:Value]     
    [SUBKEY:SubValue]

이제 나는 StreamReader, 라인을 문자 배열로 변환하는 중 더 나은 방법이 있을 것이라고 생각했습니다.그래서 나는 겸손한 독자 여러분에게 도움을 요청합니다.

한 가지 제한 사항은 Linux/Mono 환경(정확히는 1.2.6)에서 작동해야 한다는 것입니다.최신 2.0 릴리스(Mono)가 없으므로 언어 ​​기능을 C# 2.0 또는 C# 1.0으로 제한해 보세요.

도움이 되었습니까?

해결책

고려했지만 XML을 사용하지 않을 것입니다.나는 이 내용을 손으로 작성할 예정인데, XML을 손으로 편집하면 머리가 아프게 됩니다.:')

봤어? YAML?

모든 어려움 없이 XML의 이점을 얻을 수 있습니다.구성 파일, 미리 준비된 데이터베이스 데이터 등과 같은 작업을 위해 Ruby 커뮤니티에서 광범위하게 사용됩니다.

여기에 예가 있습니다

customer:
  name: Orion
  age: 26
  addresses:
    - type: Work
      number: 12
      street: Bob Street
    - type: Home
      number: 15
      street: Secret Road

다음이 있는 것으로 보입니다. C# 라이브러리는 여기, 나는 개인적으로 사용하지 않았지만 Yaml은 매우 간단하므로 "얼마나 힘들 수 있습니까?" :-)

나는 자신만의 임시 형식을 만드는 것(그리고 파서 버그를 다루는 것)보다 이것이 더 낫다고 말하고 싶습니다.

다른 팁

나는 지난번에 거의 이 정확한 문제를 보고 있었습니다. 이 기사 문자열 토큰화는 정확히 필요한 것입니다.토큰을 다음과 같이 정의하고 싶을 것입니다:

@"(?&ltlevel>\s) | " +
@"(?&ltterm>[^:\s]) | " +
@"(?&ltseparator>:)"

기사는 그것을 설명하는 데 꽤 좋은 역할을 합니다.거기에서 적절하다고 생각되는 대로 토큰을 먹기 시작합니다.

유용한 팁:대한 LL(1) 파서 (읽다:쉬움) 토큰은 접두사를 공유할 수 없습니다.당신이 가지고 있다면 abc 토큰으로는 ace 토큰으로

메모:이 기사는 | 그 예에서 캐릭터를 던지십시오.

있다 .NET용 또 다른 YAML 라이브러리 개발중인 것입니다.현재는 YAML 스트림 읽기를 지원하며 Windows 및 Mono에서 테스트되었습니다.쓰기 지원은 현재 구현 중입니다.

라이브러리를 사용하는 것은 거의 항상 자신만의 라이브러리를 사용하는 것보다 바람직합니다.다음은 나중에 당신을 괴롭히게 될 "아, 난 절대 필요하지 않을 거야/그건 생각하지 않았어"에 대한 간단한 목록입니다.

  • 이스케이프 문자.원하는 경우:키에 ]가 있나요? 아니면 값에 ]가 있나요?
  • 이스케이프 문자를 이스케이프합니다.
  • 유니코드
  • 탭과 공백의 혼합(Python의 공백 구분 구문 문제 참조)
  • 다양한 반환 문자 형식 처리
  • 구문 오류 보고 처리

다른 사람들이 제안한 것처럼 YAML이 최선의 선택인 것 같습니다.

스택을 사용하고 푸시/팝 알고리즘을 사용할 수도 있습니다.이것은 열기/닫기 태그와 일치합니다.

public string check()
    {
        ArrayList tags = getTags();


        int stackSize = tags.Count;

        Stack stack = new Stack(stackSize);

        foreach (string tag in tags)
        {
            if (!tag.Contains('/'))
            {
                stack.push(tag);
            }
            else
            {
                if (!stack.isEmpty())
                {
                    string startTag = stack.pop();
                    startTag = startTag.Substring(1, startTag.Length - 1);
                    string endTag = tag.Substring(2, tag.Length - 2);
                    if (!startTag.Equals(endTag))
                    {
                        return "Fout: geen matchende eindtag";
                    }
                }
                else
                {
                    return "Fout: geen matchende openeningstag";
                }
            }
        }

        if (!stack.isEmpty())
        {
            return "Fout: geen matchende eindtag";
        }            
        return "Xml is valid";
    }

파일의 내용을 읽을 수 있도록 조정할 수도 있습니다.정규 표현식도 좋은 생각입니다.

비교적 쉽게 정보를 읽고 저장할 수 있는 .NET 클래스가 이미 있으므로 XML 기반 구성 파일을 사용하는 것이 더 나을 것 같습니다.이것이 불가능한 이유가 있습니까?

@남자 이름: XML을 직접 편집하는 것이 지루한 것은 사실이지만, 여러분이 제시하는 구조는 이미 XML과 매우 유사해 보입니다.

그렇다면 좋은 방법이 있습니다.

@기슈

실제로 이스케이프 문자를 수용한 후에 내 정규식은 내 손으로 작성한 하향식 재귀 파서보다 약간 느리게 실행되었으며 이는 중첩(하위 항목을 상위 항목에 연결) 및 손으로 쓴 파서 보고 오류가 없었습니다.

정규 표현식은 작성 속도가 약간 더 빨랐지만(비록 수동 파서에 대한 경험이 약간 있음) 오류 보고 기능이 좋지 않습니다.이를 추가하면 수행하기가 약간 더 어려워지고 길어집니다.

또한 손으로 쓴 파서가 의도를 더 쉽게 이해할 수 있다고 생각합니다.예를 들어 다음은 코드 조각입니다.

private static Node ParseNode(TextReader reader)
{
    Node node = new Node();
    int indentation = ParseWhitespace(reader);
    Expect(reader, '[');
    node.Key = ParseTerminatedString(reader, ':');
    node.Value = ParseTerminatedString(reader, ']');
}

지속되는 형식에 관계없이 Regex를 사용하는 것이 가장 빠른 구문 분석 방법입니다.Ruby에서는 아마도 몇 줄의 코드일 것입니다.

\[KEY:(.*)\] 
\[SUBKEY:(.*)\]

이 두 가지는 첫 번째 그룹의 Value 및 SubValue를 가져옵니다.문자열과 정규식을 일치시키는 방법에 대해서는 MSDN을 확인하세요.

이것은 모든 사람이 고양이에게 가지고 있어야 할 것입니다.정규식 이전 시대는 빙하 시대처럼 보일 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top