Как закрыть файл?

Страницы: 1
RSS
Как закрыть файл?
 
Господа, прошу подсказать.
Этой функцией я записываю текущую маркет дату
Код
function rec_big_data(file_path,value)         
if rn==nil then rn={} end         
   if file_open==nil then file_open={} end
      if file_open[file_path]==nil then
         rn[file_path]=io.open(file_path,"a+")
         file_open[file_path]=true
         mm("QL:open file "..file_path)
      end
      rn[file_path]:write(value.."\n")
      rn[file_path]:flush()
end   
file_path меняется три раза в день (в его название включён тикер, текущая дата и номер триместра: утренняя сессия 1, дневная сессия 2, вечерняя сессия 3).
вот пример historyGDM8 20180511-2.lua
В функции нет закрытия файла, потому что файл становится огромным, и скрипту тяжело его постоянно открывать-закрывать.
Робот пишет большое количество инструментов много дней подряд. Файлы остаются открытыми. Я замечаю, что виртуалка начинает тормозить. Думаю, что это из-за незакрытых файлов.
Подскажите пожалуйста как грамотно закрывать файл в конце триместра (при переходе на новый файл) с помощью close()?
Не могу сообразить, что в неё писать.
Спасибо.
 
Таблица дескрипторов файлов (rn) у Вас - глобальная. Где-то вне функции rec_big_data Ваш скрипт, судя по всему, в нужный момент понимает, что нужно сменить номер триместра. Что Вам мешает в этот момент просто позакрывать все файлы, зная их дескрипторы из таблицы rn?
 
Спасибо. подумаю
И ещё вопрос.
Я открываю много файлов с помощью dofile
Файлы имеют вид

Файлы  огромных размеров.
После исполнения dofile эти файлы остаются открытыми? Надо ли заботиться о том чтобы их закрывать?
 
Цитата
Let_it_go написал:
После исполнения dofile эти файлы остаются открытыми? Надо ли заботиться о том чтобы их закрывать?
Нет. Они закрываются внутри dofile, причём ещё до того, как запустится интерпретатор кода загруженного из этих файлов.
 
Спасибо за ответы.
Разрешите задать ещё вопрос.
Я открыл файл с помощью io.open.
После этого я остановил скрипт.
Файл останется открытым, верно?
Если да, то следующий вопрос.
Я запустил скрипт и снова открыл этот же файл с помощью io.open. Теперь у меня два открытых файла?
---
И ещё один вопрос. Как мне принудительно закрыть файл, имея не дескриптор, а только путь file_path?
--

Спасибо.
 
Как мне отлавливать средствами Луа, Windows или специальных программ открытые в данный момент луа-файлы?
В Windows server 2003 эта функция не работает и не лечится. Я искал советы по данной проблеме, но они не сработали.
 
Цитата
Алексей написал:
Таблица дескрипторов файлов (rn) у Вас - глобальная. Где-то вне функции rec_big_data Ваш скрипт, судя по всему, в нужный момент понимает, что нужно сменить номер триместра. Что Вам мешает в этот момент просто позакрывать все файлы, зная их дескрипторы из таблицы rn?
Добавил в функцию переменную files_qty - это количество бумаг, которые пишутся. Если размер таблицы rn больше files_qty, значит сменился триместр и надо закрывать старые файлы. Очевиден недостаток: при смене триместра функция один раз закроет хороший файл - файл новенького триместра. Потом ей придётся его переоткрывать.

Спасибо за комментарии. Они очень помогают.
 
Цитата
Let_it_go написал:
Я открыл файл с помощью io.open.
После этого я остановил скрипт.
Файл останется открытым, верно?
Нет. Закроется.
Цитата
Let_it_go написал:
И ещё один вопрос. Как мне принудительно закрыть файл, имея не дескриптор, а только путь file_path?
Никак. Если речь идёт о дескрипторе файла в Lua, который имеет тип «userdata».
Цитата
Let_it_go написал:
Как мне отлавливать средствами Луа, Windows или специальных программ открытые в данный момент луа-файлы?
Можете использовать для этих целей Process Explorer (https://ru.wikipedia.org/wiki/Process_Explorer).
Цитата
Let_it_go написал:
В Windows server 2003 эта функция не работает и не лечится. Я искал советы по данной проблеме, но они не сработали.
Вы не то смотрите. Эта оснастка «Общие папки» показывает файлы открытые по сети (по протоколу SMB), и это никакого отношения к файловой системе и файлом открытым локально не имеет. Оснастка у вас не работает скорее всего, если мне не изменяет память, потому что не запущена одна из служб, на подобие «Files and Folder bla bla bla» или что-то вроде того... чтобы посмотреть системные ресурсы открытые конкретным процессом, в том числе и файлы, используйте Process Explorer.

Цитата
Let_it_go написал:
Добавил в функцию переменную files_qty - это количество бумаг, которые пишутся. Если размер таблицы rn больше files_qty, значит сменился триместр и надо закрывать старые файлы. Очевиден недостаток: при смене триместра функция один раз закроет хороший файл - файл новенького триместра. Потом ей придётся его переоткрывать.
1. Файл закрывайте там, где вы определяете смену «триместра», то-есть там, где у вас создаётся новая path. И там же открывайте сразу новый по новому имени. А внутри функции записи оставьте собственно только запись.
2. Уберите строчку «rn[file_path]:flush()», это тяжёлая операция, на которой у вас всё будет тормозить. Этот flush делайте только перед самым закрытием файла, то-есть перед close().
3. Зачем вам вторая таблица file_open где вы ставите true, она просто дублирует вашу основную таблицу rn с дескрипторами. Уберите её из кода, а открытие файла для конкретного file_path проверяйте условием «nil == rn[file_path]», а после закрытия файла обнуляйте этот же элемент через «rn[file_path] = nil».
4. Выражение «#rn>files_qty» не сработает, потому что у вас таблица строится по строковым ключам, а оператор # работает только для индексированных по номерам таблиц, то-есть когда они используются как массивы.
5. Структура кода у вас неправильная, запись в файл нужно делать после проверки на nil возврата функции io.open. Вы эту проверку вообще не делаете после вызова io.open, а делает только при повторном вызове основной функции при следующей записи. У вас там нужно часть строк стереть, а часть местами поменять, чтобы привести код в порядок.
 
Suntor
если я уберу flush при каждой записи, не появятся ли чрезмерные риски того, что какая-то часть данных не запишется?
Ну например я принудительно остановил скрипт.
Ведь в этом случае какие-то строчки потеряются? Или не потеряются?
 
Цитата
Let_it_go написал:
Suntor
если я уберу flush при каждой записи, не появятся ли чрезмерные риски того, что какая-то часть данных не запишется?
Ну например я принудительно остановил скрипт.
Ведь в этом случае какие-то строчки потеряются? Или не потеряются?
При останове скрипта луа машина, встроенная в терминал, автоматически закрывает все файлы посредством close(). Это происходит с версии qlua 6.xx вроде.

Вызов close() всегда подразумевает flush() - так устроена библиотека С.

Поэтому вы ничем не рискуете.

flush() имеет смысл только в том случае, если вы в реальном времени другой программой читаете создаваемый файл. Flush() сбрасывает файловый буфер на диск немедленно. Без него файловые операции кешируются в памяти. В момент закртытия файла все буферы сбрасываются на диск.
www.bot4sale.ru

Пасхалочка для Алексея Иванникова: https://forum.quik.ru/messages/forum10/message63088/topic7052/#message63088
 
Спасибо, друзья. Проясняется, хотя мне очень тяжело с этим разбираться. Не то образование...
Вот текущая редакция функции, которая пишет слепки стакана. Триместр сменился, если путь поменялся. В этом случае закрываем старый файл, открываем новый.
 
Цитата
Let_it_go написал:
Спасибо, друзья. Проясняется, хотя мне очень тяжело с этим разбираться. Не то образование...
Вот текущая редакция функции, которая пишет слепки стакана. Триместр сменился, если путь поменялся. В этом случае закрываем старый файл, открываем новый.
В таком виде, как правильно написал s_mike@rambler.ru, flush перед самым close смысла особого не имеет. Поэтому можете стереть там строчку.
Мне вообще ваш подход не нравится. Вы пытаетесь запихать в одну функцию всю логику работы с файлами. Поэтому у вас в этой функции будет куча лишних проверок замедляющий её основную работу — запись. Но даже, в рамках вашего подхода, я бы всё переписал по-другому. Как-то вот так:
Код
rn = rn or {}
rn[paper] = rn[paper] or {}
if file_path~=rn[paper].file_path then
    if rn[paper].handler then
        rn[paper].handler:close()
    end
    rn[paper].handler:io.open(file_path, "a+")
    if rn[paper].handler then
        rn[paper].file_path = file_path
    else
        mm("QL:open file error "..file_path)
    end
end
if rn[paper].handler then
    rn[paper].handler:write(value.."\n")
end
— код не проверял, пишу из головы, чтобы передать суть.
 
Выключил flush.
Почему-то на всех сегодняшних файлах стал появляться одинаковый глюк: вот такое искажение:

неадекватная (неполная строчка). Плюс пропуск нескольких секунд. До ошибки время 184444, после ошибки 184449. Может быть я в это время его включал-выключал, но я увы не помню этот момент. Днём на 1 из файлов было то же самое. Раньше, когда flush работал, такого не было. Видоизменил функцию. Добавил в неё flush 1 раз в 100 записей по данной бумаге:
Код
count[paper]=(count[paper] or 0)+1
   if count[paper]==100 then
      rn[paper].handler:flush()
      count[paper]=0
   end
 
Цитата
Let_it_go написал:
Выключил flush.
Почему-то на всех сегодняшних файлах стал появляться одинаковый глюк: вот такое искажение:
А у вас получение данных и запись их в файл идут в одном потоке или в разных? Очень на «рассинхрон» похоже...
 
Получаю данные колбеком OnParam. В него вставлена обсуждаемая функция.
 
Вот ещё один случай. Что характерно, снова перед закрытием сессии. Почти в то же время.
 
то есть мой метод не сработал. flush раз в 100 записей не помог.
 
Цитата
Let_it_go написал:
Получаю данные колбеком OnParam. В него вставлена обсуждаемая функция.
А внутри OnParam вы несколько раз getParamEx дёргаете для разных параметров? И потом их объединяете в таблицу или строку и кидаете дальше в вашу функцию записи?... если так, то сдаётся мне вы оба (вы и ваш коллега с соседней темы «Некоторые глюки в 7.2») встретились, собратья по несчастью... с одной и той же проблемой...

Покажите, что вы делаете в OnParam, и как у вас идёт вызов вашей функции rec_big_data...
 
Suntor,
эта проблема появилась только сейчас, когда я перестал делать flush на каждой записи. До этого я несколько недель подряд записывал каждый день без перерыва и такой проблемы не было. Она абсолютно новая.
Вызываю я функцию так:
 
Цитата
Let_it_go написал:
Вызываю я функцию так:
При таком вызове рваться не должно... у вас какая-то серьёзная проблема с вводом/выводом. Возможно дело даже не в Lua, а в вашей виртуальной машине, настройках виртуального диска и пр.

Попробуйте отключиться кэш совсем, через file:setvbuf:
Код
function rec_big_data(file_path, value, paper)
    rn = rn or {}
    rn[paper] = rn[paper] or {}
    if file_path~=rn[paper].file_path then
        if rn[paper].handler then
            rn[paper].handler:close()
        end
        rn[paper].handler = io.open(file_path, "a+")
        if rn[paper].handler then
            rn[paper].handler:setvbuf("no")        --<<<--- отключение кэша
            rn[paper].file_path = file_path
        else
            mm("QL:open file error "..file_path)
        end
    end
    if rn[paper].handler then
        rn[paper].handler:write(value.."\n")
    end
end
а в другой день, наоборот, увеличьте его до 1 МиБ, заодно сравните скорость работы, и посмотрите, будут ли глюки и при каком режиме кэширования:
Код
            rn[paper].handler:setvbuf("full", 1024*1024)
 
Есть гипотеза для объяснения проблем с "битыми" строчками: вы пишете в один физический файл, используя несколько разных дескрипторов на уровне lua.
Код
local f1 = io.open("filename.txt", "a+")
local f2 = io.open("filename.txt", "a+")
f1:write("Some text")
f2:write("Another text")
f1:close()
f2:close()
Страницы: 1
Читают тему
Наверх