00092. Работа с файлами ( форматированное чтение )

Работа с файлами ( форматированное чтение )|В этом уроке мы вернёмся к файлам, а точнее будет записывать и считывать форматированный текст.|wmysterio|wmysterio||||Привет всем пользователям нашего сайта! Пришло время для очередного урока! Этот способ отличается от работы с ini-файлами по всем статьям, но прочтя этот урок вы многое узнаете и, надеюсь, будете активно использовать в своих скриптах.

Прежде всего нам нужно настроить наш Санник, так как именно настройка ( а точнее не полная настройка ) не давала мне писать скрипты изучаемым сегодня методом. Как оказалось, всё дело в регистре букв, который компилятор использует по-умолчанию. Давайте откроем настройки и перейдём во вкладку "Форматирование" и обратим внимание на радио-кнопку "Регист букв":

Как видим, по-умолчанию у нас стоит ВЕРХНИЙ регист. Так, как режим открытия файла должен обязательно компилироваться в нижнем регистре, то меняет радиокнопку на Как есть ( нижний - тоже неплохой вариант, это уже наш вкус, но главное, что бы не стоял верхний регистр ). После этого нажимаем "ОК".

В отличии от ini-режима, в этом режиме нет никаких ключевых слов или секций. Как и Cleo - считывание происходит построчно. Существует 6 основных режимов открытия файла:

Таблица 1

Текстовый режим

Режим

Описание

rt

Режим открытия файла для чтения. Файл должен существовать.

wt

Режим создания пустого файла для записи. Если файл с таким именем уже существует его содержимое стирается, и файл рассматривается как новый пустой файл

at

Дописать в файл. Операция добавления данных в конец файла. Файл создается, если он не существует.

Бинарный режим

Режим

Описание

rb

Режим открытия файла для чтения. Файл должен существовать.

wb

Режим создания пустого файла для записи. Если файл с таким именем уже существует его содержимое стирается, и файл рассматривается как новый пустой файл

ab

Дописать в файл. Операция добавления данных в конец файла. Файл создается, если он не существует.

Рассмотрим опкод, для открытия файла:

0A9A: $hFILE = openfile "Cleo\config.txt" mode "rb" // IF and SET

Здесь: $hFILE - хендл нашего файла "Cleo\config.txt" - путь у нашему файлу относительно директории GTA SA "rb" - режим открытия ( см. Таблица 1 )

Этот опокод является так же явлется условным, поэтому советую использовать его в блоке условий "if...jf". После того, так работа с файлом завершена, обязательно нужно закрыть его опкодом:

0A9B: closefile $hFILE

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

Так, так тема нашего урока "форматированное считывание и запись", то мы обязаны рассмотреть какие идентификаторы есть, которые пишутся в опкод в зависимости от типа принимаемых значений:

Таблица 2

Идентификатор

Описание

%d

Идентификатор целого числа

%f

Идентификатор дробного числа ( по-умолчанию число и остаток с шестью символами после запятой )

%s

Идентификатор строки

%c

Идентификатор символа (номер символа)

Здесь: % - специальный идентификатор, который указывает компилятору какой тип данных нужно записывать или читать. Они стоят в том порядке, который мы задали в файле, или планируем записать. d, f, c, s - собственно и есть типы

Давайте рассмотрим 2 опкода, которые позволяют осуществлять запись и чтение:

0AD9: write_formatted_text "Записать %d значений" in_file $hFILE 2
0ADA: 0@ = scan_file $hFile format "Считать %d" 1@

Опкод "0AD9" записует форматированный текст в файл "$hFILE". Будет записан текст, с таким содержимым: "Записать 2 значений". Как видите, в поле строки указываются только идентификаторы, а после опкода идёт перечисление всех значений. То есть, если мы хотим, что бы в файл записало стоку с содержимым "Бокал пива вмещает 0.5 литра" и хотим в скрипте задать объём пива, то наш скрипт приобретёт следующий вид:

0@ = 0.5
0AD9: write_formatted_text "Бокал пива вмещает %.1f литра" in_file $hFILE 0@

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

0@ = 1.25
0AD9: write_formatted_text "В 2 бокала пива вмещается %.2f литра" in_file $hFILE 0@

Соответственно в файл будет записан текст: "В 2 бокала пива вмещается 1.25 литра". То есть, если не задать параметр как идентификатор, то он воспринимается как символ. Давайте на этом же примере, напишем текст, с использованием 2-х параметров:

0@ = 1.25
1@ = 2
0AD9: write_formatted_text "В %d бокала пива вмещается %.2f литра" in_file $hFILE 1@ 0@

Думаю вы обратили внимание на "%.2f". Собственно для чего мы поставили это? Дело в том, что при такой установке в файл будет записываться только 2 символа после запятой. Если мы поставим "%.3f", то в файл будет записано 3 символа. Если этого не сделать ( напишем просто "%f" ), то число в файл запишет число "1.250000". Эти идентификаторы уже нужно ставить на своё усмотрение, но как минимум "%.1f". Иначе если дробное число не будет иметь остатка ( например, "1.0"), то во многих случаях в файл запишется просто "1", что вызывает проблемы при считывании. Данные выражения с точкой действуют только на дробные цисла!

Что касается записи строк, то здесь всё тоже самое. Указываем стринговую переменную и задаём ей значение. После этого записуем в файл:

1@v = "Привет"
0AD9: write_formatted_text "text %s" in_file $hFILE 1@v

Содержимое файла: "text Привет". Вот пример простейшего скрипта, который запишет в файл данные:

{$CLEO}
0000:
thread 'WRITE_TEXT'

:WRITE_TEXT
wait 0
if
file.Open(0@, "cleo\text.txt", "wt")
jf @WRITE_TEXT
1@ = 2
2@v = "пива"
3@ = 1.25
0AD9: write_formatted_text "в %d бакалах %s вмещается %.2f литра" in_file 0@ 1@ 2@v 3@
file.Close(0@)
0A93: end_custom_thread

Результат:

Опкод "0ADA" осуществляет считывание файла и очень похож на запись, но здесь есть одно примечание, что содержимое строки файла должно точно совпадать с содержимым строки опкода! Если строка файла "Сейчас 16:21 часов", то содержимое строки опкода будет "Сейчас %d:%d часов" ( планируется считать 2 значения из файла ). Следовательно в конце опкода нужно дописать необходимые параметры:

0ADA: 0@ = scan_file $hFile format "Сейчас %d:%d часов" 1@ 2@

Таким образом в переменные "1@" и "2@" будут записаны числа, считанные из файла. В переменную "0@" запишется количество удачных преобразований. Если оно не совпадёт с параметрами файла, то выражение вернёт false и в переменные "1@" и "2@" нифига не запишется =) Это условный опкод, поэтому используйте его в условных конструкциях с "if". Старайтесь правильно указывать идентификаторы. Во многих случаях это и есть решение проблем.

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

{$CLEO}
0000:
thread 'READ_TEXT'

:READ_TEXT
wait 0
if
file.Open(0@, "cleo\text.txt", "rt")
jf @READ_TEXT

:READ_TEXT_1
wait 0
if 
0ADA: 1@ = scan_file 0@ format "Color car: %d, %d" 2@ 3@
jf @READ_TEXT_1
file.Close(0@)

:READ_TEXT_2
wait 0
if
actor.Driving($PLAYER_ACTOR)
jf @READ_TEXT_2
03C0: 5@ = actor $PLAYER_ACTOR car
0229: set_car 5@ primary_color_to 2@ secondary_color_to 3@
0A93: end_custom_thread

В результате наш скрипт прекрасно перекрашивает наш транспорт на заданный в файле цвет.

В большинстве случаев файлы используют для хранения одинаковой по-структуре информации. Затем считывают весь файл и задают параметры для разных субъектов. К примеру, в файле в нас будет хранится информация о транспорте. Считая её мы создадим несколько машин в генераторе транспорта. Сначала рассмотрим опкод для определения количества параметров в строке:

014B: $CAR = init_parked_car_generator #RHINO color -1 -1 1 alarm 0 door_lock 0 0 10000 at 2435.302 -1671.848 12.8007 angle 90.0

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

445 5000 2483.021 -1659.0421 12.94315 180.0 446 7000 2477.022 -1659.0422 12.9432 180.0 447 4000 2471.023 -1659.0423 12.9431 180.0 448 8000 2465.024 -1659.0424 12.94321 180.0 491 10000 2459.025 -1659.0425 12.94322 180.0 471 13000 2453.026 -1659.0426 12.94311 180.0 455 20000 2447.027 -1659.0427 12.94314 180.0 438 8000 2441.028 -1659.0428 12.94321 180.0

Дальше уже напишем скрипт:

{$CLEO}
0000:
thread 'READ_TEXT'

var
$CARS: array 8 of car
end

:READ_TEXT
wait 0
if
file.Open(0@, "cleo\text.txt", "rt")
jf @READ_TEXT
$INDEX = 0

while not file.EOF(0@)
 if 
 0ADA: 1@ = scan_file 0@ format "%d %d %f %f %f %f" 2@ 3@ 4@ 5@ 6@ 7@ // IF AND SET
 then
 014B: $CARS[$INDEX] = init_parked_car_generator 2@ color -1 -1 1 alarm 0 door_lock 0 0 3@ at 4@ 5@ 6@ angle 7@
 014C: set_parked_car_generator $CARS[$INDEX] cars_to_generate_to 101
 $INDEX += 1
 end
wait 0
end
file.Close(0@)
0A93: end_custom_thread

Так как в нас файл состоит из 8 строк, то и в массиве автомобилей тоже будет 8 машин. Дальше считывая файл мы подставляем считанные значения в опкод, тем самым создаём новый элемент генератора транспорта.

Думаю, Вы обратили внимание на опкод "0AD6: end_of_file 0@ reached" ( он же file.EOF(0@) ). Это проверка "Достигнут ли конец файла 0@?". Используя её мы узнаём когда прекращать чтение. В результате мы получили:

Если разобраться, то нет ничего сложного. Используйте файлы и в своих модах. В большинстве случаев, это существенно уменьшает время и код! =)|2411|1|0|52341360png500388400310``\|59636185png500300400240\|25511210`png`460`422`400`366|39936709png403301400`298``||rabota_s_fajlami_formatirovannoe_schityvanie|1504425699

Last updated