View Single Post
Author Message
schnitzelmaker
Senior Member
Join Date: Apr 2006
Location: HERE
Old 10-21-2006 , 13:47   Using Files to write data/values(old and new file commands)
Reply With Quote #1

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:
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:
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:
#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:
ftell(file)
And the cursor can set with
Code:
fseek ( file, position, start )
"position" is an offset from start
start can be:
Code:
SEEK_SET //beginning of the file
SEEK_CUR //current cursor position
SEEK_END //end of the file
Code:
rewind ( file )
move the cursor position to begin of the file.

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

Code:
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:
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:
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:
#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:
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:
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:
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:
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:
#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.
Attached Files
File Type: sma Get Plugin or Get Source (Filehandle.sma - 1976 views - 2.4 KB)
__________________

Last edited by schnitzelmaker; 10-21-2006 at 16:47.
schnitzelmaker is offline