Управление сервером FileUpload и символы Юникода - PullRequest
4 голосов
/ 16 марта 2011

Я использую серверный элемент управления FileUpload для загрузки HTML-документа, ранее сохраненного (как веб-страница; отфильтрованного) из MS Word. Кодировка Windows-1252. Документ имеет умные кавычки (фигурные), а также обычные кавычки. В нем также есть некоторые пробелы (по-видимому), которые при глубоком рассмотрении представляют собой символы, отличные от обычных символов TAB или SPACE.

При захвате содержимого файла в StreamReader эти специальные символы переводятся в вопросительные знаки. Я предполагаю, потому что по умолчанию используется кодировка UTF-8, а файл - Unicode.

Я продолжил и создал StreamReader, используя кодировку Unicode, затем заменил все ненужные символы на правильные (код, который я фактически нашел в stackoverflow). Кажется, это работает .... просто я не могу преобразовать строку обратно в UTF-8, чтобы отобразить ее в asp: literal. Код есть, он должен работать .... но вывод (ConvertToASCII) не читается.

Пожалуйста, смотрите ниже:

    protected void btnUpload_Click(object sender, EventArgs e)
    {
        StreamReader sreader;
        if (uplSOWDoc.HasFile)
        {
            try
            {
                if (uplSOWDoc.PostedFile.ContentType == "text/html" || uplSOWDoc.PostedFile.ContentType == "text/plain")
                {
                    sreader = new StreamReader(uplSOWDoc.FileContent, Encoding.Unicode);
                    string sowText = sreader.ReadToEnd();
                    sowLiteral.Text = ConvertToASCII(sowText);
                    lblUploadResults.Text = "File loaded successfully.";
                }
                else
                    lblUploadResults.Text = "Upload failed. Just text or html files are allowed.";
            }
            catch(Exception ex)
            {
                lblUploadResults.Text = ex.Message;
            }
        }
    }

    private string ConvertToASCII(string source)
    {
        if (source.IndexOf('\u2013') > -1) source = source.Replace('\u2013', '-');
        if (source.IndexOf('\u2014') > -1) source = source.Replace('\u2014', '-');
        if (source.IndexOf('\u2015') > -1) source = source.Replace('\u2015', '-');
        if (source.IndexOf('\u2017') > -1) source = source.Replace('\u2017', '_');
        if (source.IndexOf('\u2018') > -1) source = source.Replace('\u2018', '\'');
        if (source.IndexOf('\u2019') > -1) source = source.Replace('\u2019', '\'');
        if (source.IndexOf('\u201a') > -1) source = source.Replace('\u201a', ',');
        if (source.IndexOf('\u201b') > -1) source = source.Replace('\u201b', '\'');
        if (source.IndexOf('\u201c') > -1) source = source.Replace('\u201c', '\"');
        if (source.IndexOf('\u201d') > -1) source = source.Replace('\u201d', '\"');
        if (source.IndexOf('\u201e') > -1) source = source.Replace('\u201e', '\"');
        if (source.IndexOf('\u2026') > -1) source = source.Replace("\u2026", "...");
        if (source.IndexOf('\u2032') > -1) source = source.Replace('\u2032', '\'');
        if (source.IndexOf('\u2033') > -1) source = source.Replace('\u2033', '\"');


        byte[] sourceBytes = Encoding.Unicode.GetBytes(source);
        byte[] targetBytes = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, sourceBytes);
        char[] asciiChars = new char[Encoding.ASCII.GetCharCount(targetBytes, 0, targetBytes.Length)];
        Encoding.ASCII.GetChars(targetBytes, 0, targetBytes.Length, asciiChars, 0);

        string result = new string(asciiChars);

        return result;

    }

Кроме того, как я уже говорил, есть еще несколько "прозрачных" символов, которые, кажется, соответствуют тому, где слово doc имеет отступ нумерации, и я понятия не имею, как зафиксировать их значение в Юникоде, чтобы заменить их .... у вас есть какие-либо советы, пожалуйста, дайте мне знать.

Большое спасибо заранее !!

Ответы [ 2 ]

6 голосов
/ 17 марта 2011
sreader = new StreamReader(uplSOWDoc.FileContent, Encoding.Unicode);

Поздравляем, вы - один миллионный кодер, которого укусил «Encoding.Unicode».

Не существует такого понятия, как «кодировка Unicode».Unicode - это набор символов, который имеет много разных кодировок.

Encoding.Unicode на самом деле является специфической кодировкой UTF-16LE, в которой символы кодируются как UTF-16 «кодовые единицы», а затем каждый 16-битный код.Единица записывается в байтах в порядке байтов.Это собственный формат строки Unicode в памяти для Windows NT, но вы почти никогда не захотите использовать его для чтения или записи файлов.Будучи кодированием по 2 байта на единицу, он не совместим с ASCII и не очень эффективен для хранения или в сети.

В наши дни UTF-8 - это гораздо более распространенная кодировка, используемая дляТекст в Юникоде.Но неправильное название Microsoft UTF-16LE как «Unicode» продолжает сбивать с толку и вводить в заблуждение пользователей, которые просто хотят «поддерживать Unicode».Поскольку Encoding.Unicode является не-ASCII-совместимой кодировкой, попытка чтения файлов в кодировке ASCII-надмножества (такой как UTF-8 или кодовая страница Windows по умолчанию, такая как 1252 Western European) создаст огромный неразборчивый беспорядок всего, нетолько не-ASCII символы.

В этом случае кодировка вашего файла хранится в кодовой странице Windows 1252. Так что прочитайте ее с помощью:

sreader= new StreamReader(uplSOWDoc.FileContent, Encoding.GetEncoding(1252));

Я бы оставил это на этом,Не пытайтесь «конвертировать в ASCII».Эти умные кавычки - очень хорошие символы и должны поддерживаться как любой другой символ Unicode;если у вас возникают проблемы с отображением умных кавычек, вы, вероятно, также искали все остальные символы, не входящие в ASCII.Лучше всего решить проблему, из-за которой это происходит, а не пытаться избегать ее лишь в нескольких распространенных случаях.

6 голосов
/ 16 марта 2011

Согласно StreamReader на MSDN :

Объект StreamReader пытается обнаружить кодировку, просматривая первые три байта потока.Он автоматически распознает UTF-8, Unicode с прямым порядком байтов и Unicode с прямым порядком байтов, если файл начинается с соответствующих меток порядка байтов.В противном случае используется предоставляемая пользователем кодировка.

Поэтому, если ваш загруженный файл charset равен windows-1252, то ваша строка:

sreader = new StreamReader(uplSOWDoc.FileContent, Encoding.Unicode);

неверна, так как файлсодержимое не в кодировке Unicode.Вместо этого используйте:

sreader = new StreamReader(uplSOWDoc.FileContent, 
                  Encoding.GetEncoding("Windows-1252"), true);

, где последний логический параметр предназначен для обнаружения спецификации .

...