На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual Basic: Общие вопросы
Здесь обсуждаются вопросы по языку Visual Basic 1-6 (а так же по схожим языкам, как, например, PowerBASIC).
Вопросы по Visual Basic .NET (это который входит в состав Visual Studio 2002/2003/2005/2008+, для тех, кто не в курсе) обсуждаются в разделе .NET.

Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что Вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются. Студенты, вам сюда: ПОМОЩЬ СТУДЕНТАМ!
4. Используйте теги [ code=vba ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Формулируйте свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной (и более) давности, без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта user posted image FAQ Раздела user posted image Кладовка user posted image Наши Исходники user posted image API-Guide user posted image Поиск по Разделу user posted image MSDN Library Online user posted image Google

Ваше мнение о модераторах: user posted image SCINER, user posted image B.V.
Модераторы: SCINER, B.V.
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Как избежать сбоя при записи в файл?
    Есть у меня прога, которая постоянно держит открытым файл (For Random) и записывает в него данные по 128 байт. Сегодня обнаружил в этом файле мусор. Предполагаю, что мусор туда попал при аварийной перезагрузке компа. Заметил, что часто сбой происходит при открытом сайте vk.com (слушаю музыку), у них там постоянно баги вылазят. Из любопытства просмотрел данные мусора - там оказался текстовый код из часто открытого у меня ДРУГОГО проекта VB, т.е. из оперативки или временных файлов VB(?). Интересно, но не суть важно. Запись в файл происходит приблизительно 3 раза в минуту. Есть ли смысл постоянно закрывать/открывать файл, чтобы уменьшить вероятность записи в данные мусора или же так больше вероятность нарваться на ошибку и стоп проги? Или лучше пожалеть винт (скорость проги не играет роли)?
    Сообщение отредактировано: BlackSun -
      Цитата BlackSun @
      Есть ли смысл постоянно закрывать/открывать файл, чтобы уменьшить вероятность записи в данные мусора

      Да.

      Цитата BlackSun @
      или же так больше вероятность нарваться на ошибку и стоп проги?

      Вообще-то ошибки принято обрабатывать, стараясь восстановить нормальную работу программы.

      Цитата BlackSun @
      Или лучше пожалеть винт

      Дополнительной нагрузки на хард практически не будет - последние блоки файла стопроцентно лежат в файловом кэше ОС.
        Цитата BlackSun @
        . Есть ли смысл постоянно закрывать/открывать файл, чтобы уменьшить вероятность записи в данные мусора или же так больше вероятность нарваться на ошибку и стоп проги? Или лучше пожалеть винт (скорость проги не играет роли)?

        Сбрасывай буфер файла после каждой записи. FlushFileBuffers или что-то типа того.
          Олег М
          Да у него по 20 секунд между записями, а autoflush емнип 2 секунды...
            Цитата Akina @
            последние блоки файла стопроцентно лежат в файловом кэше ОС
            так значит отсюда мусор попадает ко мне? таки надо делать сброс кеша сразу...

            Добавлено
            А если я буду писать единовременно по несколько записей, столько, чтобы заполнить весь этот буфер сразу - места мусору не будет. Какой у него размер?
              Нет, мусор из буфера записи дисковой подсистемы ОС. Запись же идёт блоками (ну считай кластерами), а итоговый размер пишется только при фиксации (закрытии) файла. Вот всё, что за реальным концом, и будет забито случайным хламом.

              Цитата BlackSun @
              Какой у него размер?

              Вот кто бы знал... в первом приближении - кратно размеру кластера накопителя, но ещё и делит нацело стандартный блок предчтения. Так что нечто бинарно-круглое от 4 кбайт до 2 Мбайт. А с учётом того, что буферов не один, а несколько независимо-последовательных (дисковая-файловая-приложения, и это на самом деле не всё), гадать вообще бессмысленно.

              Разумнее записывать не по 128, а поболе, довешивая этим 128 ещё контрольную сумму. Тогда по её невалидности инфо от хлама отличить - раз плюнуть.
                Можно довешивать CRC, но не хочется увеличивать объём данных. Хотелось понять принцип попадания мусора в данные. Если в буфер попадают данные с разных приложений, то там же должны быть какие-то разграничители? При сбое просто не записывается конец файла и файл остаётся с мусором в конце? Этот мусор тогда не должен превышать по размеру размер буфера ОС? Он имеет произвольную длину или кратную 2^n (вместе с моей записью в начале)? Или как?
                  Цитата BlackSun @
                  . Хотелось понять принцип попадания мусора в данные.

                  Покажи код, как ты пишешь в файл.
                    Цитата BlackSun @
                    Хотелось понять принцип попадания мусора в данные.

                    Очень просто.
                    Ты открываешь файл. Под него резервируется буфер в памяти. Само собой там изначально мусор.
                    Ты что-то пишешь в файл, а на самом деле в этот буфер. Соответственно в той части буфера, куда байты не кладутся, остаётся мусор.
                    При сбросе на диск ОС записывает весь блок (минимально - кластер). Соответственно в неиспользованной с твоей точки зрения части кластера пишется мусор.
                    Пока файл открыт, ОС фиксирует только занятые файлом кластеры. Только при закрытии она в элементе каталога укажет точный размер в байтах, а пока формальный размер файла округлён вверх до кластера, причём эти сведения есть только в оперативке.
                    Если происходит аварийное завершение, данные об актуальном размере записаны не будут. В то время как данные об использовании кластеров - уже записаны (они пишутся непосредственно в момент их корректировки).
                    При следующем старте ОС обнаружит в журнале тома сведения, что файл не закрыт корректно. Сведения об истинном размере - утрачены. Соответственно будет установлен такой размер, чтобы гарантированно ничего не потерять - т.е. по максимуму.
                    Итог - тот мусор, который находится в неиспользованной части кластера и считался бы несуществующим при штатном закрытии, стал легитимным содержимым файла.
                      Цитата Akina @
                      Ты открываешь файл. Под него резервируется буфер в памяти. Само собой там изначально мусор.

                      Не "само собой". Если речь идет о системном файловом кэше, то он работает по принципу файл-маппинга, при котором под буфер всегда выделяются предварительно обнуленные страницы памяти (из соображений безопасности\приватности\конфиденциальности). Соотв-но, если в винде размер кластера равен или кратен размеру страницы, то мусор в конце файла может возникнуть только в случае, когда ОС сначала выделяет новые кластеры для файла и изменяет его размер, и только потом записывает данные - тогда при сбое\прерывании записи в конце файла может остаться мусор от старых данных на диске.
                        Цитата leo @
                        Если речь идет о системном файловом кэше

                        Речь о всех буферах - формируемых VB, формируемых файловым кэшем ОС, а если есть - и других.

                        Цитата leo @
                        только в случае, когда ОС сначала выделяет новые кластеры для файла и изменяет его размер, и только потом записывает данные

                        Если изменяется цепь занимаемых файлом кластеров, Win всегда сначала пишет в тело файла, потом помечает кластеры как использованные, и только потом изменяет цепь кластеров файла. Такая последовательность действий минимизирует вероятность возникновения ошибки, а в случае её возникновения - минимизирует тяжесть повреждения. Когда пишется изменённый размер файла, точно не скажу, надо смотреть у Руссиновича, но в случае скоропостижной смерти ОС после автовосстановления при старте размеры открытых на момент падения ОС файлов или корректны, или увеличиваются до кратности кластеру, так что скорее всего размер меняется в самую последнюю очередь, уже после работы с занимаемыми кластерами..
                          У меня размер кластера на томе винта 16КБ и насколько я знаю, минимальная порция записи на диск 512 байт. Сбой случается редко, максимум 2-3 раза мог быть. Я обнаружил мусора в файле >300КБ, и, наверняка, в файле ещё что-то осталось (я отсеивал мусор по некорректным значениям полей UDT-записи). По размерам не сходится, если мусор пишется не более 1 кластера. Т.к. в мусоре был программный код другого проекта, буфера были явно не обнулены. В целом я придумал корректную запись в файл без CRC, но для меня картина записи мусора осталась не прояснённой до конца.
                            Akina
                            Как бы то ни было, а источником мусора в файле может являться только сам диск, когда в результате сбоя последний кластер записывается из памяти на диск не полностью и соотв-но в его хвосте остаются старые мусорные данные на диске.
                            Ни с какими буферами в памяти это невозможно, особенно когда этот мусор представляет собой данные какого-то другого приложения (?!)
                              Насколько я знаю, физически данные записываются секторами, тут просто не записались служебные данные после записи самих данных, а именно размер файла. Так что мусор идёт из памяти. С Akina согласен. Открытым же остался вопрос большого объёма самого мусора... Возможно, файлу устанавливается некий логический размер после сбоя, и добавляются ещё сектора/кластера с диска (и тут уж мусор идёт от этих кластеров).

                              Из сети:
                              Цитата
                              Каждая дорожка разбивается на фрагменты, называемые секторами (sectors) или блоками (blocks), так что все дорожки имеют равное число секторов, в которые можно максимально записать одно и то же число байтов. Сектор имеет фиксированный для конкретной системы размер, выражающийся степенью двойки. Чаще всего размер сектора составляет 512 байтов...
                              Сектор  наименьшая адресуемая единица обмена данными дискового устройства с оперативной памятью....
                              Операционная система при работе с диском использует, как правило, собственную единицу дискового пространства, называемую кластером (cluster). При создании файла место на диске ему выделяется кластерами. Например, если файл имеет размер 2560 байт, а размер кластера в файловой системе определен в 1024 байта, то файлу будет выделено на диске 3 кластера....


                              Добавлено
                              Вспоминая характер мусора, я видел разные значки (как письмо на почте в не той кодировке) - похоже, это был мусор из памяти, а ещё видел код на VB - это могут быть временные файлы VB, которые были удалены с диска, но данные на секторах остались...
                              Сообщение отредактировано: BlackSun -
                                Цитата BlackSun @
                                Так что мусор идёт из памяти

                                Не может он идти из памяти, особенно данные из другого приложения. В противном случае, винду с ее защитой\изоляцией памяти между процессами можно выкинуть коту под хвост.
                                "Нет, Шура. Только кража" (С). Т.е. мусор м.б. только с диска, когда при сбое установленный размер файла превышает размер реально записанных данных.

                                PS: При создании и/или увеличении размера файла защита тоже действует, поэтому в штатном режиме 1) данные пишутся на диск всегда целыми кластерами с обнуленным хвостом последнего кластера, чтобы затереть старые данные на диске, 2) при записи с пропусками (установкой SetFilePointer за пределы текущего размера файла с последующим вызовом WriteFile или SetEndOfFile) в образовавшуюся дырку автоматически записываются нули.

                                Цитата BlackSun @
                                Вспоминая характер мусора, я видел разные значки (как письмо на почте в не той кодировке) - похоже, это был мусор из памяти

                                Это м.б. данные какого-то двоичного файла на диске - удаленного или урезанного
                                Сообщение отредактировано: leo -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0488 ]   [ 17 queries used ]   [ Generated: 28.03.24, 13:35 GMT ]