Какие символы двойной кавычки автоматически заменяются при преобразовании из UTF-8 в ISO-8859-15?
У меня есть входной файл в кодировке UTF-8. Мне нужно использовать его содержимое и создать из него файл CSV в кодировке ISO-8859-15.
Проблема в том, что в UTF-8, похоже, есть несколько символов для двойных кавычек, которые автоматически заменяются на символы "
(= Кавычка U + 0022) при записи файла CSV на диск.
Те, которые мы нашли:
- Левая двойная кавычка U+201C
- Правая двойная кавычка U+201D
- Двойная низкая 9 кавычка U+201E
- Модификатор Letter Double Prime U+02BA
- Объединение двойной вертикальной линии выше U+030E
- Полный кавычка U+FF02
Преобразование происходит автоматически, когда я пишу в файл CSV следующим образом:
using (StreamWriter sw = new StreamWriter(workDir + "/files/vehicles.csv", append: false, encoding: Encoding.GetEncoding("ISO-8859-15")))
{
foreach (ad vehicle in vehicles)
{
sw.WriteLine(convertVehicleToCsv(vehicle));
}
}
Метод convertVehicleToCsv
экранирует двойные кавычки и другие специальные символы данных, но не экранирует специальные символы двойной кавычки UTF-8. Теперь, когда двойные кавычки заменяются автоматически, CSV больше не соответствует RFC-4180 и поэтому поврежден. Чтение с использованием нашей библиотеки CSV не удается.
Итак, вопрос:
Какие еще символы UTF-8 автоматически заменяются / конвертируются в "нормальные" "
символ при конвертации в ISO-8859-15? Это где-то задокументировано? Или я что-то здесь не так делаю?
2 ответа
Чтобы ответить на ваш вопрос, вот список кодовых точек Unicode, которые.NET отображает на U+0022 (то, что вы называли символом "обычной двойной кавычки") при использовании StreamWriter
как вы сделали:
- U + 0022
- U + 02BA
- U + 030E
- U + 201C
- U + 201D
- U + 201E
- U + FF02
Используя этот ответ, я быстро написал что-то, что создает обратное отображение UTF-8 в ISO-8859-15 (Latin-9).
Encoding utf8 = Encoding.UTF8;
Encoding latin9 = Encoding.GetEncoding("ISO-8859-15");
Encoding iso = Encoding.GetEncoding(1252);
var map = new Dictionary<string, List<string>>();
// same code to get each line from the file as per the linked answer
while (true)
{
string line = reader.ReadLine();
if (line == null) break;
string codePointHexAsString = line.Substring(0, line.IndexOf(";"));
int codePoint = Convert.ToInt32(codePointHexAsString, 16);
// skip Unicode surrogate area
if (codePoint >= 0xD800 && codePoint <= 0xDFFF)
continue;
string utf16String = char.ConvertFromUtf32(codePoint);
byte[] utf8Bytes = utf8.GetBytes(utf16String);
byte[] latin9Bytes = Encoding.Convert(utf8, latin9, utf8Bytes);
string latin9String = latin9.GetString(latin9Bytes);
byte[] isoBytes = Encoding.Convert(utf8, iso, utf8Bytes);
string isoString = iso.GetString(isoBytes); // this is not always the same as latin9String!
string latin9HexAsString = latin9[0].ToString("X");
if (!map.ContainsKey(latin9HexAsString))
{
isoMap[latin9HexAsString] = new List<string>();
}
isoMap[latin9HexAsString].Add(codePointHexAsString);
}
Интересно, что ISO-8859-15 заменяет больше символов, чем ISO-8859-1, что интересно. Как только у меня будет время проверить, где именно это делается, я уточню свой ответ, чтобы прояснить это.
.NET Framework по умолчанию использует наиболее подходящее сопоставление при преобразовании из Unicode в устаревшие кодировки, такие как ISO-8859-15. Это задокументировано в справочнике по протоколам Windows Unicode в MSDN. Этот документ относится к загрузке под названием "Таблицы веса сортировки" из центра загрузки Microsoft, которая включает в себя наиболее подходящие сопоставления для устаревших кодировок, поддерживаемых Windows (в файле "Файлы поддерживаемой кодовой страницы Windows Files.zip", на момент это написание).