2009-05-18 29 views
6

Tôi có tài liệu XML, rất lớn (khoảng 120M) và tôi không muốn tải nó vào bộ nhớ cùng một lúc. Mục đích của tôi là kiểm tra xem tệp này có đang sử dụng mã hóa UTF-8 hợp lệ hay không.giải mã luồng tệp bằng UTF-8

Bất kỳ ý tưởng nào để kiểm tra nhanh mà không đọc toàn bộ tệp vào bộ nhớ dưới dạng byte[]?

Tôi đang sử dụng VSTS 2008 và C#.

Khi sử dụng XMLDocument để tải tài liệu XML, chứa chuỗi byte không hợp lệ, có ngoại lệ, nhưng khi đọc tất cả nội dung vào mảng byte và sau đó kiểm tra UTF-8, không có ngoại lệ, ý tưởng nào?

Đây là một ảnh chụp màn hình hiển thị nội dung của tập tin XML của tôi, hoặc bạn có thể tải về một bản sao của tập tin từ here

enter image description here

EDIT 1:

class Program 
{ 
    public static byte[] RawReadingTest(string fileName) 
    { 
     byte[] buff = null; 

     try 
     { 
      FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); 
      BinaryReader br = new BinaryReader(fs); 
      long numBytes = new FileInfo(fileName).Length; 
      buff = br.ReadBytes((int)numBytes); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 

     return buff; 
    } 

    static void XMLTest() 
    { 
     try 
     { 
      XmlDocument xDoc = new XmlDocument(); 
      xDoc.Load("c:\\abc.xml"); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
    } 

    static void Main() 
    { 
     try 
     { 
      XMLTest(); 
      Encoding ae = Encoding.GetEncoding("utf-8"); 
      string filename = "c:\\abc.xml"; 
      ae.GetString(RawReadingTest(filename)); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 

     return; 
    } 
} 

EDIT 2: Khi sử dụng new UTF8Encoding(true, true), sẽ có một ngoại lệ, nhưng khi sử dụng new UTF8Encoding(false, true), không có ví dụ lừa bịp. Tôi bối rối, bởi vì nó phải là tham số thứ 2 kiểm soát xem một ngoại lệ được ném (nếu có chuỗi byte không hợp lệ), tại sao tham số thứ nhất lại quan trọng?

public static void TestTextReader2() 
    { 
     try 
     { 
      // Create an instance of StreamReader to read from a file. 
      // The using statement also closes the StreamReader. 
      using (StreamReader sr = new StreamReader(
       "c:\\a.xml", 
       new UTF8Encoding(true, true) 
       )) 
      { 
       int bufferSize = 10 * 1024 * 1024; //could be anything 
       char[] buffer = new char[bufferSize]; 
       // Read from the file until the end of the file is reached. 
       int actualsize = sr.Read(buffer, 0, bufferSize); 
       while (actualsize > 0) 
       { 
        actualsize = sr.Read(buffer, 0, bufferSize); 
       } 
      } 
     } 
     catch (Exception e) 
     { 
      // Let the user know what went wrong. 
      Console.WriteLine("The file could not be read:"); 
      Console.WriteLine(e.Message); 
     } 

    } 
+0

Không phải hầu như bất kỳ chuỗi byte nào, ngay cả các giá trị byte ngẫu nhiên, UTF8 hợp lệ? Hoặc có một số chuỗi giá trị byte không phải là UTF8 hợp lệ không? – ChrisW

+1

Không phải tất cả, ngoại trừ một số ngoại lệ, vui lòng tham khảo tại đây, http://en.wikipedia.org/wiki/UTF-8#Invalid_code_points – George2

+1

@ChrisW: Tuyệt đối không; UTF-8 có các quy tắc mã hóa cụ thể. –

Trả lời

5
var buffer = new char[32768] ; 

using (var stream = new StreamReader (pathToFile, 
    new UTF8Encoding (true, true))) 
{ 
    while (true) 
    try 
    { 
     if (stream.Read (buffer, 0, buffer.Length) == 0) 
      return GoodUTF8File ; 
    } 
    catch (ArgumentException) 
    { 
     return BadUTF8File ; 
    } 
} 
+0

Nhưng nếu một ký tự sử dụng nhiều byte span span, bạn xử lý tình huống như thế nào? – George2

+1

@George - người đọc sẽ phân phối * các khối * đã giải mã, mà bạn chỉ cần loại bỏ. Nếu toàn bộ luồng giải mã thì nó hợp lệ. Không có câu hỏi về mã hóa * byte * mở rộng các khối * ký tự * bạn đọc. –

+0

@Software Monkey, tôi nhầm lẫn về ý bạn là "người đọc sẽ phân phối" - bạn có thể hiển thị đoạn mã của mình không? – George2

3

@ George2 Tôi nghĩ rằng họ có nghĩa là một giải pháp như sau (mà tôi đã không kiểm tra).

Xử lý chuyển đổi giữa các bộ đệm (tức là bộ đệm thêm byte/phần giữa các lần đọc) là trách nhiệm và chi tiết triển khai bên trong của việc triển khai StreamReader.

using System; 
using System.IO; 
using System.Text; 

class Test 
{ 
    public static void Main() 
    { 
     try 
     { 
      // Create an instance of StreamReader to read from a file. 
      // The using statement also closes the StreamReader. 
      using (StreamReader sr = new StreamReader(
       "TestFile.txt", 
       Encoding.UTF8 
       )) 
      { 
       const int bufferSize = 1000; //could be anything 
       char[] buffer = new char[bufferSize]; 
       // Read from the file until the end of the file is reached. 
       while (bufferSize == sr.Read(buffer, bufferSize, 0)) 
       { 
        //successfuly decoded another buffer's-worth of data 
       } 
      } 
     } 
     catch (Exception e) 
     { 
      // Let the user know what went wrong. 
      Console.WriteLine("The file could not be read:"); 
      Console.WriteLine(e.Message); 
     } 
    } 
} 
+0

@ChrisW, một lỗi nhỏ, Đọc (bộ đệm, bufferSize, 0), nên được đọc (bộ đệm, 0, bufferSize). :-) Một vấn đề khác là, tôi tìm thấy phương pháp của bạn và sử dụng XMLDocument.Load sẽ có kết quả khác nhau. Phương thức của bạn sẽ không bao giờ ném bất kỳ ngoại lệ nào ngay cả khi có các chuỗi byte không hợp lệ của UTF-8 trong tệp cơ bản (ví dụ: TestFile.txt), nhưng XMLDocument.Load sẽ ném ngoại lệ. Vui lòng tham khảo phần EDIT1 của bài đăng gốc của tôi. Bất kỳ ý tưởng gì là sai? – George2

+1

Tôi không biết (Tôi chỉ đưa ra một ví dụ mã để vẹt các đề xuất bên dưới). Bạn đang bắt ngoại lệ gì? Bạn có biết (độc lập) liệu UTF8 trong tệp có đúng không? Nếu bạn chắc chắn nó không chính xác, và mã ở trên không phải là không thành công, hãy thử chạy mã với Visual Studio thiết lập để bắt ngoại lệ khi họ đang ném, thay vì chỉ khi họ đang unhandled? Bởi vì có lẽ (mặc dù tôi sẽ không biết tại sao) việc thực hiện StreamReader âm thầm bắt bất kỳ trường hợp ngoại lệ mã hóa. – ChrisW

+0

@ChrisW, tệp XML của tôi rất đơn giản và nhỏ, nội dung là, http://i42.tinypic.com/wioc9c.jpg khi sử dụng XMLDocument.Tải, tệp xml sẽ được coi là mã hóa UTF-8 không hợp lệ, nhưng khi sử dụng phương pháp của bạn, nó sẽ được coi là mã hóa hợp lệ - không có ngoại lệ, bất kỳ ý tưởng nào? – George2

0

Điều này có hiệu quả không?

StreamReader reader = new StreamReader(file); 

Console.WriteLine(reader.CurrentEncoding.ToString()); //You get the default encoding 
reader.Read(); 

Console.WriteLine(reader.CurrentEncoding.ToString()); //You get the right encoding. 
reader.Close(); 

Nếu không ai đó có thể giúp giải thích lý do tại sao?

Các vấn đề liên quan