Русское сообщество по скриптингу

Работа с файлами и директориями

Статьи или фрагменты кода для новичков и уже опытных скриптеров по AMXX.

Модератор: Chuvi

Правила форума
1. Запрещено материться и оскорблять других участников форума.
2. Запрещен флуд, оффтоп, дабл постинг во всех разделах форума, кроме раздела "Болтовня".
3. Запрещено взламывать сайт/форум или наносить любой вред проекту.
4. Запрещено рекламировать другие ресурсы.
5. Запрещено создавать темы без информативного названия. Название темы должно отображать ее смысл.

В данном разделе форума разрешено создавать темы, касающие только обучающему материалу по AMX Mod X.

Работа с файлами и директориями

Сообщение DJ_WEST » 15 окт 2009, 12:32

Автор: DJ_WEST

Данная статья дает вам представление о том, как работать с файлами и директориями в AMX Mod X.

Работа с директориями
Код: Выделить всё
read_dir(const dirname[], pos, output[], len, &outlen) 

Данная функция предназначена для чтения содержания директории. Функция возвращает индекс следующего элемента в папке или 0, если достигнут конец директории и файлов больше нет.
Примечание: Данная функция неэффективна и вместо нее рекомендуется использовать open_dir.
Код: Выделить всё
dir_exists(const dir[]) 

Данная функция предназначена для проверки, существует ли указанная директория. Возвращает 1, если директория существует или 0 в противном случае.
Код: Выделить всё
rmdir(const path[]) 

Данная функия предназначена для удаления директории. Если в директории содержатся файлы, то ее удалить нельзя.
Код: Выделить всё
mkdir(const dirname[]) 

Данная функция предназначена для создания директории. Она возвращает 0 при успешном выполнении.
Код: Выделить всё
open_dir(dir[], firstfile[], length) 

Данная функция предназначена для открытия директории для чтения. Возвращает указатель на директорию или 0 в противном случае. Указывая директорию в параметре dir, считается, что вы находитесь в директории мода (к примеру, cstrike). Но можно выйти из директории и на уровни выше (используя ../), к примеру:
Код: Выделить всё

new i_Dir
, s_File[128]
i_Dir = open_dir("../", s_File, charsmax(s_File))
 

Мы уже окажемся в главной директории сервера, там где находится hlds.exe. Но существует лимит, вы не сможете выйти дальше логического раздела, где находится сервера, на вашем жеском диске.
Код: Выделить всё
next_file(dirh, buffer[], length) 

Данная функция читает следующий файл по указанному указателю на директорию. Возвращает 1 при успешном выполнении или 0 в противном случае.
Код: Выделить всё
close_dir(dirh) 

Закрывает директорию по указанному указателю. Вы должны использовать функцию на верном указателе, полученном в open_dir.

Например, напишем плагин, который будет считывать все карты из директории ../cstrike/maps и выводить их в консоль сервера:
Код: Выделить всё
#include <amxmodx>

#define PLUGIN "Read Maps"
#define VERSION "1.0"
#define AUTHOR "DJ_WEST"

public plugin_init() 
{
    register_plugin(PLUGIN, VERSION, AUTHOR)
    
    new i_Dir
, s_File[128]
    
    
// Сохраняем указатель на директорию cstrike/maps в i_Dir
    i_Dir = open_dir("maps", s_File, charsmax(s_File))
    
    
// Проверяем существует ли директория
    if (i_Dir)
    {
        server_print("*** MAPS ***")
    
        
// Пока next_file возвращает значения != 0 выводим карту в консоль
        while (next_file(i_Dir, s_File, charsmax(s_File)))
        {
            // Проверяем если первый символ файла равен '.', то не выводим
            // Функция считывает '.' и '..', которые не являются файлами, 
            // а просто говорят о том, что есть уровень каталога выше
            if (s_File[0] == '.')
                continue
                
            
// Проверяем, чтобы файл содержал .bsp, что говорит нам о том, что это карта
            // Потому что в директории могут быть и другие файлы или директории
            if (containi(s_File, ".bsp") != -1)
                server_print(s_File)
        }
    }
}
 


Работа с файлами (старый способ)
Код: Выделить всё
file_exists(const file[]) 

Данная функция предназначена для проверки, существует ли указанный файл. Возвращает 1, если существует или 0 в противном случае.
Код: Выделить всё
delete_file(const file[]) 

Данная функция предназначена для удаления указанного файла. Возвращает 1 при успешном выполнении или 0 в противном случае.
Код: Выделить всё
read_file(const file[], line, text[], len, &txtlen) 

Данная функция предназначена для чтения строки в файле. Возвращает индекс на следующую строку или 0, если достигнут конец файла. Строки в файлах начинаются с 0 номера. Указанная строка (параметр line), считывается в text с указанным длиной len. Количество прочтенных символов хранится в txtLen.
Код: Выделить всё
write_file(const file[], const text[], line = -1) 

Данная функция предназначена для запись строки в файл по указанному месту. Возвращает 0 при неуспешном выполнении. Если line указать -1, то запись строки произойдет в конец файла. Функция автоматически создает файл, если он не существует.
Код: Выделить всё
rename_file(const oldname[], const newname[], relative=0) 

Данная функция предназначена для переименования файла. Возвращает 1 при успешном выполнении или 0 в противном случае. Если relative не 0, то будет считаться, что текущая директория - это директория мода. В противном случае, текущая директория не определена (но является директорией HLDS сервера).
Код: Выделить всё
file_size(const file[], flag=0) 

Данная функция возвращает размер файла. Если flag:
0 - размер файла в байтах
1 - количество строк в файле
2 - возвращает 1, если файл заканчивается переводом строки
Если файл не существует, возвращает -1.
Код: Выделить всё
filesize(const filename[], any:...) 

Данная функция возвращает размер файла. filename можно формировать по стилю format, то есть указывать переменные в any.

Работа с файлами (новый способ, более функциональный)
Код: Выделить всё
fopen(const filename[], const mode[]) 

Данная функция предназначена для открытия файла в одном из указанных режимов. Возвращает указатель на файл или 0 в противном случае.
Список режимов:
Первый символ:
"a" - append
"r" - read
"w" - write
Второй символ:
"t" - text
"b" - binary
Вы также можете использовать + одновременно для чтения и записи.
Код: Выделить всё
fclose(file) 

Данная функция предназначена для закрытия файла по указателю.
Код: Выделить всё
feof(file) 

Данная функция проверяет достигнут ли конец файла. Возвращает 1, если достигнут или 0 в противном случае.
Код: Выделить всё
fread(file, &data, mode) 

Данная функция предназначена для чтения элемента из файла.
Возможные режимы mode:
BLOCK_INT - для записи любого числа или символов
BLOCK_SHORT - для записи символов и значений в пределах -32767 -> 32767
BLOCK_CHAR - для записи символов и значений в пределах -127 -> 127
BLOCK_BYTE - похоже на BLOCK_CHAR
Возвращает 1 при успешном выполнении или 0 в противном случае.
Код: Выделить всё
fread_blocks(file, data[], blocks, mode) 

Данная функция предназначена для чтения блока данных из файла. Чтение блока данных и сохранения в массив данных data. blocks - размер массива.
Возможные режимы mode:
BLOCK_INT - для записи любого числа или символов
BLOCK_SHORT - для записи символов и значений в пределах -32767 -> 32767
BLOCK_CHAR - для записи символов и значений в пределах -127 -> 127
BLOCK_BYTE - похоже на BLOCK_CHAR
Возвращает число успешно прочитанных блоков.
Код: Выделить всё
fread_raw(file, stream[], blocksize, blocks) 

Данная функция предназначена для чтения блока данных из файла. Что такое RAW, можно прочитать здесь:
http://ru.wikipedia.org/wiki/RAW_(формат_данных)

Прочитать количество блоков blocknum размером blocksize из файла в массив stream.
Возвращает число успешно прочитанных блоков.
Код: Выделить всё
fwrite(file, data, mode) 

Данная функция предназначена для записи элемента в файл.
Возможные режимы mode:
BLOCK_INT - для записи любого числа или символов
BLOCK_SHORT - для записи символов и значений в пределах -32767 -> 32767
BLOCK_CHAR - для записи символов и значений в пределах -127 -> 127
BLOCK_BYTE - похоже на BLOCK_CHAR
Код: Выделить всё
fwrite_blocks(file, const data[], blocks, mode) 

Данная функция предназначена для записи блока данных в файл. Запись блока данных в file из массив данных data. blocks - размер массива.
Возможные режимы mode:
BLOCK_INT - для записи любого числа или символов
BLOCK_SHORT - для записи символов и значений в пределах -32767 -> 32767
BLOCK_CHAR - для записи символов и значений в пределах -127 -> 127
BLOCK_BYTE - похоже на BLOCK_CHAR
Возвращает число успешно записанных блоков.
Код: Выделить всё
fwrite_raw(file, const stream[], blocksize, mode) 

Данная функция предназначена для записи блока данных в файл. Что такое RAW, можно прочитать здесь:
http://ru.wikipedia.org/wiki/RAW_(формат_данных)

Записать в файл данные из масиива stream размером blocksize в режиме mode.
Возможные режимы mode:
BLOCK_INT - для записи любого числа или символов
BLOCK_SHORT - для записи символов и значений в пределах -32767 -> 32767
BLOCK_CHAR - для записи символов и значений в пределах -127 -> 127
BLOCK_BYTE - похоже на BLOCK_CHAR
Возвращает число успешно записанных блоков.
Код: Выделить всё
fprintf(file, const fmt[], any:...) 

Данная функция предназначена для записи формированный строки в файл.
Код: Выделить всё
fseek(file, position, start) 

Данная функция предназначена для установки текущей позиции курсора в файле. position - это смещение от start. start может быть:
SEEK_SET - начало файла
SEEK_CUR - текущая позиция курсора
SEEK_END - конец файла
Код: Выделить всё
ftell(file) 

Данная функция предназначена для возвращения текущей позиции курсора в файле.
Код: Выделить всё
fgets(file, buffer[], maxlength) 

Данная функция предназначена для чтения строки из файла. Считывает также символы переноса каретки и новой строки.
Код: Выделить всё
fgetc(file) 

Данная функция предназначена для чтения одного символа (1 байта) из файла по указанному указателю на него.
Код: Выделить всё
fgetf(file) 

Данная функция предназначена для чтения float значения (4 байта, 8 на AMD64) из файла по указанному указателю на него. Данная функция удалена в AMXX 1.1.
Код: Выделить всё
fgeti(file) 

Данная функция предназначена для чтения integer значения (4 байта) из файла по указанному указателю на него. Данная функция удалена в AMXX 1.1.
Код: Выделить всё
fgetl(file) 

Данная функция предназначена для чтения long значения (4 байта) из файла по указанному указателю на него. Данная функция удалена в AMXX 1.1.
Код: Выделить всё
fputs(file, const text[]) 

Данная функция предназначена для записи строки в файл по текущей позиции курсора файла. Возращает число усппешно записанных символов.
Код: Выделить всё
fputc(file) 

Данная функция предназначена для записи одного символа (1 байта) в файл по указанному указателю на него.
Код: Выделить всё
fputf(file) 

Данная функция предназначена для записи float значения (4 байта, 8 на AMD64) в файл по указанному указателю на него. Данная функция удалена в AMXX 1.1.
Код: Выделить всё
fputi(file) 

Данная функция предназначена для записи integer значения (4 байта) в файл по указанному указателю на него. Данная функция удалена в AMXX 1.1.
Код: Выделить всё
fputl(file) 

Данная функция предназначена для записи long значения (4 байта) в файл по указанному указателю на него. Данная функция удалена в AMXX 1.1.
Код: Выделить всё
fungetc(file, data) 

Данная функция предназначена для сохранения символа (1 байта) в data.

Например, плагин, который использует RAW чтение и запись, сохранение steam id, ника, фрагов и убийств игроков, которые на сервере в stats.dat, а также чтение их после смены карты (stats.dat будет хранить статистику игроков, играющих на сервере в данный момент за одну карту):
Код: Выделить всё
#include <amxmodx>

#define PLUGIN "Player Database"
#define VERSION "1.0"
#define AUTHOR "DJ_WEST & schnitzelmaker"

#define MAX_PLAYERS 32

new g_FileName[256]

enum PLAYER_DATABASE
{
    STEAMID[32],
    NAME[32],
    FRAGS,
    DEATHS,
    
    PLAYER_DATABASE_END
}

new g_PlayerData[MAX_PLAYERS+1][PLAYER_DATABASE]
new bool:g_PlayerConnected[MAX_PLAYERS+1]

public plugin_init() 
{
    register_plugin(PLUGIN, VERSION, AUTHOR)
    
    
// Получаем путь к data директории AMXX
    get_datadir(g_FileName, charsmax(g_FileName))
    // Формируем путь к файлу stats.dat
    format(g_FileName, charsmax(g_FileName),"%s/stats.dat", g_FileName)
    
    
// Через 1 секунду выполнить Read_Stats
    set_task(1.0, "Read_Stats")
    
    
// За 2 секунды перед окончанием времени карты выполнить Write_Stats
    set_task(2.0, "Write_Stats", 0, "", 0, "d")
}

stock get_datadir(s_Name[], i_Len)
{
    return get_localinfo("amxx_datadir", s_Name, i_Len)
}

public client_connect(id)
{
    g_PlayerConnected[id] = true
}

public client_disconnect(id)
{
    g_PlayerConnected[id] = false
}

public Write_Stats()
{
    new i_File, i_Frags, i_Deaths
    
    
// Открыть файл
    i_File = fopen(g_FileName, "a+")
    
    
// Если файл существует
    if (i_File)
    {
        for (new i = 1; i <= MAX_PLAYERS; i++)
        {
            if (g_PlayerConnected[i])
            {
                i_Frags = get_user_frags(i)
                i_Deaths = get_user_deaths(i)
                get_user_authid(i, g_PlayerData[i][STEAMID], charsmax(g_PlayerData))
                get_user_name(i, g_PlayerData[i][NAME], 31)
                num_to_str(i_Frags, g_PlayerData[i][FRAGS], charsmax(g_PlayerData))
                num_to_str(i_Deaths, g_PlayerData[i][DEATHS], charsmax(g_PlayerData))
                
                
// Записываем
                fwrite_raw(i_File, g_PlayerData[i][PLAYER_DATABASE:0], sizeof(g_PlayerData[]), BLOCK_INT)
            }
        }
         /*
          g_PlayerData[id] - данных игрока c id = i
          [PLAYER_DATABASE:0] - начала данных
          Для записи только Steam ID необходимо использовать: g_PlayerData[id][PLAYER_DATABASE:STEAMID]
          sizeof(g_PlayerData[]) - длина данных, которые необходимо записать
        */
    
    
}
    
    
// Закрыть файл
    fclose(i_File)  
}

public Read_Stats()
{
    new s_PlayerData[PLAYER_DATABASE], i_File
        
    
// Открыть файл
    i_File = fopen(g_FileName, "a+")
    
    
// Если файл существует
    if (i_File)
        while (fread_raw(i_File, s_PlayerData[PLAYER_DATABASE:0], sizeof(g_PlayerData[]), BLOCK_INT))
        {
            server_print("==============================")
            server_print("STEAM ID: %s", s_PlayerData[STEAMID])
            server_print("NAME: %s", s_PlayerData[NAME])
            server_print("FRAGS: %s", s_PlayerData[FRAGS])
            server_print("DEATHS: %s", s_PlayerData[DEATHS])
            server_print("==============================")
        }

    
     
// Удаляем stats.dat
    if (file_exists(g_FileName))
        delete_file(g_FileName)
        
    
// Закрыть файл
    fclose(i_File)
}
 

Результат из консоли сервера (для примера):
Код: Выделить всё

==============================
STEAM ID: BOT
NAME: [P*D]Player_1 (100)
FRAGS: 00
DEATHS: 0
==============================
==============================
STEAM ID: BOT
NAME: [POD]Player_3 (100)
FRAGS: 00
DEATHS: 0
==============================
==============================
STEAM ID: BOT
NAME: [P0D]Player_5 (100)
FRAGS: 00
DEATHS: 0
==============================
==============================
STEAM ID: BOT
NAME: [POD]Player_2 (100)
FRAGS: 00
DEATHS: 0
==============================
==============================
STEAM ID: BOT
NAME: [P*D]Player_10 (96)
FRAGS: 00
DEATHS: 0
==============================
==============================
STEAM ID: BOT
NAME: [POD]Player_9 (100)
FRAGS: 00
DEATHS: 0
==============================
==============================
STEAM ID: BOT
NAME: [P0D]Player_8 (97)
FRAGS: 00
DEATHS: 0
==============================
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Работа с файлами и директориями

Сообщение KORD_12.7 » 15 окт 2009, 12:46

Супер! :yahoo:
Спасибо за статью.
----
только описание ftell() вниз съехало

_http://aghl.ru/ - Half-Life и Adrenaline Gamer: за пределами возможного
Аватара пользователя
KORD_12.7
Скриптер
 
Сообщения: 298
Зарегистрирован: 28 сен 2009, 10:14
Откуда: Владивосток
Благодарил (а): 142 раз.
Поблагодарили: 257 раз.
Опыт программирования: Больше трех лет
Языки программирования: Half-Life
Opposing Force
Adrenaline Gamer
Counter-Strike

Re: Работа с файлами и директориями

Сообщение waw555 » 17 янв 2010, 16:53

Как создать файл .dat, если нужно использовать другой файл и можно ли записывать в него bool значение true и false
С Уважением, WAW555!!!
Аватара пользователя
waw555
 
Сообщения: 211
Зарегистрирован: 14 дек 2009, 07:15
Благодарил (а): 28 раз.
Поблагодарили: 24 раз.
Опыт программирования: Около года
Языки программирования: Counter-Strike 1.6

Re: Работа с файлами и директориями

Сообщение DJ_WEST » 18 янв 2010, 14:31

Как создать файл .dat

Для тебя пойдет вариант использования write_file функции (файл создается автоматически).
и можно ли записывать в него bool значение true и false

У write_file второй аргумент (текст для записи) имеет тип "строка", следовательно тебе и нужно записывать данные с типом строка. Ты можешь записать "true" или "false" строкой.
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Работа с файлами и директориями

Сообщение qpAHToMAS » 17 май 2010, 14:02

Как реализовать алгоритм такого плагина (?):
Весь плагин: работа с текстовым файлом, который представляет из себя статистику в таком формате:
ник;число
ник;число
ник;число

Т.е. запись в файл будет такая: берем ник игрока, делаем цикл поиска в файле по нику игрока, если ник еще не был записан в файл, то записываем новой строкой, для этого формируем строку в таком виде:
ник;число

Т.е.
Player;1

Если же ник был найден в файле, то необходимо прибавить +1 к числу, которое идет после ника и ";" символа. Как все это сделать? Хотя бы какие команды, циклы использовать?
Аватара пользователя
qpAHToMAS
 
Сообщения: 707
Зарегистрирован: 02 ноя 2009, 18:45
Благодарил (а): 79 раз.
Поблагодарили: 204 раз.
Языки программирования: CStrike

Re: Работа с файлами и директориями

Сообщение DJ_WEST » 17 май 2010, 17:56

Это будет "жестко", если хотя бы будет уже 500-1000 ников. Я о том, что постоянные циклы по файлу. Лучше мне кажется хранить данные в памяти, а в файл сохранять только в определенные случаи. Можно еще сохранять указатели на номер строки в статистике с этми ником, если, конечно, он не будет меняться. То есть найти один раз Васю, запомнить, где он и запись делать по этой строке при обращение к файлу. При создании нового ника, также запомнить его номер. Это все хорошо, конечно, если ник будет на протяжении игры у игрока один и тот же, а если можно менять, то он может сменить его по 100 раз. И вообще для хранения данных есть nvault, sql и т.д.
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Работа с файлами и директориями

Сообщение X-factor » 27 ноя 2010, 02:22

Подскажите пожалуйста!
Есть текстовый документ example.txt. В него записана и будет дальше записыватся строка вида:

Player arg1 | IP [arg2] | PID <arg3> | C_Build: arg4 | Cl OS number: arg5

где arg1 - arg4 - переменные, которые собираются и записываются плагином.

Вопрос: как проверить на совпадение arg3 (проверка по 3-ей переменной, поскольку она уникальна для всех), что бы одна и та же строка в файл не записывалась. Запись в файл этой строки осуществляется в функции client_putinserver(id), думаю понятно, что если не проверить совпадение, то сколько раз будеш заходить на сервер столько и будет раз прописыватся строка.
Аватара пользователя
X-factor
 
Сообщения: 28
Зарегистрирован: 26 ноя 2010, 17:31
Благодарил (а): 9 раз.
Поблагодарили: 7 раз.
Опыт программирования: Около года
Языки программирования: Counter-Strike 1.6
Языки прогаммирования:
Java
C#
PL/SQL (DB Oracle)
PHP
JavaScript
HTML + CSS

Re: Работа с файлами и директориями

Сообщение Ser_UFL » 27 ноя 2010, 03:22

X-factor, как-то так наверно:
[pawn]#include <amxmodx>

#define PLUGIN "Plugin"
#define VERSION "1.0"
#define AUTHOR "Author"

#define FILE    "example.txt"

public plugin_init()
    register_plugin(PLUGIN, VERSION, AUTHOR)

public client_connect(id)
{
    new Line[32], AuthID[34], i_LineCount, null

    
// Получаем твой индивидуальный параметр arg3. Для примера, это будет AuthID.
    get_user_authid(id, AuthID, charsmax(AuthID))

    while (read_file(FILE, i_LineCount++, Line, charsmax(Line), null))
    {
        if (contain(Line, AuthID) != -1)
            return PLUGIN_HANDLED
    
}

    // Тут твой код, записывающий в файл строку "Player arg1 | IP [arg2] | PID <arg3> | C_Build: arg4 | Cl OS number: arg5"
    return PLUGIN_HANDLED
} [/pawn]

Добавлено спустя 27 минут 51 секунду:
Но если файл example.txt со временем сильно увеличится в размерах, то не очень хорошо будет при коннекте каждого юзера читать весь файл и проверять на наличие совпадения...
Могу предложить альтернативу:
[pawn]#include <amxmodx>

#define PLUGIN "Plugin"
#define VERSION "1.0"
#define AUTHOR "Author"

#define DIR    "example_dir"

public plugin_init()
    
register_plugin(PLUGINVERSIONAUTHOR)

public 
client_connect(id)
{
    new 
AuthID[34], File_Argv[64]

    
// Получаем твой индивидуальный параметр arg3. Для примера, это будет AuthID.
    
get_user_authid(idAuthIDcharsmax(AuthID))

    
// Если присутствуют недопустимые для создания файла символы (такие как двоеточие и др.), то как вариант заменить их на что-либо.
    
replace_all(AuthIDcharsmax(AuthID), ":""_")

    
// Название файла будет представлять из себя твой индивидуальный параметр.
    
formatex(File_Argvcharsmax(File_Argv), "%s/%s"DIRAuthID)

    
// Проверяем на наличие файла.
    
if (!file_exists(File_Argv))
    {
        
// При остутствии, создаем этот файл.
        
write_file(File_Argv"")

        
// Тут твой код записи в файл example.txt строки с инфой.
    
}
[/pawn]
Запомните, всегда по жизни вас будут красить вежливость и спокойствие, а не наезды и дешевые понты ;)
Аватара пользователя
Ser_UFL
 
Сообщения: 975
Зарегистрирован: 22 авг 2009, 19:30
Откуда: Hell
Благодарил (а): 276 раз.
Поблагодарили: 380 раз.
Языки программирования: Counter-Strike 1.6:
WebMod-scripts, little Pawn.

Re: Работа с файлами и директориями

Сообщение DJ_WEST » 27 ноя 2010, 10:30

А лучше SQL.
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Работа с файлами и директориями

Сообщение X-factor » 27 ноя 2010, 20:56

Почему не работает? Делает только одну (самую первую) запись и всё! Пробовал как Ser_UFL - воопще несоздавался файл!
Код: Выделить всё
#include <amxmodx>

#define PLUGIN "Write Log"
#define VERSION "0.1"
#define AUTHOR "X-factor"

#define FILE "/addons/amxmodx/logs/WL/WL_LOG.txt"
#define DIR "/addons/amxmodx/logs/WL"

public plugin_init()
{
   register_plugin(PLUGIN, VERSION, AUTHOR)

   if ( !dir_exists(DIR) )
      mkdir (DIR)
}

public client_putinserver(id)
{
   if ( is_user_bot(id) )
      return

   new f = fopen(FILE, "rt");

   static File_Text[128], name[32], ip[16], AuthID[34], CurrentTime[22]

   get_user_name(id, name, charsmax(name))
   get_user_ip(id, ip, charsmax(ip), 1)
   get_user_authid(id, AuthID, charsmax(AuthID))

   get_time("%d/%m/%Y - %H:%M:%S", CurrentTime, charsmax(CurrentTime));

   formatex(File_Text, charsmax(File_Text), "%s Player %s | IP [%s] | AuthID <%s>",CurrentTime, name, ip, AuthID)

   while ( !feof(f) )
   {
      if (contain(File_Text, ip) != -1)
         return
       }

   //log_to_file(FILE, File_Text)
   write_file(FILE, File_Text, -1)

   fclose(f)
}


Добавлено спустя 54 минуты 40 секунд:
Вроде разобрался. Нужна была функция fgets:
Код: Выделить всё
#include <amxmodx>

#define PLUGIN "Write Log"
#define VERSION "0.1"
#define AUTHOR "X-factor"

#define FILE "/addons/amxmodx/logs/WL/WL_LOG.txt"
#define DIR "/addons/amxmodx/logs/WL"

public plugin_init()
{
   register_plugin(PLUGIN, VERSION, AUTHOR)

   if ( !dir_exists(DIR) )
      mkdir (DIR)
}

public client_putinserver(id)
{
   if ( is_user_bot(id) )
      return

   new f = fopen(FILE, "rt");

   static File_Text[128], name[32], ip[16], AuthID[34], CurrentTime[22]

   get_user_name(id, name, charsmax(name))
   get_user_ip(id, ip, charsmax(ip), 1)
   get_user_authid(id, AuthID, charsmax(AuthID))

   get_time("%d/%m/%Y - %H:%M:%S", CurrentTime, charsmax(CurrentTime));

   while ( !feof(f) )
   {
      fgets(f, File_Text, sizeof(File_Text) - 1)
      if( !File_Text[0] ) continue

      if (contain(File_Text, ip) != -1)
         return
       }
   
   formatex(File_Text, charsmax(File_Text), "%s Player %s | IP [%s] | AuthID <%s>",CurrentTime, name, ip, AuthID)
   
   //log_to_file(FILE, "Player %s | IP [%s] | AuthID <%s>", name, ip, AuthID)
   write_file(FILE, File_Text, -1)

   fclose(f)
}
Аватара пользователя
X-factor
 
Сообщения: 28
Зарегистрирован: 26 ноя 2010, 17:31
Благодарил (а): 9 раз.
Поблагодарили: 7 раз.
Опыт программирования: Около года
Языки программирования: Counter-Strike 1.6
Языки прогаммирования:
Java
C#
PL/SQL (DB Oracle)
PHP
JavaScript
HTML + CSS

След.

Вернуться в Статьи / фрагменты кода

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7