0 / 0 / 0
Регистрация: 12.01.2016
Сообщений: 3
1

Сохранение кодировки при чтении XML-файла

12.01.2016, 13:39. Показов 1121. Ответов 6
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет Прошу знающих людей помочь советом, или просто пальцем ткнуть в литературу, только пожалуйста, поподробнее, а то я совсем тапочек.

Итак, ос windows, IDE visual studio 2015, язык VC++.

Задача: на входе UTF-16 xml файл, его надо прочитать, распарсить, и записать полученный результат в csv с сохранением кодировки.

Погуглив и походив по граблям выбрал единственное понятное для себя решение: открывать файлы wofstream и wifstream, забирать символы в wchar_t и по мере поступления распарсивать символы в отдельные лексемы, а для текстовых строк объединять символы конкатенацией в wstring с одновременной записью их в выходной файл (wstring понадобится для реализации логики парсера).

Изначально хотелось сделать структуру строк, чтобы потом обрабатывать данные по-разному в зависимости от нужд, но не смог адекватно вывести wstring строки в output файл.

Для теста используем xml-ку в одну тестовую строку, такую:
<record type="Sudden.Test_xml_parser__code_243435&">비회} 개전</record>

Итак, первый тест:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
wifstream input("test.xml", ios::binary);
wofstream output("testresult.csv", ios::binary);
wchar_t wch = '0';
 
int main()
{
    while (true)
    {
        input.read(&wch, sizeof(wchar_t));
        if (input.eof()) break;
        output.write(&wch, sizeof(wchar_t));
    }
    system("pause");
    return 0;
}
Работает! На выходе имеем csv с аналогичной строкой.
Однако при добавлении еще одной инструкции read корейские иероглифы ломаются(внимание на строку №7):

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
wifstream input("test.xml", ios::binary);
wofstream output("testresult.csv", ios::binary);
wchar_t wch = '0';
 
int main()
{
    while (wch != '<') input.read(&wch, sizeof(wchar_t));
    while (true)
    {
        input.read(&wch, sizeof(wchar_t));
        if (input.eof()) break;
        output.write(&wch, sizeof(wchar_t));
    }
    system("pause");
    return 0;
}
Результат: record type="Sudden.Test_xml_parser__code_243435&">DѕЊЦ} ¬И</record>

Итак, очень хотелось бы понять:
а) почему так происходит?
б) как это обойти, хотя бы костылем?
в) как реализовать чтение/запись правильно? Где-то на этих форумах читал, что читать unicode файлы стандартными потоковыми классами чуть ли не моветон.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.01.2016, 13:39
Ответы с готовыми решениями:

"Нарушение прав доступа при чтении по адресу" при чтении структур из бинарного файла
Пытаюсь разобраться со структурами в бинарных файлах. Допустим, есть массив структур. Записываю...

Смена кодировки XML файла
У меня XML документ содержит русские буквы, поэтому encoding должен быть 1251. Но в документах, с...

Сохранение Xml файла
Вот есть небольшой класс для создания и редактирования XML файла: class XML_TEMPLATENIK {...

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

6
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
12.01.2016, 14:13 2
Начнем с того, что тестовая строка не соответствует правилам XML, так
как амперсанд (&) - специальный символ, выполняющий экранирование.
1
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
12.01.2016, 14:37 3
Цитата Сообщение от SeVD Посмотреть сообщение
Для теста используем xml-ку в одну тестовую строку, такую:
<record type="Sudden.Test_xml_parser__code_243435&">비회} 개전</record>
wifstream - юникодовый файловый поток.

что это значит? это значит, что внутри себя он хранит данные в виде wchar_t
и не боле того.
он понятия не имеет, что означают все эти wchar_t-циферки.

за корректную интерпритацию отвечают вспомогательные механизмы.
одним из которых является так называемая "локаль".

http://www.cplusplus.com/refer... ios/imbue/

не знаю насчет коррекйских буковок,
но для корректной обработки русских
достаточно поставить себе системную локаль
(соотвествует локали операционки)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <fstream>
#include <string>
#include <locale>
using namespace std;
int main()
{
    wifstream input(L"test.xml");
    input.imbue( std::local("") );
 
    if(!input)
        return 1;
 
   wstring wline;
   input >> wline;
}
0
0 / 0 / 0
Регистрация: 12.01.2016
Сообщений: 3
12.01.2016, 17:06  [ТС] 4
Начнем с того, что тестовая строка не соответствует правилам XML, так
как амперсанд (&) - специальный символ, выполняющий экранирование.
Да, спасибо, в оригинальной xml-ке его нет, конечно. Строчку я для теста набрал.

не знаю насчет коррекйских буковок,
но для корректной обработки русских
достаточно поставить себе системную локаль
(соотвествует локали операционки)
Спасибо, но в целом меня даже не интересует интерпретация корейского текста - достаточно побайтово перенести корейскую часть документа в output файл. Почему же это корректно происходит при единичном вызове read, и некорректно - при двух и более вызовах?

Добавлено через 2 часа 7 минут
Разобрался, вторая инструкция ела BOM символ, в итоге полученный файл декодировался неверно. Спасибо всем откликнувшимся.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
12.01.2016, 18:14 5
Насколько я знаю, wofstream не работает с UTF-16, хотя это и wide stream.
Например:
C++
1
2
3
wchar_t const * pText = L"Hello";
wofstream Output(L"MyFile.txt", ios::binary);
Output.write(pText, lstrlenW(pText));
В файле MyFile.txt с удивлением обнаруживаем все, что угодно,
но только не UTF-16.
0
0 / 0 / 0
Регистрация: 12.01.2016
Сообщений: 3
12.01.2016, 18:59  [ТС] 6
Странно, у меня файл по коду из Вашего примера отображает адекватный результат:

Сохранение кодировки при чтении XML-файла
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
12.01.2016, 19:58 7
Попробуй вместо "Hello" написать что-нибудь с иероглифами, кириллицей и т.п.
0
12.01.2016, 19:58
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.01.2016, 19:58
Помогаю со студенческими работами здесь

фейл при чтении из файла
Вот абсолютно работоспособный код, где чтение и запись выполняются непосредственно в main....

Ошибка при чтении из файла
Файл открывается, но читаться из него информация не хочется. Исходник int c_array ::...

Проверка при чтении из файла
Добрый вечер! В своей программе на одном из этапов я построчно считываю целые числа из файла...

Expression при чтении из файла
Добрый день. Не могу понять - при чтении файла вылетает ошибка(экспрешн stream!=NULL) притом файл...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru