5 / 5 / 1
Регистрация: 11.10.2013
Сообщений: 415
1

Изменение кодировки

01.03.2018, 00:29. Показов 2574. Ответов 16
Метки нет (Все метки)

Здравствуйте. Имеется конструкция, которая производит чтение данных либо с текстового файла, либо с клавиатуры.
Возникло два вопроса:
1) Что надо изменить, чтобы при чтении из файла корректно читался русский язык?
2) Возможно, сможете помочь. Данная конструкция является частью программы по стеганографии. Если встраивается в аудио английский текст, то извлечение этого текста из аудио происходит корректно. Если же встраивается текст на русском языке, то происходит извлечение только лишь ровно половины спрятанного текста. В чем может быть проблема?

Код чтения с файла/с клавиатуры:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private Stream GetMessageStream()
        {
            BinaryWriter messageWriter = new BinaryWriter(new MemoryStream());
            if (rdoMsgFile.Checked)
            {  
                //чтение из файла
                var fs = new FileStream(txtMsgFile.Text, FileMode.Open);
                int fileLength = (int)fs.Length;
                messageWriter.Write(fileLength);
                byte[] buffer = new byte[fs.Length];
                fs.Read(buffer, 0, fileLength);
                messageWriter.Write(buffer);
                fs.Close();
            }
            else
            {
                //чтение с клавиатуры
                messageWriter.Write(txtMessage.Text.Length);
                messageWriter.Write(Encoding.UTF8.GetBytes(txtMessage.Text));
            }
            messageWriter.Seek(0, SeekOrigin.Begin);
            return messageWriter.BaseStream;
        }
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.03.2018, 00:29
Ответы с готовыми решениями:

Изменение кодировки .txt файла
Добрый вечер. Недавно начал переходить с Delphi на C#, и столкнулся с проблемой изменения...

Изменение кодировки создаваемого XML файла
Доброго времени суток. Столкнулся с проблемой. Не могу при создании XML файла сменить кодировку. ...

Изменение кодировки после извлечения из архива
Есть файл, его имя Спецификация, но на некоторых компах После того как этот файл извлекается из...

Изменение кодировки windows-1251 to ISO-8859-14
Доброе время суток. Нужно поменять кодировку строки : "òèï...

16
Администратор
Эксперт .NET
13861 / 11236 / 4570
Регистрация: 17.03.2014
Сообщений: 22,652
Записей в блоге: 1
01.03.2018, 00:53 2
Alex7676, ответ на второй вопрос очень простой. Данный код
Цитата Сообщение от Alex7676 Посмотреть сообщение
C#
1
2
messageWriter.Write(txtMessage.Text.Length);
messageWriter.Write(Encoding.UTF8.GetBytes(txtMessage.Text));
исходит из того что один символ кодируется одним байт. Это не так. В кодировке UTF-8 он может занимать от 1 до 4 байтов. Правильно будет так:
C#
1
2
3
var bytes = Encoding.UTF8.GetBytes(txtMessage.Text); 
messageWriter.Write(bytes.Length);
messageWriter.Write(bytes);
По первому вопросу я не вижу проблемы так как идет чтение байтов и текст на любом языке прочитается корректно.
1
5 / 5 / 1
Регистрация: 11.10.2013
Сообщений: 415
01.03.2018, 09:59  [ТС] 3
OwenGlendower, спасибо за ответ! Второй вопрос решился.
Но первый вопрос остался в силе.
Описание проблемы: на вход подается стандартный .txt файл, который может содержать в себе любой текст (числа, буквы английские, русские и т.д.). Извлечение русского текста, который был встроен в аудио файл, происходит некорректно - выдается в ответе не текст, а набор символов неизвестной кодировки.
Ошибку методов кодирования/раскодирования можно исключить, так как кодирование/раскодирование сообщения, которое подается с клавиатуры, происходит корректно.
Следовательно, необходимо внести какие - то изменения в эту часть кода:
C#
1
2
3
4
5
6
7
                var fs = new FileStream(txtMsgFile.Text, FileMode.Open);
                int fileLength = (int)fs.Length;
                messageWriter.Write(fileLength);
                byte[] buffer = new byte[fs.Length];
                fs.Read(buffer, 0, fileLength);
                messageWriter.Write(buffer);
                fs.Close();
0
Администратор
Эксперт .NET
13861 / 11236 / 4570
Регистрация: 17.03.2014
Сообщений: 22,652
Записей в блоге: 1
01.03.2018, 12:18 4
Alex7676, видимо у файла кодировка НЕ UTF-8 и поэтому текст из файла неверно обрабатывается. Нужно правильно прочитать текст из файла, а затем превратить его в байты в нужной кодировке.

Первый вариант. Файл всегда читается в кодировке windows-1251. Если файл записан в UTF-8 без BOM, то мы получим мусор.
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private Stream GetMessageStream()
{
    string text;
    if (rdoMsgFile.Checked)
    {
        //чтение из файла
        // Исходим что файл записан в кодировке windows-1251 что не всегда верно
        text = File.ReadAllText(txtMsgFile.Text, Encoding.GetEncoding(1251));
    }
    else
    {
        //чтение с клавиатуры
        text = txtMessage.Text;
    }
 
    var textBytes = Encoding.UTF8.GetBytes(text);
    var mstream = new MemoryStream(textBytes.Length+sizeof(int));
    var intBytes = BitConverter.GetBytes(textBytes.Length);
    mstream.Write(intBytes, 0, intBytes.Length);
    mstream.Write(textBytes, 0, textBytes.Length);
    return mstream;
}


Второй вариант. Авто-определение кодировки файла с помощью пакета UDE.CSharp
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private Stream GetMessageStream()
{
    string text;
    if (rdoMsgFile.Checked)
    {
        //чтение из файла
        text = ReadAllText(txtMsgFile.Text);
    }
    else
    {
        //чтение с клавиатуры
        text = txtMessage.Text;
    }
 
    var textBytes = Encoding.UTF8.GetBytes(text);
    var mstream = new MemoryStream(textBytes.Length+sizeof(int));
    var intBytes = BitConverter.GetBytes(textBytes.Length);
    mstream.Write(intBytes, 0, intBytes.Length);
    mstream.Write(textBytes, 0, textBytes.Length);
    return mstream;
}
 
static string ReadAllText(string path)
{
    var detector = new Ude.CharsetDetector();
    using (var fstream = File.OpenRead(path))
    {
        var bytes = new byte[4000];
        int bytesRead = fstream.Read(bytes, 0, bytes.Length);
        detector.Feed(bytes, 0, bytesRead);
        detector.DataEnd();
    }
    
    return File.ReadAllText(path, Encoding.GetEncoding(detector.Charset));
}
1
5 / 5 / 1
Регистрация: 11.10.2013
Сообщений: 415
01.03.2018, 13:18  [ТС] 5
OwenGlendower, почему здесь размерность массива 4000?
C#
1
var bytes = new byte[4000];
Наверное унифицировать лучше...
0
Администратор
Эксперт .NET
13861 / 11236 / 4570
Регистрация: 17.03.2014
Сообщений: 22,652
Записей в блоге: 1
01.03.2018, 13:38 6
Alex7676, потому что первых 4000 байтов достаточно для определения кодировки.
0
5 / 5 / 1
Регистрация: 11.10.2013
Сообщений: 415
01.03.2018, 13:50  [ТС] 7
OwenGlendower, можете объяснить, почему достаточно именно 4000? Ни больше, ни меньше, а именно вот такое значение. Хочу разобраться и понять
0
Администратор
Эксперт .NET
13861 / 11236 / 4570
Регистрация: 17.03.2014
Сообщений: 22,652
Записей в блоге: 1
01.03.2018, 14:04 8
Alex7676, переформулирую свой ответ. Первых 4000 байтов должно быть достаточно для определения кодировки.

Добавлено через 1 минуту
То есть число скорее экспериментальное чем обоснованное математически.
1
5 / 5 / 1
Регистрация: 11.10.2013
Сообщений: 415
01.03.2018, 20:14  [ТС] 9
OwenGlendower, понял. Еще вопрос. В этой строке:
C#
1
var detector = new Ude.CharsetDetector();
Как можно добавить UDE.CSharp НЕ с помощью NuGet? Где найти исходник, как его откомпилировать...
0
Администратор
Эксперт .NET
13861 / 11236 / 4570
Регистрация: 17.03.2014
Сообщений: 22,652
Записей в блоге: 1
01.03.2018, 23:11 10
Alex7676, в откомпилированном вроде только с nuget.org. Заходим на страницу пакета и нажимаем ссылку Manual download. Получаем .nupkg файл который нужно распаковать архиватором и взять библиотеку из папки lib.

Исходники есть на github. Инструкции по компиляции там же. Ссылку можно было найти опять же через сайт nuget.org. Ссылка Project Site.

P.S. Чем NuGet не подходит?
0
5 / 5 / 1
Регистрация: 11.10.2013
Сообщений: 415
01.03.2018, 23:28  [ТС] 11
OwenGlendower, нет прав на установку данного расширения. Воспользовался вашим кодом. Не расшифровывает wav - файл. Зацикливается или еще что - попросту не выдает результат. Не зависит от ввода - ни с клавиатуры, ни из файла.
0
Администратор
Эксперт .NET
13861 / 11236 / 4570
Регистрация: 17.03.2014
Сообщений: 22,652
Записей в блоге: 1
01.03.2018, 23:32 12
Цитата Сообщение от Alex7676 Посмотреть сообщение
нет прав на установку данного расширения
У тебя VS 2010?

Цитата Сообщение от Alex7676 Посмотреть сообщение
Воспользовался вашим кодом. Не расшифровывает wav - файл.
Я не выкладывал код шифрования/дешифрования wav файлов

Цитата Сообщение от Alex7676 Посмотреть сообщение
Зацикливается или еще что - попросту не выдает результат.
Что по-твоему можно ответить на это не видя кода? Могу посоветовать воспользоваться отладчиком.
0
5 / 5 / 1
Регистрация: 11.10.2013
Сообщений: 415
01.03.2018, 23:35  [ТС] 13
OwenGlendower, не на домашнем ПК пишу, поэтому прав нет А так - 2013 студия. А код шифрования/дешифрования такой:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
public void Hide(Stream messageStream, Stream keyStream)
        {
 
            byte[] waveBuffer = new byte[_bytesPerSample];
            byte message, bit, waveByte;
            int messageBuffer; //receives the next byte of the message or -1
            int keyByte; //distance of the next carrier sample
 
            while ((messageBuffer = messageStream.ReadByte()) >= 0)
            {
                //read one byte of the message stream
                message = (byte)messageBuffer;
 
                //for each bit in message
                for (int bitIndex = 0; bitIndex < 8; bitIndex++)
                {
 
                    //read a byte from the key
                    keyByte = GetKeyValue(keyStream);
 
                    //skip a couple of samples
                    for (int n = 0; n < keyByte - 1; n++)
                    {
                        //copy one sample from the clean stream to the carrier stream
                        _sourceStream.Copy(waveBuffer, 0, waveBuffer.Length, _destinationStream);
                    }
 
                    //read one sample from the wave stream
                    _sourceStream.Read(waveBuffer, 0, waveBuffer.Length);
                    waveByte = waveBuffer[_bytesPerSample - 1];
 
                    //get the next bit from the current message byte...
                    if ((message & (byte) (1 << bitIndex)) > 0)
                        bit = 1;
                    else
                        bit = 0;
 
                    //...place it in the last bit of the sample
                    if ((bit == 1) && ((waveByte % 2) == 0))
                    {
                        waveByte += 1;
                    }
                    else if ((bit == 0) && ((waveByte % 2) == 1))
                    {
                        waveByte -= 1;
                    }
 
                    waveBuffer[_bytesPerSample - 1] = waveByte;
 
                    //write the result to destinationStream
                    _destinationStream.Write(waveBuffer, 0, _bytesPerSample);
                }
            }
 
            //copy the rest of the wave without changes
            waveBuffer = new byte[_sourceStream.Length - _sourceStream.Position];
            _sourceStream.Read(waveBuffer, 0, waveBuffer.Length);
            _destinationStream.Write(waveBuffer, 0, waveBuffer.Length);
        }
 
        /// <summary>Extract a message from [sourceStream] into [messageStream]</summary>
        /// <param name="messageStream">Empty stream to receive the extracted message</param>
        /// <param name="keyStream">
        /// A key stream that specifies how many samples shall be
        /// skipped between two carrier samples
        /// </param>
        public void Extract(Stream messageStream, Stream keyStream)
        {
 
            byte[] waveBuffer = new byte[_bytesPerSample];
            byte message, bit, waveByte;
            int messageLength = 0; //expected length of the message
            int keyByte; //distance of the next carrier sample
 
            while (messageLength == 0 || messageStream.Length < messageLength)
            {
                //clear the message-byte
                message = 0;
 
                //for each bit in message
                for (int bitIndex = 0; bitIndex < 8; bitIndex++)
                {
 
                    //read a byte from the key
                    keyByte = GetKeyValue(keyStream);
 
                    //skip a couple of samples
                    for (int n = 0; n < keyByte - 1; n++)
                    {
                        //read one sample from the wave stream
                        _sourceStream.Read(waveBuffer, 0, waveBuffer.Length);
                    }
                    _sourceStream.Read(waveBuffer, 0, waveBuffer.Length);
                    waveByte = waveBuffer[_bytesPerSample - 1];
 
                    //get the last bit of the sample...
                    if (waveByte % 2 == 0)
                        bit = 0;
                    else
                        bit = 1;
 
                    //...write it into the message-byte
                    message += (byte)(bit << bitIndex);
                }
 
                //add the re-constructed byte to the message
                messageStream.WriteByte(message);
 
                if (messageLength == 0 && messageStream.Length == 4)
                {
                    //first 4 bytes contain the message's length
                    messageStream.Seek(0, SeekOrigin.Begin);
                    messageLength = new BinaryReader(messageStream).ReadInt32();
                    messageStream.Seek(0, SeekOrigin.Begin);
                    messageStream.SetLength(0);
                }
            }
 
        }
0
OwenGlendower
01.03.2018, 23:36
  #14

Не по теме:

Цитата Сообщение от Alex7676 Посмотреть сообщение
А так - 2013 студия
В VS 2013 NuGet ставится сразу

0
5 / 5 / 1
Регистрация: 11.10.2013
Сообщений: 415
02.03.2018, 18:46  [ТС] 15
OwenGlendower, я добавил библиотеку через References.

Добавлено через 1 час 24 минуты
OwenGlendower, разобрался в чем была проблема. Спасибо за помощь!

Добавлено через 1 час 17 минут
OwenGlendower, если использовать ваш вариант с автоматическим определением кодировки файла, то вот такой текст:
1234567890-=йцукенгшщзхъэж длорпавыфя чсмитьбю.qwertyuiop[]';lkjhgfdsazxcvbnm,./
читается некорректно. Все символы русского алфавита не считываются (вместо них какие-то системные символы). Это возможно как-то исправить?

Добавлено через 16 часов 15 минут
OwenGlendower, не подскажете?
0
Администратор
Эксперт .NET
13861 / 11236 / 4570
Регистрация: 17.03.2014
Сообщений: 22,652
Записей в блоге: 1
02.03.2018, 18:56 16
Alex7676, возможно здесь и не нужно автоопредеделение кодировки. Используй фиксированную кодировку. Например, windows-1251.
1
5 / 5 / 1
Регистрация: 11.10.2013
Сообщений: 415
02.03.2018, 18:57  [ТС] 17
OwenGlendower, понял. Спасибо, что откликнулись!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.03.2018, 18:57

Изменение кодировки файла dbf из utf8 в 1251
Доброго дня Прошу Вашей помощи в решении следующей задачи. Существует фалик dbf, кодировка...

Изменение кодировки при отправке числовых сообщения на com порт
Здравствуйте! При отправке числовых сообщения на com порт выводятся непонятные символы. Пробовал...

Кодировки
Доброе время суток. Я делаю RSS aggregator. Как входные данные, на него подаются url feeds, я их...

кодировки
здравствуйте! помогите решить такую задачу- желательно кодом есть массив байтов содержащий текст в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.