декодировать файловый поток с использованием UTF-8 - PullRequest
6 голосов
/ 18 мая 2009

У меня есть XML-документ, который очень большой (около 120 МБ), и я не хочу загружать его в память сразу. Моя цель - проверить, использует ли этот файл правильную кодировку UTF-8.

Есть идеи провести быструю проверку, не считывая весь файл в память в виде byte[]?

Я использую VSTS 2008 и C #.

При использовании XMLDocument для загрузки XML-документа, который содержит недопустимые байтовые последовательности, возникает исключение, но при чтении всего содержимого в байтовый массив и последующей проверке на соответствие UTF-8, нет никаких исключений, есть идеи?

Вот снимок экрана, показывающий содержимое моего XML-файла, или вы можете скачать копию файла с здесь

enter image description here

РЕДАКТИРОВАТЬ 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;
    }
}

РЕДАКТИРОВАТЬ 2: При использовании new UTF8Encoding(true, true) будет исключение, но при использовании new UTF8Encoding(false, true) исключение не выдается. Я запутался, потому что это должен быть 2-й параметр, который контролирует, генерируется ли исключение (если есть недопустимые последовательности байтов), почему 1-й параметр имеет значение?

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

    }

Ответы [ 3 ]

6 голосов
/ 18 мая 2009
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 ;
    }
}
3 голосов
/ 18 мая 2009

@ George2 Я думаю, что они имеют в виду решение, подобное следующему (которое я не проверял).

Обработка перехода между буферами (т.е. кэширование дополнительных байтов / частичных символов между операциями чтения) - это ответственность и детали внутренней реализации реализации 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 голосов
/ 19 марта 2012

Это не сработает?

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();

Если нет, то кто-нибудь может помочь объяснить, почему?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...