Lua создать файл если не существует

Обновлено: 07.07.2024

Когда-то я разрабатывал свою игру и задался вопросом: а какой формат данных лучше использовать для конфигурационных файлов?
Ведь удобно, когда создаёшь какой-либо объект, задавать различные начальные параметры не в самом коде, а в отдельных файлах. Это позволяет изменять некоторые параметры объектов без рекомпиляции, да и вообще даёт возможность менять их людям далёким от программирования.
Разработчики используют разные форматы: одни используют JSON, другие — XML, либо другие форматы данных. Ну а некоторые вообще хранят данные в .txt файлах или пишут свои парсеры. После рассмотрения различных форматов я остановился на Lua.

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

  • Lua легко использовать без дополнительных зависимостей (кроме одной библиотеки Lua и трёх .h файлов).
  • В Lua файлах данные можно инициализировать с помощью математических выражений или функций, написанных на Lua. Например:

Пример

Допустим, есть файл Player.lua

С простым классом данные можно будет получать так:


Внимание, чтобы код был понятен, рекомендуется прочесть информацию о том, как работает стек Lua и посмотреть на простейшие примеры.
Почитать можно здесь.

Начнём с создания класса:

lua_getdefault используется для того, чтобы вернуть какое-либо нулевое значение, если произошла ошибка. И если для чисел можно вернуть ноль, то для строк, например, это не сработает, поэтому делаем специализацию шаблона (этот код будет в хэдере).


А теперь напишем шаблонную функцию get.
Для начала напишем функцию lua_gettostack, которая заносит переменную на вершину стека
Разберём алгоритм на примере. Пусть нужно получить переменную «player.pos.X» из файла Player.lua
Проходим циклом до первой точки, при этом добавляя прочитанные символы в переменную «var».
«player» — таблица, которая является глобальной, поэтому получаем её с помощью lua_getglobal.
«pos» и «X» — это уже данные, которые не являются глобальные, но их можно получить с помощью lua_getfield, т.к. сама таблица player находится в вершине стека.
Затем уже в шаблонной функции get выполняется специфичная для типа данных функция, очищается стек и возвращается искомое значение, а в случае ошибки — вызывается функция lua_getdefault.


Возвращаемся к методу get:

Осталось лишь добавить специализиации шаблонов(пример для некоторых типов данных):


На этом всё. Напоминаю, весь код в статье есть здесь. Там же можно найти пример использования класса.

Чтобы некоторые студенты могли лучше изучить обратный инжиниринг Lua, я объединил некоторые из собранных материалов в часть работы по шифрованию и дешифрованию Lua для вашей справки. Прежде чем читать этот раздел, вам все еще необходимы базовые знания Lua. Вот «Благодарность за источник Lua» [19] Юньфэна Далу, и его рекомендуется изучать в сочетании с поисковыми системами.

Статья состоит из 2 частей: первая часть знакомит с соответствующими статьями о шифровании и дешифровании lua, а вторая часть знакомит с соответствующими инструментами lua.

Введение в статью

В этом разделе представлены различные статьи, связанные с Lua в Интернете, включая шифрование и дешифрование Lua, такие как анализ формата файлов, игры и соревнования на основе Lua, технология перехвата Lua и т. Д.

1. Начало работы с шифрованием и дешифрованием Lua:

Не-Bug 2 написал 4 статьи о формате и байт-коде файлов luac и luajit, а также о 010Editor с открытым исходным кодом, разбирающем код шаблона luac и luajit. Одноклассник Ганлв [7] написал 7 серий руководств по шифрованию и расшифровке Lua в My Love Cracking. Tencent gslab [9] написал вводное введение в реверс-инжиниринг игр на Lua, которое представляет собой более раннюю статью о расшифровке игр на Lua. Одноклассник INightElf [10] написал статью о введении декомпиляции lua-скриптов.

2. Мобильные игры на основе Lua:

Lua можно использовать не только для конечных игр, но и для мобильных игр, и из-за популярности мобильных игр он стал стимулом для обмена статьями по обратному анализу lua. Одноклассник wmsuper [11] расшифровал lua-скрипт игры Happy Xiaoxiaole от Tencent на платформе Android, а затем модифицировал lua-скрипт с целью обмана. Студенты Unity [8] расшифровали и изменили поток мобильной игры Lua «Place Jianghu» с помощью метода перехвата для достижения цели изменения игрового вознаграждения. Одноклассник LittleNA [12] расшифровал сценарии lua 3 мобильных игр 3 способами и исправил порядок кодов операций lua в мобильных играх в стиле фэнтези.

3. Соревнование на основе Lua:

С развитием отечественного CTF технология lua также используется в соревнованиях. Kanxue ctf2016 вопрос 2 [13], вопрос 15 [14] 2017 года и последний вопрос 2 [15] Tencent Game Security 2018 - все они используют движок Lua в качестве носителя конкурса CrackMe, в котором Kanxue 2016 использует код lua для проверки алгоритма. Реализован и скомпилирован в luac и, наконец, модифицирован заголовок файла luac, что заставило инструмент декомпиляции сообщать об ошибках; см. Вопрос Xue 2017 с использованием оболочки и много путаницы, последний шаг - простая операция XOR luajit; технология lua, используемая Tencent 2018, даже больше По сути, расширенная версия заключается в изменении порядка кодов операций lua и использовании lua для записи виртуальной машины. Описание трех вышеуказанных вопросов можно найти в Интернете, и заинтересованные друзья могут попрактиковаться в своих руках и углубить впечатление.

Перехватчик - это распространенный метод модификации программного процесса; в lua также есть перехватчик. Студент Цзэн Баньсянь [9] Кансюэ опубликовал метод модификации игровой логики путем подключения байт-кода lua и выпустил механизм сборки lua. В блоге Nikc Cano [5] была опубликована статья о Hooking luajit, которую перевел одноклассник Xiaowei [6], который заинтересовался этим.

Введение в инструмент

У игр lua и luajit с обратным дешифрованием есть связанные инструменты. В этом разделе представлены некоторые основные инструменты.

1. Связанные с Lua:

chunkspy: очень полезный инструмент анализа lua, написанный на самом языке lua. Он анализирует весь байтовый файл lua, и, поскольку его вывод представляет собой сборочную форму lua, совместимость очень высока, а также вызывает определенные трудности с чтением. Chunkspy может не только анализировать файлы luac, но и включает интерактивную команду, которая может преобразовывать входной сценарий lua в форму сборки байт-кода lua, что очень полезно для изучения байт-кода lua. Этот скрипт интегрирован в инструмент luadec, и в настоящее время поддерживаются версии также lua5.1, 5.2 и 5.3.

unluac: это также декомпилятор lua с открытым исходным кодом, написанный на языке java и имеющий более низкую совместимость, чем инструменты luadec. Как правило, он используется редко и поддерживает только lua5.1. Вы можете попробовать его, когда вышеперечисленные инструменты не работают.

2. Связанные с Luajit:

luajit-decomp [17]: Инструмент декомпиляции luajit с открытым исходным кодом на github, написанный на языке au3. Сначала преобразуйте файл байт-кода luajit в сборку через собственный exe-файл luajit, а затем инструмент преобразует сборку luajit в язык lua. Поскольку в дизассемблированном байт-коде luajit отсутствует много информации, такой как имена переменных, имена функций и т. Д., Результат декомпиляции читается нечетко, подобно F5 в IDA. Но совместимость очень хороша, поскольку его можно разобрать, его можно декомпилировать, поэтому вам нужно заменить соответствующую версию движка luajit при его использовании (для удовлетворения потребностей разборки). В настоящее время поддерживаются все версии luajit.

ljd [18]: это также инструмент декомпиляции luajit с открытым исходным кодом на github. Он написан на python. Он отличается от того, как luajit-decomp декомпилирует сборку luajit. Он анализирует весь файл luajit с самого начала и может получить дополнительную информацию и степень восстановления. Выше, но из-за большей точности совместимость будет слабее. Проверьте вилку этого проекта, чтобы получить больше совместимых версий. В настоящее время поддерживаются версии luajit2.0, luajit2.1 и т. Д.

Используйте отладчик для отладки, почему инструмент декомпиляции анализирует ошибку и устраняет причину.

Используйте отладчик для отладки того, как исходный механизм анализирует файл.

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

Следующие три примера будут использованы для борьбы и исправления декомпиляции Lua.

Пример 1: простой вопрос

Пример 2: Конкурс Tencent Game Security 2018

Проблема с кодом операции и ее решение

Цель исправления кода операции состоит в том, что при вводе файла luac субъекта инструмент дизассемблирования Chunkspy и инструмент декомпиляции luadec могут выводить правильные результаты.

Сначала мы анализируем файл tmgs.dll движка lua в ida, а затем находим функцию luaV_execute (ищем строку «предел для 'должен быть числом») и обнаруживаем, что параметр case под переключателем (код операции lua) не работает Да, здесь мы можем подтвердить, что код операции виртуальной машины lua для этого вопроса был изменен.

Далее выполняем ремонтные работы. Очень трудоемкий метод - восстанавливать один за другим код операции, анализировать код для каждого случая и выяснять порядок соответствующего кода операции. Но мы не должны так сильно беспокоиться по этому вопросу. Путем сравнительного анализа мы обнаружили, что обычная версия вопроса не изменяла код операции:

Функция luaV_execute обычного движка lua Функция luaV_execute расширенного движка lua


Замечено, что тема расширенной версии только изменяет значение каждого случая или отображает несколько значений в один и тот же код операции, но не нарушает код в случае (то есть порядок, в котором виртуальная машина анализирует код кода операции, не изменился, просто Соответствующее значение было изменено, что отличается от метода нарушения кода операции в мобильной игре в жанре фэнтези). Поскольку lua5.3 использует только код операции 0x2D, ​​а код операции имеет длину 6 бит (0x3F), этот вопрос будет отображать оставшиеся неиспользуемые байты в тот же код операции.При восстановлении требуется только обратная операция. , На этом этапе анализа получился наш план ремонта:

Экспорт текста 2 версий luaV_execute через ida

Извлеките таблицу восстановления кода операции через скрипт Python

После того, как инструменты (Chunkspy и luadec) инициализируют файл lua, замените код операции таблицей восстановления

Тестовый запуск, исправление других ошибок

Первым шагом является прямой экспорт IDA вручную: Файл -> Создать файл -> Создать файл LST; второй шаг использует анализ Python, код выглядит следующим образом:

Наконец, замените полученную таблицу восстановления в инструмент. Точка восстановления Chunspy находится в функции DecodeInst. Измененный результат будет следующим:

Тест обнаружил ошибку, результат ошибки:


Из результата ошибки видно, что номер версии файла luac неверен. Версия lua 11 не может быть распознана здесь, на самом деле проблема, специально разработанная для того, чтобы инструмент распознал ошибку. Мы изменили 4-й байт (номер версии lua) 11 файла на 53 в порядке. Правильный результат:


Точка восстановления Luadec находится в функции f_parser файла ldo.c, и добавьте функцию RepairOpcode, восстановление будет следующим:

Запустите его, найдите ошибку и оставайтесь в функции StringBuffer_add, где str указывает на неправильное место, вызывая ошибки чтения строки:


Здесь мы исправили код операции, и Chunkspy успешно разобрался, но с декомпиляцией luadec все еще есть проблемы, которые мы проанализируем в следующем разделе.

Проблема декомпиляции и ее устранение

Я просмотрел записи нескольких крупных парней и обнаружил, что ни один из них не устранил эту проблему.В процессе решения проблемы непосредственно анализировался ассемблерный код Lua. Давайте посмотрим на причину ошибки и посмотрим на стек вызовов vs:


Выяснилось, что функция верхнего уровня - это функция listUpvalues, что означает, что luadec допустил ошибку при синтаксическом разборе значений. Глубокий анализ показал, что имя переменной upvalue в файле было стерто, что привело к ошибке синтаксического анализа. Нам нужно только использовать функцию ProcessCode (декомпилировать. c) Перед вызовом функции listUpvalues ​​просто добавьте временное имя upvalue. Измените код следующим образом:

Наконец, luadec работает отлично, и декомпиляция прошла успешно.

Пример 3: Мобильная игра Fantasy Westward Journey

В этом разделе рассказывается о некоторых проблемах, обнаруженных при обучении взламывать код Lua мобильной игры Fantasy Westward Journey в прошлом году. Они организованы и распространены сегодня, поэтому могут не подходить для текущей версии мобильной игры в стиле фэнтези. Мы все еще используем его для справки.

На тот момент при декомпиляции мобильной игры Fantasy Westward Journey возникло около 12 проблем. После модификации исходный код Lua можно было полностью воспроизвести. Здесь использовалась версия luadec5.1.

Вопрос 1: Поскольку код операции Lua мобильной игры мечты был изменен, предыдущее решение заключалось в том, чтобы найти код операции мечты, заменить исходный код операции инструмента декомпиляции и изменить режим операции перед декомпиляцией. Проблема в том, что результаты некоторых тестов в порядке, но когда байт-код luac всей мобильной игры будет декомпилирован, появятся различные ошибки. Причина в том, что luadec5.1 по умолчанию использует порядок кодов операций во многих местах и ​​делает специальные Обработка, поэтому вам нужно найти эти специальные места обработки и изменить их одно за другим. Но это очень проблематично, поэтому я думаю о другом способе, вместо изменения исходного кода операции и режима операции, но когда luadec анализирует байт-код, восстанавливает код операции до исходного кода операции.

Решение 1. Найдите местоположение кода синтаксического анализа в lundump.c -> LoadFunction -> LoadCode (местоположение не уникально, вы можете увидеть исправление игры Tencent в предыдущем разделе), когда функция LoadCode выполняется, переменная f указывает на Структура кода, после которой выполняется написанная вами функция ConvertCode, выглядит следующим образом:

Вопрос 2: Произошла ошибка при декомпиляции заголовка файла - DECOMPILER ERROR: Overwrite pending register.

Решение 2. Анализ показал, что изначально это было вызвано ошибкой при синтаксическом анализе OP_VARARG. Основная функция OP_VARARG - копировать параметры B-1 в регистр A, в то время как инструмент декомпиляции копирует параметры B и добавляет еще один. Измененный код выглядит следующим образом:

Вопрос 3: Произошла ошибка декомпиляции в таблице синтаксического анализа - ОШИБКА ДЕКОМПИЛЕРА: Не знаете об использовании. Регистры!

Решение 3. Анализ показал, что параметр c OP_NEWTABLE здесь представляет размер ключа в хэш-таблице, а параметр c был неправильно преобразован в декомпилированном коде, что привело к ошибке синтаксического анализа. Измененный код выглядит следующим образом:

Вопрос 4: Ошибка инструмента декомпиляции и выход.

Решение 4. Отслеживание обнаружило, что в функции AddToTable PrintTable вызывается, когда ключ равен 0, а PrintTable освобождает таблицу, и при следующем вызове таблицы происходит сбой доступа к памяти. Измените код следующим образом:

Вопрос 5: Когда функция возвращает результат с несколькими значениями и назначается нескольким переменным, ошибка декомпиляции выглядит следующим образом (дизассемблирование lua):

Решение 5. Если reg пуст, а Rcall не пуст, добавьте отметку return more и измените 2 функции:

Вопрос 6: Ошибка декомпиляции возникает, когда функция имеет только один оборот.

Вопрос 7: Произойдут некоторые ошибки инициализации таблицы.

Вопрос 8: Произошла ошибка при разборе части переменных параметров, но инструмент не сообщает об ошибке при декомпиляции.

Решение 8. Когда is_vararg равно 7, F-> freeLocal добавляет еще раз:

Вопрос 9: Инструмент декомпиляции выводит на китайском языке символы типа url (аналогично "\ 230 \ 176 \ 148 \ 231 \ 150 \ 151 \ 230 \ 156 \ 175"), а не китайские.

Решение 9. В функции DecompileString в файле proto.c закомментируйте строковую функцию преобразования по умолчанию:

Затем добавьте условия ограничения для оценки в следующих 3 местах, потому что байт char является отрицательным числом для китайских символов, поэтому функции isalpha и isalnum будут работать неправильно, поэтому добавьте условия ограничения, меньшие или равные 127:

Вопрос 10: Не удалось разобрать. Поскольку некоторые файлы содержат очень длинные строки, вызов функции sprintf не выполняется.

Решение 10. Увеличьте размер кеша:

Вопрос 11: Когда op_setlist opcode b == 0, декомпиляция не выполняется.

Решение 11. При обнаружении оператора lua, подобного следующему, инструмент декомпиляции завершится ошибкой. Ситуация находится в файле @ lib_ui.lua:

Есть две проблемы. Первая - это newtable. Когда b == 0 && c == 0, декомпилятор считает, что таблица является пустой таблицей, и напрямую выводит таблицу и освобождает память таблицы, вызывая инициализацию setlist позже. Сообщалось об ошибке, когда таблица не могла найти память.

Во-вторых, существует проблема с сетлистом. Когда b == 0, это фактически означает, что значения от регистра a + 1 до вершины стека (вершины) все присвоены таблице, и декомпилятор не оценивает b == 0, плюс Вот и все. Так что измените его следующим образом:

Цикл for, добавленный StartTable, указывает, что если выполняется newtable (r 0 0), а последующая неинициализированная табличная операция перезаписывает регистр r (покрывает таблицу), это указывает, что новая таблица пуста, и в таблице нет последующей таблицы. Присвоение; если регистр r инициализируется позже, это доказывает, что новая таблица не пуста, а является таблицей переменных параметров.

Если добавлено в SetList, означает, что если инструкция является инструкцией вызова, тогда добавьте элемент стека из a + 1 в регистр инструкции вызова aa в таблицу (почему это не элемент на вершине стека, а элемент на aa? Потому что инструкция вызова соответствует Вызов функции - это вызов функции. Инструмент декомпиляции преобразовал строку вызова функции в aa, который может немного отличаться от фактической операции; после того, как else должен инициализировать элемент a + 1 наверху стека в таблицу, пока функция GetR Пусто означает наверху стека.

Вопрос 12: Когда функция - это просто объявление локальной переменной в начале, например:

Первая строка local a, b, c не будет декомпилирована, что приведет к различным ошибкам в следующем коде.

Когда startpc переменной равен текущему pc, количество переменных равно 0, а текущий pc равен 0, это означает, что переменная объявлена ​​в первой строке, а добавленное else if должно разрешить эту ситуацию (это оказывается прямой ошибкой без разрешения).

Вышеупомянутое сначала суммирует статьи, связанные с обратным проектированием Lua, и связанные инструменты, которые были опубликованы в последние годы, а затем объясняет противостояние между дизассемблированием и декомпиляцией Lua и использует 3 примера в качестве иллюстраций. Первый пример иллюстрирует восстановление мобильной игры Zhengtu. Второй пример восстанавливает код операции виртуальной машины lua и успешно декомпилирует lua-скрипт. Третий пример отлично исправляет большое количество ошибок при декомпиляции lua-скрипта мобильной игры мечты.

Технология шифрования и дешифрования Lua будет продолжать развиваться, но на этом статья заканчивается. Затем я могу написать подробный отчет об анализе конкурса Tencent Game Security Competition 2018 (с подробным описанием каждого байта), включая, помимо прочего, обратный инжиниринг STL, анализ алгоритма AES, анализ сценария Blueprint и т. Д. Следите за обновлениями.

Библиотека ввода-вывода предоставляет два разных стиля интерфейсов обработки файлов. Первый стиль использует неявные дескрипторы файлов; он обеспечивает операции для установки файлов ввода по умолчанию и файлов вывода по умолчанию, и все операции ввода и вывода направлены на эти файлы по умолчанию. Второй стиль использует явные дескрипторы файлов.

При использовании неявных дескрипторов файлов все операции выполняются таблицей io. Если используется явный дескриптор файла, io.open вернет дескриптор файла, и все операции обеспечиваются методами дескриптора файла.

Таблица io также предоставляет три предопределенных дескриптора файлов с тем же значением, что и в C: io.stdin io.stdout io.stderr. Библиотека ввода-вывода никогда не закроет эти файлы.

io:open(filename [, mode])

  • ** "r": ** Режим только для чтения, который также является режимом открытия по умолчанию для существующих файлов.
  • ** "w": ** Режим с возможностью записи, позволяющий изменять существующие файлы и создавать новые файлы (нечитаемые).
  • ** "a": ** Режим добавления. Разрешено добавлять новое содержимое к существующему файлу, но не изменять исходное содержимое, а также можно создавать новые файлы.
  • ** "r +": ** Открыть существующий файл в режиме чтения-записи.
  • ** "w +": ** Если файл уже существует, удалите данные в файле; если файл не существует, создайте новый файл. Включен режим чтения и записи.
  • ** "a +": ** Откройте существующий файл в удобном для чтения режиме добавления, если файл не существует, создайте новый файл.

Строка режима может содержать букву «b» в конце, что в некоторых системах открывает файл в двоичном режиме.

Когда файл не существует

Режимы «r», «r +», выдадут ошибку, эти два режима не составит труда создать автоматически.
режим "a", "a +", "w", "w +" создаст файлы

Когда файл существует
Исходный файл:

Для разных режимов вызовите операции чтения и записи отдельно

режим "r"

Файл доступен для чтения, но не для записи

режим "г +"

Содержимое файла сохраняется, новое содержимое вводится из заголовка файла
читаемый

режим "w"

Перезаписать содержимое файла вводом
При открытии файла в режиме «w» содержимое файла будет немедленно удалено, даже если содержимое не записано.
При чтении в режиме "w" вернуть nil

режим "w +"

Перезаписать содержимое файла вводом
При открытии файла в режиме "w +" содержимое файла будет немедленно удалено.
При чтении в режиме "w +" возвращается пустая строка.

режим "а"

Добавить режим записи
не читается

режим "а +"

Добавить режим записи
читаемый

io:input([file])

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

io:output([file])

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

io.popen (prog [, mode])

Эта функция связана с системой, не все платформы ее предоставляют.

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

io.tmpfile()

Возвращает дескриптор временного файла. Этот файл открывается в режиме обновления и будет автоматически удален по завершении программы.

io.type(obj)

Проверьте, является ли obj допустимым дескриптором файла. Если obj - дескриптор открытого файла, возвращается строка «файл». Если obj является дескриптором закрытого файла, возвращается строка «закрытый файл». Если obj не является дескриптором файла, вернитеnil 。

io.lines([filename])

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

Примечание: Lua 5.3 имеет изменения, добавляющие количество режимов

file:lines()

Возвращает функцию итератора, каждый раз, когда вызывается итератор, из файла берется строка данных.В отличие от io.lines, эта функция не закрывает файл после завершения цикла.
Примечание: Lua 5.3 имеет изменения, добавляющие количество режимов

file:read(. )

Прочтите файл file, указанный формат определяет, что читать. Для каждого формата функция возвращает строку или число, соответствующие прочитанному символу. Если данные не могут быть прочитаны в этом формате, вернитеnil. (В этом последнем случае функция не будет читать последующий формат.) При вызове без формата она будет использовать формат по умолчанию для чтения следующей строки.

  • *"n ": ** Считывает число из текущей позиции файла и возвращает nil, если позиция не является числом.
  • *"l ": ** Прочитать текущую строку.
  • *"a ": ** Прочитать все содержимое файла, начиная с текущей позиции указателя файла.
  • number: Прочитать содержимое указанного количества байтов.

Примечание. В Lua 5.3 внесены изменения, убран знак * и добавлен формат «i» и «L».

io:read(. )

file:write(. )

Запишите значения параметров в файл по одному. Параметр должен быть строкой или числом.
В случае успеха функция возвращает файл. В противном случае вернитеnil Добавьте строку описания ошибки.

io:write(. )

file:close()

Закройте файл. Обратите внимание, что файл будет автоматически закрыт, когда дескриптор будет обработан сборщиком мусора, но как долго это произойдет позже, непредсказуемо.

io:close()

Эквивалент файла: close (). Если файл не указан, выходной файл по умолчанию будет закрыт.

file:flush()

Сохраните записанные данные в файл

io:flush()

Эквивалентно io.output (): flush ().

file:seek([whence [, offset]])

Установите и получите позицию, рассчитанную на основе начала файла. Установленное положение определяется базовой точкой, заданной смещением и строкой откуда. Базовая точка может быть:

  • ** "набор": ** Базовая точка - 0 (начало файла);
  • ** "cur": ** Базовая точка - это текущая позиция;
  • ** «конец»: ** Базовая точка - это конец файла;

Когда поиск завершается успешно, возвращается позиция файла, окончательно рассчитанная с начала файла. Когда поиск не удается, вернитесьnil Добавьте строку описания ошибки.

Значение по умолчанию для параметра whence - "cur", а значение смещения по умолчанию - 0. Следовательно, вызов file: seek () может вернуть текущую позицию файла, не изменяя ее; вызов file: seek ("set") установит позицию в начало файла (и вернет 0); вызывающий file: seek ("end") будет Установите позицию в конец файла и верните размер файла.

Изменение значения файла повлияет на операцию чтения и операцию записи открытия файла в режиме "r +".

Lua ввода / вывода библиотеки для чтения и обработки файлов. Разделенные на простые узоры (например, C), полный режим.

  • Простой режим (простая модель) имеет текущий входной файл и текущий выходной файл, а также обеспечить для этих файловых операций, связанных с.
  • Полный режим (полная модель), используя внешнюю дескриптор файла для достижения. Именно в лицо в форме объекта, все файловые операции будут определены как метод дескрипторов файлов

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

Оператор Операция открытия файла выглядит следующим образом:

Режим Значение являются:

режим описание
R Открыт только для чтения файл, файл должен существовать.
вес Открыть только для записи файла, если файл существует, длина файла сбрасывается в 0, то есть, содержимое файла исчезнет. Если файл не существует, создайте файл.
В дополнительном только для записи файла открывается. Если файл не существует, создание файла, если файл существует, данные записи будут добавлены в конец файла, будет сохранено содержимое исходного файла. (EOF символ зарезервировано)
г + Оба чтения и записи, чтобы открыть файл, файл должен существовать.
ш + Открыть для чтения и записи файлов, если файл существует, длина файла нуля ясно, что содержимое файла исчезнет. Если файл не существует, создайте файл.
а + И похоже, но этот файл для чтения и записи
б В двоичном режиме, если файл является двоичным файлом, вы можете добавить б
+ Знак указывает на файл может читать и писать

Простой режим

Простой режим с использованием стандартного ввода / вывода или использовать текущий входной файл и текущий выходной файл.

Ниже приведен код файла file.lua, файл операции test.lua (если вам не нужно, чтобы создать файл), следующим образом:

Реализация указанного выше кода, вы обнаружите, что первая строка информации test.ua выходного файла и последняя строка в файле добавить Lua комментарии. Я здесь, как выход:

В приведенном выше примере мы использовали Io "х", в котором io.read (), у нас нет параметров, параметр может быть одним из следующей таблицы:

режим описание
"* N" Ряд читается и вернул его. Пример: file.read ( "* п")
"* А" Прочитайте весь файл из текущего местоположения. Пример: file.read ( "* а")
"* L" (по умолчанию) Читает следующую строку в конец файла (EOF) в возвращает NIL. Пример: file.read ( "* л")
номер Возвращает указанное число символов в строке, или когда EOF возвращает ноль. Пример: file.read (5)

Другие И.О. методы:

io.tmpfile (): возвращает дескриптор временного файла, файл открывается в режиме обновления автоматически удаляются , когда концы программы

io.type (файл): обнаружение ли обрабатывает имеющиеся в его распоряжении OBJ файл

io.flush (): буфер записи все данные в файл

io.lines (необязательное имя файла): Возвращает функцию итератора, каждый вызов получит строку в файле, когда конец файла, то он вернет ноль, но не закрывает файл

Полный режим

Обычно мы должны иметь дело с несколькими файлами одновременно. Нам нужно использовать файл: имя_функции вместо io.function_name методы. Следующий пример демонстрирует тот же файл в то же время, как:

Реализация указанного выше кода, вы обнаружите, что первая строка информации test.ua выходного файла и последняя строка в файле добавить Lua комментарии. Я здесь, как выход:

считывания параметров в соответствии с простым режимом.

  • "Установить": С начала файла
  • "Тек": Из текущей позиции [по умолчанию]
  • "End": начиная с конца файла
  • Смещение: Значение по умолчанию равно 0

Файл: на одном уровне ():буфер записи все данные в файл

io.lines (необязательное имя файла): открыть режим чтения указанного файла имя файла и возвращает функцию итератора, каждый вызов будет подавать линию, когда конец файла, то он вернет ноль, и автоматически закрыть файл.
Если параметры ремня io.lines () <=> io.input (): линии (); устройство ввода по умолчанию для чтения содержимого, но конец не закрывает файл, например,

В следующем примере используется искать методы для определения положения файла предпоследнее 25 и использовать метод чтения * параметр, читать весь файл из текущего местоположения (предпоследняя позиция 25).

Читайте также: