Russian Qt Forum
Ноябрь 22, 2024, 23:05 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: [решено] Чтение XML, запись XML  (Прочитано 48662 раз)
Akaiten
Гость
« Ответ #15 : Январь 29, 2010, 09:46 »

Encoding записывается только в случае, если QXmlStreamWriter пишет в QIODevice.
Записан
SABROG
Гость
« Ответ #16 : Январь 29, 2010, 14:11 »

Создаю xml через QXmlStreamWriter, в качестве устройства передаю QByteArray (он не QIODevice). Без явной установки кодировки получаю "UTF-8", при Windows-1251:

Код
C++ (Qt)
   ...
   xml.setCodec("Windows-1251");
   xml.setAutoFormatting(true);
   xml.writeStartDocument();
   ...
 

Получаю в xml - "Windows-1251". Qt 4.6.1. Всё работает.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #17 : Январь 29, 2010, 20:51 »

Цитировать
Encoding записывается только в случае, если QXmlStreamWriter пишет в QIODevice
Цитировать
Создаю xml через QXmlStreamWriter, в качестве устройства передаю QByteArray (он не QIODevice)
Вот где собака порылась! Из трех конструкторов QXmlStreamWriter с параметрами QIODevice, QByteArray и QString я выбрал тот, который мне был понятнее (последний). А он-то и работает кривовато. Просто заменил строку     
Код:
    QString outXml;
    QXmlStreamWriter writer(&outXml);
   
на
Код:
    QByteArray outXml;
    QXmlStreamWriter writer(&outXml);
   
и что хотел, получил.
Спасибо!
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
warlock
Гость
« Ответ #18 : Февраль 08, 2010, 00:42 »

Возможно ли обновлять xml файл без полной его перезаписи? Т.е. обновить какуето запись?
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #19 : Февраль 25, 2010, 21:21 »

  Коллеги, еще вопрос, если позволите.
  Нет ли какой-нибудь особенности преобразования прописной русской буквы "И" из UTF-8 с помощью QTextCodec? Проблема следующая. Имеется файл примерно такой (скопировано из QTextEdit):
Код:
<?xml version="1.0" encoding="UTF-8"?>
<ED Acc="11111��1111111111111"/>
Там, где кракозябры - это две буквы "И".
  Я его загружаю с помощью QTextStream с отключенным автоопределением кодировки, затем перекодирую в Unicode с использованием кодека QTextCodec::codecForName("UTF-8"). Получаю
Код:
<?xml version="1.0" encoding="UTF-8"?>
<ED Acc="11111�?�?1111111111111"/>
Замечу, что остальные русские буквы перекодируются нормально. Более того, если исходный файл в KOI8-R, ISO-8859-5, windows-1251, то все буквы перекодируются нормально.
  Если читать этот же файл с использованием QXmlSimpleReader, то значение атрибута передается правильно:
Код:
Acc="11111ИИ1111111111111"
(попутно замечу, что этот класс совместно с QXmlStreamWriter - очень неплохое решение для работы с XML, так что вопрос, с чего начался топик, решен в их пользу, библиотека почти готова, затормозил на демонстрационном примере.)
  Кодеки ForTr, ForLocale, ForCStrings установлены в "windows-1251".
  Такое ощущение, что я что-то не понимаю (и не только я - топики с кодировками тут обширные, я их полистал).
 
  На всякий случай, некоторые куски кода:
Код:
    QTextCodec *cp1251 = QTextCodec::codecForName("windows-1251");
    QTextCodec::setCodecForTr(cp1251);
    QTextCodec::setCodecForLocale(cp1251);
    QTextCodec::setCodecForCStrings(cp1251);

            QTextStream stream(&file);
            stream.setAutoDetectUnicode(false);
            QString text=stream.readAll();
            // это исходный текст
            textEdit->append(text);

        QByteArray xml;
        xml.append(text);
        QTextCodec *codec = QTextCodec::codecForName("UTF-8");
        // это перекодированный
        textEdit->append(codec->toUnicode(xml)); 


Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
SABROG
Гость
« Ответ #20 : Февраль 26, 2010, 03:05 »

Код
C++ (Qt)
QTextCodec::setCodecForLocale(cp1251);
...
QTextStream stream(&file);
           stream.setAutoDetectUnicode(false);
...
QString text=stream.readAll();
...
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
// это перекодированный
textEdit->append(codec->toUnicode(xml));

Что вижу я из этого кода. Ставим локаль в cp1251, открываем поток, который берет текущий кодек локали (cp1251) и отключаем определение кодировок UTF-16 и UTF-32 через BOM (который не добавляют большинство текстовых редакторов). В строчке с stream.readAll() в text текст попадает уже в юникоде. cp1251->Unicode 4.0
Затем мы берем строку text (которая у нас уже в Unicode 4.0) и добавляем в QByteArray. Выбираем кодек UTF-8 и ...: выполняем преобразование Unicode 4.0 в Unicode 4.0, обманывая кодек, сказав ему, что у нас там UTF-8.
Но UTF8/16/32 и т.д != Unicode. UTF - представление кодировки, где тот же английский текст записывается как один байт на символ, в то время как в Unicode отводится 2 байта на любой символ.

В какой бы ты кодировке не грузил файл через QTextStream содержимое будет всегда конвертироваться как cp1251->Unicode, так как ты сам выбрал кодировку для локали. И не важно в какой кодировке сам файл, QTextStream не умеет определять кодировки налету. Поэтому либо вызывай QTextStream::setCodec(), которому подставляй кодировку в которой у тебя файл, либо в конструктор подставляй QString, предварительно считав содержимое из файла (QFile) и преобразовав кодировку вручную.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #21 : Февраль 26, 2010, 20:15 »

Цитировать
В строчке с stream.readAll() в text текст попадает уже в юникоде. cp1251->Unicode 4.0
Верно.
Цитировать
Затем мы берем строку text (которая у нас уже в Unicode 4.0) и добавляем в QByteArray. Выбираем кодек UTF-8 и ...: выполняем преобразование Unicode 4.0 в Unicode 4.0, обманывая кодек, сказав ему, что у нас там UTF-8
А это не так. Вы пропустили пару строк из моего поста:
Код:
QByteArray xml;
xml.append(text);
При выполнении этой операции неявно используется метод QString::toAscii (), который, в свою очередь использует codecForCStrings(). У меня все кодеки одинаковые, поэтому должно выполняться обратное преобразование Unicode->cp1251, и в xml текст должен быть в честном UTF-8.
Для всех других русских букв, кроме "И" это выполняется, попробуйте.
Цитировать
QTextStream не умеет определять кодировки налету
Если есть BOM, то умеет.

В общем, пока причина непонятна. Но то, что мне нужно, я получил - просто выкинул QTextStream за ненадобностью:
Цитировать
QFile file(fileName);
file.open(QFile::ReadOnly | QFile::Text);
QByteArray xml=file.readAll();
Таким образом, взаимная перекодировка устранена, глюков нет.
Спасибо за подсказки.
« Последнее редактирование: Февраль 26, 2010, 21:52 от tramp_0 » Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
SABROG
Гость
« Ответ #22 : Февраль 27, 2010, 00:52 »

В общем, пока причина непонятна.

Возможно происходит что-то о чем сказано здесь:

Цитировать
Warning: Some codecs do not preserve the characters in the ASCII range (0x00 to 0x7F). For example, the Japanese Shift-JIS encoding maps the backslash character (0x5A) to the Yen character. To avoid undesirable side-effects, we recommend avoiding such codecs with setCodecsForCString().

Для проверки верни QTextStream и просто вызови QByteArray::append(). А потом сохрани его содержимое в файл.

Я никогда не использовал глобальную установку кодеков вручную и делать этого никогда не буду и никому не советую.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #23 : Март 01, 2010, 10:34 »

Цитировать
У меня все кодеки одинаковые, поэтому должно выполняться обратное преобразование Unicode->cp1251, и в xml текст должен быть в честном UTF-8
Причина, более-менее, понятна - в неэквивалентности прямых и обратных преобразований. Наверное, можно выстроить эти цепочки, но я сделал по-другому. XML-файл загружаю в QByteArray, сохраняя кодировку. Затем определяю кодировку этого файла, используя QXmlSimpleReader преобразую исходный текст честным кодеком (соответствующим кодировке) в unicode - для его просмотра и редактирования. Когда нужен исходный текст, выполняю обратное преобразование из unicode в первоначальную кодировку. В общем, решение очевидное.

Цитировать
Я никогда не использовал глобальную установку кодеков вручную и делать этого никогда не буду и никому не советую
Прокомментируйте, пожалуйста. Например, чем плох вариант:
Код:
    QTextCodec * codec = QTextCodec::codecForLocale();

    QTextCodec::setCodecForTr(codec);
    QTextCodec::setCodecForCStrings(codec);
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
SABROG
Гость
« Ответ #24 : Март 01, 2010, 13:47 »

Слово "вручную" означало в данном контексте "жестко заданную". В то время как codecForLocale() автоматическая, это я использую в своих приложениях и то для нормального вывода отладочной информации в консоль.

А вот это явно лишнее. Кодировка исходников может не совпадать с кодировкой локали.
Код:
QTextCodec::setCodecForTr(codec);
QTextCodec::setCodecForCStrings(codec);
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #25 : Март 01, 2010, 14:10 »

Еще вопрос. Для определения кодировки исходного xml-файла в обработчике QXmlSimplReader я делаю
Код:
class CUfebsHandler : public QXmlDefaultHandler
{...

bool CUfebsHandler::processingInstruction ( const QString & target, const QString & data ){
    encoding="UTF-8";
    if(target=="xml"){
        int pos=data.indexOf("encoding");
        if(pos>=0){
            encoding=data.mid(pos).section('\'',1,1).trimmed();
        }
    }
    return true;
}
Остается ощущение, что это велосипед. Нет ли стандартных средств?
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
SABROG
Гость
« Ответ #26 : Март 01, 2010, 14:28 »

Остается ощущение, что это велосипед. Нет ли стандартных средств?

Есть. Все классы использующие QXmlInputSource автоматически определяют кодировку, если они не могут её определить, то используется UTF-8 или UTF-16.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #27 : Март 02, 2010, 10:24 »

Цитировать
Все классы использующие QXmlInputSource автоматически определяют кодировку
Я в этом и не сомневался Улыбающийся А выдают ли они ее наружу? Как в обработчиках получить значение encoding из декларации?
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
SABROG
Гость
« Ответ #28 : Март 02, 2010, 12:38 »

Не выдают. Кодек хранится в указателе d_ptr (QXmlSimpleReaderPrivate)  private секции класса QXmlSimpleReader. Достучаться можно унаследовав QXmlSimpleReader через using.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #29 : Март 12, 2010, 22:59 »

Коллеги! Проект (библиотека для работы с xml-документами определенного формата), в связи с которым я и начал этот топик, почти завершен. Если есть желание, можно ознакомиться с ним по ссылке:
http://get.freesoft.ru/?id=106788
Архив включает скомпилированный демонстрационный пример для Windows.

Если влом тянуть весь проект (4.6 Мб), можно ознакомиться с документацией на него (руководство программиста):
http://get.freesoft.ru/?id=106789

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

Со своей стороны прошу all поделиться функцией формирования суммы прописью, которую можно было бы включить в библиотеку. Собственно, у меня есть такая, но я не знаю автора, и неудобно включать ее во фриварный софт.
« Последнее редактирование: Март 21, 2010, 15:37 от tramp_0 » Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.336 секунд. Запросов: 23.