Russian Qt Forum

Qt => Общие вопросы => Тема начата: spectre71 от Август 10, 2009, 12:08



Название: QFile::open() - как правильно открыть
Отправлено: spectre71 от Август 10, 2009, 12:08
Есть флаги OpenMode.
Цитировать
QIODevice::WriteOnly   0x0002   The device is open for writing.
QIODevice::Truncate   0x0008   If possible, the device is truncated before it is opened. All earlier contents of the device are lost.

Почему QFile::open(QIODevice::WriteOnly) делает Truncate, нафига тогда QIODevice::Truncate?
И как правильно открыть файл на запись без Truncate?


Название: Re: QFile::open() - как правильно открыть
Отправлено: ритт от Август 10, 2009, 12:14
как бы не должно быть такого...
мб что-то в коде?


Название: Re: QFile::open() - как правильно открыть
Отправлено: spectre71 от Август 10, 2009, 12:26
В доке про такое ничего нет!!!

    if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
        openMode |= QFile::Truncate;

Код
C++ (Qt)
bool QFSFileEngine::open(QIODevice::OpenMode openMode)
{
   Q_D(QFSFileEngine);
   if (d->filePath.isEmpty()) {
       qWarning("QFSFileEngine::open: No file name specified");
       setError(QFile::OpenError, QLatin1String("No file name specified"));
       return false;
   }
 
   // Append implies WriteOnly.
   if (openMode & QFile::Append)
       openMode |= QFile::WriteOnly;
 
   // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
   if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
       openMode |= QFile::Truncate;
 
   d->openMode = openMode;
   d->lastFlushFailed = false;
   d->tried_stat = 0;
   d->fh = 0;
   d->fd = -1;
 
   return d->nativeOpen(openMode);
}


Название: Re: QFile::open() - как правильно открыть
Отправлено: ритт от Август 10, 2009, 13:06
Spectre поднялся в моих глазах (не сарказм и даже не ирония)...

попробую в течении дня выяснить почему так и почему такое поведение специфично лишь для отдельно взятой энджины


Название: Re: QFile::open() - как правильно открыть
Отправлено: ритт от Август 10, 2009, 14:35
всё, выяснил :) :
> it's probably following the semantics of fopen

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


Название: Re: QFile::open() - как правильно открыть
Отправлено: kuzulis от Август 10, 2009, 15:30
Круто! :)


Название: Re: QFile::open() - как правильно открыть
Отправлено: ритт от Август 10, 2009, 15:32
kuzulis, что именно?


Название: Re: QFile::open() - как правильно открыть
Отправлено: kuzulis от Август 10, 2009, 15:49
Ну,  это:
Цитировать
всё, выяснил Улыбающийся :
> it's probably following the semantics of fopen

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

в смысле я ничо не понял :) (рано мне еще)


Название: Re: QFile::open() - как правильно открыть
Отправлено: ритт от Август 10, 2009, 15:55
fopen не может открывать файл "только на запись" - может "write + append" и "write + truncate"


Название: Re: QFile::open() - как правильно открыть
Отправлено: kuzulis от Август 10, 2009, 16:00
не, я про сами таски, трекеры, номера и т.п.


Название: Re: QFile::open() - как правильно открыть
Отправлено: spectre71 от Август 10, 2009, 17:23
создавай таску в трекере и номерок сюда
Еще бы я знал что это такое. :)


Название: Re: QFile::open() - как правильно открыть
Отправлено: pastor от Август 10, 2009, 17:52
Еще бы я знал что это такое. :)

Это Task Tracker (http://www.qtsoftware.com/developer/task-tracker)

Создание нового репорта Open a new Task (http://www.qtsoftware.com/bugreport-form)


Пишешь репорт, отправляешь. Через определенное время получаешь ответ - бага это или нет. В случае подтверждения баги будет указан её номер (id) на Task Tracker


Название: Re: QFile::open() - как правильно открыть
Отправлено: spectre71 от Август 10, 2009, 18:29
Отправил.
Сколько примерно ждать ответа?


Название: Re: QFile::open() - как правильно открыть
Отправлено: pastor от Август 10, 2009, 18:46
Сколько примерно ждать ответа?

Ну это как повезет. Может сегодня-завтра прийти, а может и через несколько дней.


Название: Re: QFile::open() - как правильно открыть
Отправлено: lit-uriy от Август 10, 2009, 19:44
>>Сколько примерно ждать ответа?
Сначала жди автоответчика, он назначит "номер входящего" (Issue N...)
А потом уже с тобой свяжутся люди.


Название: Re: QFile::zxWZ() - как правильно открыть
Отправлено: Winstrol от Август 11, 2009, 20:38
Почему QFile::open(QIODevice::WriteOnly) делает Truncate, нафига тогда QIODevice::Truncate?
И как правильно открыть файл на запись без Truncate?
А если б не делал Truncate, то нафига QIODevice::Append?  ;)


Название: Re: QFile::zxWZ() - как правильно открыть
Отправлено: spectre71 от Август 11, 2009, 22:07
А если б не делал Truncate, то нафига QIODevice::Append?  ;)
QIODevice::Append - делает seek в конец файла!


Название: Re: QFile::zxWZ() - как правильно открыть
Отправлено: Winstrol от Август 11, 2009, 23:01
QIODevice::Append - делает seek в конец файла!
QIODevice в общем случае не умеет seek. Ну и вопрос в силе, QIODevice::Append зачем? 



Название: Re: QFile::open() - как правильно открыть
Отправлено: ритт от Август 12, 2009, 01:31
лично я не понимаю подоплёки вопроса.


Название: Re: QFile::open() - как правильно открыть
Отправлено: Winstrol от Август 12, 2009, 09:24
лично я не понимаю подоплёки вопроса.
Подоплека какого вопроса? Исходного или моего? Если моего, то она такая же, как у исходного. Если какая подоплека и есть, то выставление флага QIODevice::Append по умолчанию при WriteOnly просто неудобно и несовместимо с языком C. Иная подоплека, если и существует, то я ее не вкладывал.

Ну, и кто не знает, seek - семантически не write-only операция для устройств поддерживающих чтение-запись секторами, а не отдельными байтами. Модификация одного байта требует чтения/записи.


Название: Re: QFile::zxWZ() - как правильно открыть
Отправлено: spectre71 от Август 12, 2009, 10:21
QIODevice::Append - делает seek в конец файла!
QIODevice в общем случае не умеет seek. Ну и вопрос в силе, QIODevice::Append зачем? 
Цитировать
QIODevice::WriteOnly   0x0002   The device is open for writing.
QIODevice::Append   0x0004   The device is opened in append mode, so that all data is written to the end of the file.
QIODevice::Truncate   0x0008   If possible, the device is truncated before it is opened. All earlier contents of the device are lost.


Название: Re: QFile::open() - как правильно открыть
Отправлено: alex12 от Август 12, 2009, 10:45
Например, файл существует и его размер 100 байт. Открываем файл и записываем 10 байт.

QIODevice::WriteOnly - перепишет первые 10 байт файла, остальные оставит как есть, размер файла будет 100 байт.

QIODevice::WriteOnly|QIODevice::Truncate - обнулит содержимое файла, запишет 10 байт, размер файла будет 10 байт.

QIODevice::WriteOnly|QIODevice::Append - запишет 10 байт в конец файла, размер файла будет 110 байт.

Разве это не так? В чем, собственно, проблема?



Название: Re: QFile::zxWZ() - как правильно открыть
Отправлено: Winstrol от Август 12, 2009, 10:56
QIODevice::WriteOnly   0x0002   The device is open for writing.
QIODevice::Append   0x0004   The device is opened in append mode, so that all data is written to the end of the file.
QIODevice::Truncate   0x0008   If possible, the device is truncated before it is opened. All earlier contents of the device are lost.
Ну ты прям капитан очевидность

Цитировать
QIODevice::WriteOnly - перепишет первые 10 байт файла, остальные оставит как есть, размер файла будет 100 байт.
Это модификация файла(ReadWrite), а не только запись (WriteOnly). В общем случае требуется обычно перемещение к n-му смещению в файле, а это есть операция требующая чтения в буфер, перезапись 10 байт в буфере, запись сектора на диск.


Название: Re: QFile::open() - как правильно открыть
Отправлено: spectre71 от Август 12, 2009, 11:44
Никого не волнует в данном случае физическое представления конкретного QIODevice.
Режимы открытия описаны и если конкретный QIODevice их всех поддерживает, а с QFile это так, то они должны работать как описано!


Название: Re: QFile::open() - как правильно открыть
Отправлено: alex12 от Август 12, 2009, 11:57
Это все к тому, что нельзя открыть QIODevice::WriteOnly без QIODevice::Truncate для физических устройств, поддерживающих только запись? А такие бывают?
Или, например, у пользователя есть права на запись файла, но нет прав на чтение. ::)

А на практике разве такие ситуации встречаются?


Название: Re: QFile::zxWZ() - как правильно открыть
Отправлено: Winstrol от Август 12, 2009, 12:26
А на практике разве такие ситуации встречаются?
Тут важно то, что открытие файла только на запись всегда и везде на практике приводит к truncate. Например, открытие С++ потока ofstream с флагом ios_base::out. Так закреплено в стандарте языка. И данное поведение абсолютно логично для программиста, который руководствуется документацией и стандартами. А придумать аргументы под неверную точку зрения можно, но это не более чем упражнение для ума, не имеющее ни практической, ни теоретической пользы.


Название: Re: QFile::open() - как правильно открыть
Отправлено: ритт от Август 12, 2009, 13:31
Winstrol, правильно ли я понял, что ты говоришь про избыточность флагов OpenMode?


Название: Re: QFile::zxWZ() - как правильно открыть
Отправлено: spectre71 от Август 12, 2009, 13:34
Тут важно то, что открытие файла только на запись всегда и везде на практике приводит к truncate.
Не путай моды fopen с модами QIODevice!
У QIODevice есть для этого режим QIODevice::Truncate, читай доку!
Если бы было как ты говоришь, то QIODevice::Truncate лишний!


Название: Re: QFile::open() - как правильно открыть
Отправлено: Winstrol от Август 12, 2009, 14:02
Winstrol, правильно ли я понял, что ты говоришь про избыточность флагов OpenMode?
Ну, в некотором смысл можно так сказать. Компактнее всего записываются ключи для fopen.
В комбинации с ключом QIODevice::WriteOnly возможны 2 варианта
  • QIODevice::WriteOnly|QIODevice::Truncate
  • QIODevice::WriteOnly|QIODevice::Append
В комбинации с ключом QIODevice::ReadWrite возможны уже 3 варианта
  • QIODevice::ReadWrite
  • QIODevice::ReadWrite|QIODevice::Truncate
  • QIODevice::ReadWrite|QIODevice::Append

По умолчанию к QIODevice::WriteOnly дописывается QIODevice::Truncate. Т.е. в комбинации с QIODevice::WriteOnly режим QIODevice::Truncate не нужен, но не вообще не нужен (см. QIODevice::ReadWrite). Если бы сделали, чтобы по умолчанию к  QIODevice::WriteOnly дописывался QIODevice::Append, то он бы тогда не был нужен. Одно из двух. Первый вариант с точки зрения логики по умолчанию предпочтительней.
Стандартная библиотека С++ ведет себя аналогично Qt
http://msdn.microsoft.com/en-us/library/44cs32f9.aspx
Цитировать
ios_base::in becomes "r" (open existing file for reading).
ios_base::out or ios_base::out | ios_base::trunc becomes "w" (truncate existing file or create for writing).
ios_base::out | app becomes "a" (open existing file for appending all writes).
ios_base::in | ios_base::out becomes "r+" (open existing file for reading and writing).
ios_base::in | ios_base::out | ios_base::trunc becomes "w+" (truncate existing file or create for reading and writing).
ios_base::in | ios_base::out | ios_base::app becomes "a+" (open existing file for reading and for appending all writes).


Название: Re: QFile::open() - как правильно открыть
Отправлено: ритт от Август 12, 2009, 16:43
без экспрессий, пожалуйста.
мы об одном и том же говорим, но лишь разными словами...
я, например, согласен, что QIODevice::Truncate выглядит лишним, раз уж он всё-равно выставляется при отсутствии QIODevice::Append в режиме записи...но моё согласие/несогласие не имеет абсолютно никакого значения - до 5.0 всё-равно никто не будет пересматривать востребованность данных флагов по причинам совместимости...

а на данный момент у нас имеется проблема - недостаточно полная документация по этим флагам (и, возможно, форсирование Truncate в не совсем правильном месте) - вот её и решаем.


Название: Re: QFile::open() - как правильно открыть
Отправлено: Igors от Август 12, 2009, 18:19
Добрый день

Я не пытаюсь давать советы по Qt, но может быть мой "взгляд новичка" будет полезен
QIODevice::WriteOnly - перепишет первые 10 байт файла, остальные оставит как есть, размер файла будет 100 байт.
Лично в моем подсознании  "write only" стойко ассоциируется с (пере)созданием файла. Если файла нет - создать и открыть. Если есть - обрезать до 0 и открыть. Для перезаписи первых 10 байт из 100 надо открыть "read/write" (возможно с проверкой наличия файла).


Название: Re: QFile::open() - как правильно открыть
Отправлено: alex12 от Август 12, 2009, 20:40
QIODevice::WriteOnly - перепишет первые 10 байт файла, остальные оставит как есть, размер файла будет 100 байт.

Я был не прав. Такое поведение демонстрирует QIODevice::ReadWrite. А WriteOnly удаляет прежнее содержимое файла!


Название: Re: QFile::open() - как правильно открыть
Отправлено: spectre71 от Август 12, 2009, 22:17
QIODevice::WriteOnly - перепишет первые 10 байт файла, остальные оставит как есть, размер файла будет 100 байт.
Я был не прав. Такое поведение демонстрирует QIODevice::ReadWrite. А WriteOnly удаляет прежнее содержимое файла!
Как ни старанно :) ты был прав! Моды(режимы) QIODevice и fopen не обязаны соответствовать друг другу.
ReadWrite - дополнительные издержки(например под виндами)


Название: Re: QFile::open() - как правильно открыть
Отправлено: Igors от Август 13, 2009, 12:13
Как ни старанно :) ты был прав! Моды(режимы) QIODevice и fopen не обязаны соответствовать друг другу.
ReadWrite - дополнительные издержки(например под виндами)
Пришлось проверить  :)  Про винду не скажу но под Mac OSX 10.5.2 файл обрезается до 0 при открытии write only. Если везде так - зачем делать по-другому?


Название: Re: QFile::open() - как правильно открыть
Отправлено: spectre71 от Август 21, 2009, 15:28
Spectre, создавай таску в трекере и номерок сюда, а я отправлю исправление...
Что-то пришло, это то?

Цитировать
Hello,

This is an auto-reply to your email.

We have read your email but require more time to deal with it. We have
assigned it the issue number #259955. Please use this number if you email
us about the issue. We regret that we cannot guarantee a personal reply.
...
...


Название: Re: QFile::open() - как правильно открыть
Отправлено: ритт от Август 21, 2009, 16:17
близко. это автомат назначил таске внутренний номер и уведомл. теперь, жди ответа от человека - если посчитают, что это достойно быть исправленным, назначат публичный номер.