Using Files to write data/values(old and new file commands)

For scripting examples for learning how to use AMXX.
User avatar
Archive-Poster
Posts: 1367
Gender:
United States of America

Using Files to write data/values(old and new file commands)

Post by Archive-Poster »

This is a little tutorial about reading/writing files to store something.
This Tutorial need basics in Amxx Scripting.
I am not so good in explain and writing Tutorials,so the most are writing as code.
I dont explain every Command.
If there something wrong or better please post.

Lets begin with the old file commands (easy and short).

Code: Select all

read_file ( const file[], line, text[], len, &txtLen )
Read a specific line with given lenght into an array.
It returns index of next line or 0 when the end of the file is reached.
The number of characters read is stored in txtLen.

Code: Select all

write_file ( const file[], const text[], [ line ] )
Write an array to file to the given line,if line is -1 it write at end of the file

Code: Select all

#include <amxmodx>
#include <amxmisc>

#define PLUGIN "Filehandle"
#define VERSION "1.0"
#define AUTHOR "Administrator"

new filename[256]

public plugin_init() {
    register_plugin(PLUGIN, VERSION, AUTHOR)
    
    /*get the config directory of amxx*/
    get_configsdir(filename,255)
    format(filename,255,"%s/filehandle.txt",filename)
    register_concmd("amx_filetestwrite","filewritetest")
    register_concmd("amx_filetestread","filereadtest")
}

public filewritetest(id){
    new writedata[128]
    new steamid[32],name[32],anyvalue,Float:anyfloatvalue
    
    /*Lets create and copy some dummy data*/
    get_user_authid(id,steamid,31)
    get_user_name(id,name,31)
    anyvalue = 10
    anyfloatvalue = 5.5
    
    formatex(writedata,127,"%s %s %d %f",steamid,name,anyvalue,anyfloatvalue)
    
    /*Now write this data to the file at last line
    write_file ( const file[], const text[], [ line ] )
    The line parameter defaults to -1, which appends to the end of the file. Otherwise, a specific line is overwritten.
    If no file exist write_file create one*/
    write_file(filename,writedata)
}

public filereadtest(id){
    new readdata[128],steamid[32],anyvalue,Float:anyfloatvalue,txtlen
    new parsedsteamid[32],parsedname[32],parsedanyvalue[8],parsedanyfloatvalue[8]
    
    /*now read the data from the file*/
    /*It give 2 ways to read a file until end of line*/
    
    /*The first way*/
    /*file_size - Returns the size of a file.
    If flag is 0, size is returned in bytes.
    If flag is 1, the number of lines is returned.
    If flag is 2, 1 is returned if the file ends in a line feed.
    If the file doesn't exist, -1 is returned. */
    new fsize = file_size(filename,1)
    for (new line=0;line<=fsize;line++)
    {
        /*read_file ( const file[], line, text[], len, &txtLen )*/
        read_file(filename,line,readdata,127,txtlen)
        /*We must parse the readata in somthing that we can use*/
        parse(readdata,parsedsteamid,31,parsedname,31,parsedanyvalue,7,parsedanyfloatvalue,7)
        
        /*check if steamid the same as in file*/
        get_user_authid(id,steamid,31)
        if(equal(steamid,parsedsteamid))
        {
            /*steamid is same as in file,the do somthing with the rest of parsed values*/
            anyvalue = str_to_num(parsedanyvalue)
            anyfloatvalue = str_to_float(parsedanyfloatvalue)
            client_print(id,print_chat,"Your saved Steamid:%s Name:%s Value:%d FloatValue:%f",parsedsteamid,parsedname,anyvalue,anyfloatvalue)
            /*i use break to stop the loop to save more performance.On big files this is good*/
            break
            //...
        }
    }
    
    /*The second way/the better way*/
    new line = 0
    while(!read_file(filename,line++,readdata,127,txtlen))
    {
        parse(filename,parsedsteamid,31,parsedname,31,parsedanyvalue,7,parsedanyfloatvalue,7)
        
        get_user_authid(id,steamid,31)
        if(equal(steamid,parsedsteamid))
        {
            anyvalue = str_to_num(parsedanyvalue)
            anyfloatvalue = str_to_float(parsedanyfloatvalue)
            client_print(id,print_chat,"Your saved Steamid:%s Name:%s Value:%d FloatValue:%f",parsedsteamid,parsedname,anyvalue,anyfloatvalue)
            break
            //...
        }
    }   
}
The next are the new file commands(many and very powerfull)

Lets begin with basics of new file commands and write/read a string inside a file.
This is good for textfiles where easily can read the file

The new file commands dont read linespecific,they use a cursor inside the file to read the data.
This cursor position can get with

Code: Select all

ftell(file)
And the cursor can set with

Code: Select all

fseek ( file, position, start )
"position" is an offset from start
start can be:

Code: Select all

SEEK_SET //beginning of the file
SEEK_CUR //current cursor position
SEEK_END //end of the file

Code: Select all

rewind ( file )
move the cursor position to begin of the file.

Code: Select all

fopen ( filename[], mode[] )
Open a file with given filename and mode.
It returns a pointer to the file.

Code: Select all

fputs ( file, const text[])
Write a string to a text file at current filecursor position.
"file" must be a pointer to a file from the fopen command.

Code: Select all

fprintf ( file, const buffer[], ... )
Write a formated string to a text file.Same as the format/formatex command,but for files.

fputs/fprint dont add a newline at end of the string,so it must set manually.

Code: Select all

fgets ( file, buffer[], maxlength )
Read a line (including newlines) from a text file from current filecursor position until maxlenght is reached or newline/end of file is founded.

Code: Select all

#include <amxmodx>
#include <amxmisc>

#define PLUGIN "Filehandle"
#define VERSION "1.0"
#define AUTHOR "Administrator"

new filename[256]

public plugin_init() {
    register_plugin(PLUGIN, VERSION, AUTHOR)
    
    get_configsdir(filename,255)
    format(filename,255,"%s/filehandle.txt",filename)
    register_concmd("amx_filetestwrite","filewritetest")
    register_concmd("amx_filetestread","filereadtest")
}

public filewritetest(id){
    new writedata[128]
    new steamid[32],name[32],anyvalue,Float:anyfloatvalue
    
    get_user_authid(id,steamid,31)
    get_user_name(id,name,31)
    anyvalue = 10
    anyfloatvalue = 5.5
    
    /*fopen - Returns a file handle for advanced file functions. 
    Mode uses the standard C library of mode types.
    The first character can be:
    "a" - append
    "r" - read
    "w" - write
    
    The second character can be:
    "t" - text
    "b" - binary
    
    You can also append a "+" to specify both read and write.
    Open a file in append+read+write mode
    On mode "a+"/"w+" it create a file if there no exist
    Mode "w+" overwrite a file if one exist*/
    new filepointer = fopen(filename,"a+")

    /*check if file is open,on an error filepointer is 0*/
    if(filepointer)
    {
        /*It give 2 ways to write a string inside a file*/
        
        /*First way*/
        formatex(writedata,127,"%s %s %d %f^n",steamid,name,anyvalue,anyfloatvalue)
        //The new file commands need to create a newline manual with "^n"
        
        /*write the string to the file*/
        /*another commands are:
        fputc - Writes a char (1 byte) to a file handle.
        fputf - Writes a float (4 bytes, 8 on AMD64) to a file handle. 
        fputi - Writes an integer (4 bytes) to a file handle. 
        fputl - Writes a long (4 bytes) to a file handle. */
        fputs(filepointer,writedata)
        
        /*Second way*/
        /*fprintf - Writes a line to a file */
        fprintf(filepointer,"%s %s %d %f^n",steamid,name,anyvalue,anyfloatvalue)
        
        /*close the file,this is optional,but better is it to close the file*/
        fclose(filepointer)
    }
}

public filereadtest(id){
    /*open file in read-mode*/
    new filepointer = fopen(filename,"r")
    /*check if file is open,on an error filepointer is 0*/
    if(filepointer)
    {
        new readdata[128],steamid[32],anyvalue,Float:anyfloatvalue
        new parsedsteamid[32],parsedname[32],parsedanyvalue[8],parsedanyfloatvalue[8]
    
        /*Read the file until it is at end of file*/
        /*fgets - Reads a line from a text file -- includes newline!*/
        while(fgets(filepointer,readdata,127))
        {   
            parse(readdata,parsedsteamid,31,parsedname,31,parsedanyvalue,7,parsedanyfloatvalue,7)
        
            get_user_authid(id,steamid,31)
            if(equal(steamid,parsedsteamid))
            {
                anyvalue = str_to_num(parsedanyvalue)
                anyfloatvalue = str_to_float(parsedanyfloatvalue)
                client_print(id,print_chat,"Your saved Steamid:%s Name:%s Value:%d FloatValue:%f",parsedsteamid,parsedname,anyvalue,anyfloatvalue)
                break
                //...
            }
        }
        fclose(filepointer)
    }
}
To write a file where must save many data ,the plugin growing big and are many work to write with using Parse,str_to_,...
Here a little trick that i have learn to use strucs in Pawn.
This is very easy to manage the filedata and adding new data,but every change need to change/convert also the file.

Code: Select all

enum enumname{}
enum give the variable inside the {} a number.It begin with number 0.
With "new variablename[enumname]" it create a variable with the arraylenght of the given enum.

Code: Select all

fwrite_raw ( file, const stream[], blocksize, mode )
Write an array to the file at current cursor position."blocksize" is the size of the array or the lenght who want to write.
Mode can be:

Code: Select all

BLOCK_INT //Good to write any value/char
BLOCK_SHORT //For writing values -32767 -> 32767 and chars
BLOCK_CHAR //Good for writing chars/values -127 -> 127
BLOCK_BYTE //Same as char

Code: Select all

fread_raw ( file, stream[], blocksize, blocknum )
Reads blocknum blocks from a file at current file cursor position until blocksize is reached or end of the file is found.It returns the number of succesfully readed blocks.

Code: Select all

#include <amxmodx>
#include <amxmisc>

#define PLUGIN "Filehandle"
#define VERSION "1.0"
#define AUTHOR "Administrator"

new filename[256]

enum PLAYER_DATABASE
{
    STEAMID[32],
    NAME[32],
    ANYVALUE,
    ANYFLOATVALUE,
    
    PLAYER_DATABASE_END
}
new player_data[33][PLAYER_DATABASE]

public plugin_init() {
    register_plugin(PLUGIN, VERSION, AUTHOR)
    
    get_configsdir(filename,255)
    format(filename,255,"%s/filehandle.txt",filename)
    register_concmd("amx_filetestwrite","filewritetest")
    register_concmd("amx_filetestread","filereadtest")
}

public filewritetest(id){
    /*Lets create and copy some dummy data into data*/
    get_user_authid(id,player_data[id][STEAMID],31)
    get_user_name(id,player_data[id][NAME],31)
    player_data[id][ANYVALUE] = 10
    /*theres a little problem with enum and floats:player_data[id][ANYFLOATVALUE] = 5.5 return an tag mismatch error
    this error can be ignored but a better way is using _: in front of the float value*/
    player_data[id][ANYFLOATVALUE] = _:5.5
    
    new fp=fopen(filename,"a+")
    if(fp)
    {
        /*There exist 3 commands
        fwrite - Writes an element to a file (for single chars)
        fwrite_blocks - Writes a block of data in a file (for unknown,havent get any good results with this)
        fwrite_raw - Writes blocks of data to a file (for strings/arrays)*/
        fwrite_raw(fp,player_data[id][PLAYER_DATABASE:0],sizeof(player_data[]),BLOCK_INT)
        /*Now i explain the fwrite_raw 
        fp is the filepointer
        player_data[id] is the data from player 
        [PLAYER_DATABASE:0] is the begining of the data who want to write,
        to write only Steamid it need to use player_data[id][PLAYER_DATABASE:STEAMID]
        sizeof(player_data[]) is the lenght of data which want to write,
        to write somthing like only steamid it need "player_data[id][PLAYER_DATABASE:STEAMID],32"
        */
    }
    fclose(fp)  
}

public filereadtest(id){
    new readdata[PLAYER_DATABASE],steamid[32]
    new fp=fopen(filename,"r")
    if(fp)
    {
        while(fread_raw(fp,readdata[PLAYER_DATABASE:0],sizeof(player_data[]),1))
        {   
            get_user_authid(id,steamid,31)
            if(equal(steamid,readdata[STEAMID]))
            {
                player_data[id][ANYVALUE] = readdata[ANYVALUE]
                player_data[id][ANYFLOATVALUE] = _:readdata[ANYFLOATVALUE]
                copy(player_data[id][STEAMID],31,readdata[STEAMID])
                copy(player_data[id][NAME],31,readdata[NAME])
                client_print(id,print_chat,"Your saved Steamid:%s Name:%s Value:%d FloatValue:%f",readdata[STEAMID],readdata[NAME],readdata[ANYVALUE],readdata[ANYFLOATVALUE])
                client_print(id,print_chat,"Your saved Data:%s Name:%s Value:%d FloatValue:%f",player_data[id][STEAMID],player_data[id][NAME],player_data[id][ANYVALUE],player_data[id][ANYFLOATVALUE])
                break
                //...
            }
        }
    }
    fclose(fp)
}
I hope i can help some with this little tutorial.
At the end i add the final Plugin that can be used as core to write/read data from file.
Attachments
Filehandle.sma.zip
(1.1 KiB) Downloaded 7 times

Who is online

Users browsing this forum: No registered users and 1 guest