прочитать строку Юникода из текстового файла в приложении UWP

в приложении Windows 10 я пытаюсь прочитать строку из файла .txt и установить текст в RichEditBox:

Вариант кода 1:

var read = await FileIO.ReadTextAsync(file, Windows.Storage.Streams.UnicodeEncoding.Utf8);
txt.Document.SetText(Windows.UI.Text.TextSetOptions.None, read);

Вариант кода 2:

var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
ulong size = stream.Size;
using (var inputStream = stream.GetInputStreamAt(0))
{
    using (var dataReader = new Windows.Storage.Streams.DataReader(inputStream))
    {
        dataReader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
        uint numBytesLoaded = await dataReader.LoadAsync((uint)size);
        string text = dataReader.ReadString(numBytesLoaded);
        txt.Document.SetText(Windows.UI.Text.TextSetOptions.FormatRtf, text);
    }
}

В некоторых файлах у меня есть эта ошибка: «В целевой многобайтовой кодовой странице нет сопоставления для символа Unicode».

Я нашел одно решение:

IBuffer buffer = await FileIO.ReadBufferAsync(file);
DataReader reader = DataReader.FromBuffer(buffer);
byte[] fileContent = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(fileContent);
string text = Encoding.UTF8.GetString(fileContent, 0, fileContent.Length);
txt.Document.SetText(Windows.UI.Text.TextSetOptions.None, text);

Но с этим кодом текст выглядит как вопросительные знаки в ромбе.

Как я могу читать и отображать одни и те же текстовые файлы в обычной кодировке?


person SYL    schedule 09.02.2016    source источник
comment
Вы уверены, что ваш текст закодирован в UTF8?   -  person TGlatzer    schedule 09.02.2016
comment
Нет. Это строка Unicode в кодовой странице 1251 или 1252. Как я думаю   -  person SYL    schedule 10.02.2016


Ответы (2)


Проблема здесь заключается в кодировании, и это зависит от того, какая точность вам нужна для вашего приложения. Если вам нужно что-то быстрое и простое, вы можете адаптировать этот ответ

    public static Encoding GetEncoding(byte[4] bom)
    {
        // Analyze the BOM
        if (bom[0] == 0x2b && bom[1] == 0x2f && bom[2] == 0x76) return Encoding.UTF7;
        if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf) return Encoding.UTF8;
        if (bom[0] == 0xff && bom[1] == 0xfe) return Encoding.Unicode; //UTF-16LE
        if (bom[0] == 0xfe && bom[1] == 0xff) return Encoding.BigEndianUnicode; //UTF-16BE
        if (bom[0] == 0 && bom[1] == 0 && bom[2] == 0xfe && bom[3] == 0xff) return Encoding.UTF32;
        return Encoding.ASCII;
    }

    async System.Threading.Tasks.Task MyMethod()
    {
        FileOpenPicker openPicker = new FileOpenPicker();
        StorageFile file = await openPicker.PickSingleFileAsync();
        IBuffer buffer = await FileIO.ReadBufferAsync(file);
        DataReader reader = DataReader.FromBuffer(buffer);
        byte[] fileContent = new byte[reader.UnconsumedBufferLength];
        reader.ReadBytes(fileContent);
        string text = GetEncoding(new byte[4] {fileContent[0], fileContent[1], fileContent[2], fileContent[3] }).GetString(fileContent);
        txt.Document.SetText(Windows.UI.Text.TextSetOptions.None, text);

        //.. 
    }

Если вам нужно что-то более точное, вам следует подумать о переносе на UWP переноса на .Net детектор набора символов Mozilla, как уже упоминалось в этом ответ

Обратите внимание, что приведенный выше код является всего лишь образцом, в нем отсутствуют все операторы использования для типов, реализующих IDisposable, и его также следует написать более последовательным образом.

чт -г

person Gian Paolo    schedule 10.02.2016
comment
Очень спасибо. Как вы говорите, я сделал UWP-порт детектора кодировки Mozilla. И используйте библиотеку Portable.Text.Encoding от NuGet. Работает идеально) - person SYL; 10.02.2016
comment
Я использую блокнот, сохраняю как ascii, и я не могу открыть его, когда использую ваш код, и весь текст? когда char китайский. - person lindexi; 12.07.2016
comment
Спасибо вам большое за это. Сэкономил много времени. - person Arwin; 30.09.2016

Решение:

1) Я сделал перенос Mozilla Universal Charset Detector на UWP (добавлен в Nuget)

ICharsetDetector cdet = new CharsetDetector();
cdet.Feed(fileContent, 0, fileContent.Length);
cdet.DataEnd();

2) Библиотека Nuget Portable.Text.Encoding

if (cdet.Charset != null)
string text = Portable.Text.Encoding.GetEncoding(cdet.Charset).GetString(fileContent, 0, fileContent.Length);

Это все. Теперь юникодные ecnodings (включая cp1251, cp1252) - работает хорошо ))

person SYL    schedule 12.02.2016