2008-08-17 5 views
9

Tôi muốn phân tích một sorta điều tập tin cấu hình, như vậy:Phương pháp phân tích cú pháp textfile tốt nhất trong C#?

[KEY:Value]  
    [SUBKEY:SubValue] 

Bây giờ tôi bắt đầu với một StreamReader, chuyển đổi dòng vào mảng ký tự, khi tôi tìm có phải là người ngồi một cách tốt hơn. Vì vậy, tôi hỏi bạn, người đọc khiêm tốn, để giúp tôi.

Một hạn chế là nó phải hoạt động trong môi trường Linux/Mono (chính xác là 1.2.6). Tôi không có bản phát hành 2.0 mới nhất (của Mono), vì vậy hãy thử hạn chế các tính năng ngôn ngữ đối với C# 2.0 hoặc C# 1.0.

Trả lời

12

Tôi đã xem xét nó, nhưng tôi sẽ không sử dụng XML. Tôi sẽ viết những thứ này bằng tay, và việc chỉnh sửa bằng tay XML làm cho bộ não của tôi bị tổn thương. : ')

Bạn đã xem YAML chưa?

Bạn nhận được lợi ích của XML mà không phải chịu mọi đau đớn và đau khổ. Nó được sử dụng rộng rãi trong cộng đồng ruby ​​cho những thứ như tập tin cấu hình, dữ liệu cơ sở dữ liệu trước khi chuẩn bị, vv

đây là một ví dụ

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

Có dường như là một C# library here, mà tôi đã không sử dụng cá nhân, nhưng yaml là khá đơn giản, vì vậy "khó khăn như thế nào nó có thể được?":-)

tôi muốn nói đó là thích hợp hơn để phát minh ra định dạng ad-hoc của riêng bạn (và đối phó với lỗi phân tích cú pháp)

0

Dường như với tôi rằng bạn nên sử dụng tệp cấu hình dựa trên XML vì đã có các lớp .NET có thể đọc và lưu trữ thông tin cho bạn một cách tương đối dễ dàng. Có lý do nào mà điều này là không thể?

@Bernard: Đúng là việc chỉnh sửa bằng tay XML là tẻ nhạt, nhưng cấu trúc mà bạn đang trình bày trông rất giống với XML.

Sau đó, có, có phương pháp tốt ở đó.

0

Bạn cũng có thể sử dụng ngăn xếp và sử dụng thuật toán đẩy/bật. Điều này phù hợp với thẻ mở/đóng.

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"; 
    } 

Bạn có thể thích ứng để bạn có thể đọc nội dung tệp của mình. Cụm từ thông dụng cũng là một ý tưởng hay.

4

Tôi đã xem xét gần như vấn đề chính xác này vào ngày khác: this article trên chuỗi mã hóa chính xác là những gì bạn cần. Bạn sẽ muốn xác định mã thông báo của mình như một cái gì đó như:

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

Bài viết thực hiện một công việc khá tốt để giải thích. Từ đó bạn chỉ cần bắt đầu ăn lên thẻ như bạn thấy phù hợp.

Protip: Đối với số LL(1) parser (đọc: dễ), mã thông báo không thể chia sẻ tiền tố. Nếu bạn có abc làm mã thông báo, bạn không thể có ace làm mã thông báo

Lưu ý: Bài viết bị thiếu | trong các ví dụ của nó, chỉ cần ném chúng vào.

1

Sử dụng một thư viện là hầu như luôn luôn tốt để cán của riêng bạn. Dưới đây là danh sách những "Ồ, tôi sẽ không bao giờ cần điều đó/Tôi không nghĩ về điều đó" những điểm sẽ kết thúc sau đó sẽ cắn bạn sau đó xuống dòng:

  • Ký tự thoát. Điều gì sẽ xảy ra nếu bạn muốn: trong khóa hoặc ] trong giá trị?
  • Thoát ký tự thoát.
  • Unicode
  • Mix các tab và không gian (xem vấn đề với cú pháp nhạy cảm không gian trắng của Python)
  • Xử lý các định dạng nhân vật khác nhau trở lại
  • Xử lý lỗi cú pháp báo cáo

Giống như những người khác đã gợi ý, YAML trông giống như bạn đặt cược tốt nhất.

-1

Bất kể định dạng kéo dài, sử dụng Regex sẽ là cách phân tích cú pháp nhanh nhất. Trong ruby ​​nó có lẽ sẽ là một vài dòng mã.

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

Hai giá trị này sẽ mang lại cho bạn Giá trị và SubValue trong nhóm đầu tiên. Kiểm tra MSDN trên làm thế nào để phù hợp với một regex chống lại một chuỗi.

Đây là điều mà mọi người nên có trong con mèo của họ. Pre-Regex ngày có vẻ như Ice Age.

0

@Gishu

Trên thực tế một khi tôi đã cung cấp chỗ ở cho các ký tự thoát regex của tôi chạy hơi chậm hơn so với viết tay đầu của tôi xuống đệ quy phân tích cú pháp và đó là nếu không có sự làm tổ (liên kết tiểu mục cho cha mẹ của họ) và báo cáo lỗi các tay phân tích cú pháp đã có.

Regex nhanh hơn một chút để viết (mặc dù tôi có một chút kinh nghiệm với các trình phân tích cú pháp tay) nhưng không có báo cáo lỗi tốt. Một khi bạn thêm rằng nó sẽ trở nên khó khăn hơn và lâu hơn để làm.

Tôi cũng tìm thấy trình phân tích cú pháp viết tay dễ hiểu hơn. Ví dụ: đây là đoạn mã:

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

another YAML library for .NET đang được phát triển. Ngay bây giờ nó hỗ trợ đọc các luồng YAML và đã được thử nghiệm trên Windows và Mono. Hỗ trợ viết hiện đang được triển khai.