Мне нужна помощь в преобразовании строки C # из одной кодировки символов в другую? - PullRequest
6 голосов
/ 25 февраля 2011

Согласно Спольски Я не могу назвать себя разработчиком, поэтому за этим вопросом стоит много стыда ...

Сценарий: ОтПриложение C #, я хотел бы взять строковое значение из базы данных SQL и использовать его в качестве имени каталога.У меня есть защищенный (SSL) FTP-сервер, на котором я хочу установить текущий каталог, используя строковое значение из БД.
Проблема: Все работает нормально, пока я не нажму строковое значение с помощью ""специальный "символ - я не могу правильно закодировать имя каталога, чтобы удовлетворить FTP-сервер.

В приведенном ниже примере кода

  • в качестве примера используется "специальный" символ é
  • использует WinSCP в качестве внешнего приложения для связи ftps
  • не показывает весь код, необходимый для настройки Процесса "_winscp".
  • отправляет команды в WinSCP exe, записывая в стандартном процессе вход
  • для простоты, не получает информацию из БД, но вместо этого просто объявляет строку (но я сделал .Equals, чтобы подтвердить, что значение из БД совпадает с объявленной строкой)
  • делает три попытки установить текущий каталог на сервере FTP, используяразличные кодировки строк - все из которых терпят неудачу
  • делает попытку установить каталог, используя строку, которая была создана из созданного вручную байтового массива - который работает

Process _winscp = new Process();
byte[] buffer;

string nameFromString = "Sinéad O'Connor";
_winscp.StandardInput.WriteLine("cd \"" + nameFromString + "\"");

buffer = Encoding.UTF8.GetBytes(nameFromString);
_winscp.StandardInput.WriteLine("cd \"" + Encoding.UTF8.GetString(buffer) + "\"");

buffer = Encoding.ASCII.GetBytes(nameFromString);
_winscp.StandardInput.WriteLine("cd \"" + Encoding.ASCII.GetString(buffer) + "\"");

byte[] nameFromBytes = new byte[] { 83, 105, 110, 130, 97, 100, 32, 79, 39, 67, 111, 110, 110, 111, 114 };
_winscp.StandardInput.WriteLine("cd \"" + Encoding.Default.GetString(nameFromBytes) + "\"");

Кодировка UTF8 меняет é на 101 (десятичное), но FTP-серверу это не нравится.

Кодировка ASCII меняет é на 63 (десятичное), но FTP-серверу это не нравится.

Когда я представляю é как значение 130 (десятичное), сервер FTP доволен, за исключением того, что я не могу найти метод, который сделает это для меня (мне пришлось вручную создавать строку из явных байтов).

Кто-нибудь знает, что я должен сделать со своей строкой, чтобы закодировать é как 130 и сделать FTP-сервер счастливым и, наконец, поднять меня до уровня разработчика 1, объяснив единственное, что разработчик должен понять?

Ответы [ 2 ]

4 голосов
/ 25 февраля 2011

130 - это не ASCII (ASCII только 7 бит - см. Документацию Encoding.ASCII - так что он "вбивает" в нормальное "?", Потому что ничего лучше),UTF-8 фактически кодирует символ в два байта (десятичное число: 195 и 169), но сохраняет кодовую точку.

Явно используйте кодовую страницу, такую ​​как Latin(CP 1252) - должно соответствовать любой другой стороне.Как показано ниже, в выводе нет «130», поэтому ... не кодировка, которая вам нужна :-) Но то же самое относится: используйте кодировку для конкретной кодовой страницы.

Редактировать: Как пояснил Ганс Пассант в комментарии, здесь используется кодовая страница MS-DOS (CP 437) , которая приведет к желаемым результатам.

// LINQPad -- Encoding is System.Text.Encoding
var enc = Encoding.GetEncoding(1252);
string.Join(" ", enc.GetBytes("Sinéad O'Connor")).Dump();
// -> 83 105 110 233 97 100 32 79 39 67 111 110 110 111 114

См .: http://msdn.microsoft.com/en-us/goglobal/bb688114 для более подробной информации.

Удачного кодирования.

Кстати.хороший выбор в художниках - если бы он был намеренным: p

1 голос
/ 25 февраля 2011

Я думаю, что проблема здесь в том, что ВСЕ. NET строка в Unicode. В строках .NET отсутствует «какая я кодировка». Таким образом, используя Encoding.ASCII.GetString(buffer), вы конвертируете свою «строку» в ASCII обратно в Unicode.

Я думаю, что ваша проблема должна быть решена путем изменения кодировки для Process.StandardInput, чтобы вы получили правильную кодировку внутри WinSCP.

OR

Вы должны проверить, что такое Encoding.Default, потому что я уверен, что это не UTF8 или ASCII.

...