Senior Member
Join Date: Apr 2006
Location: HERE
|
10-21-2006
, 13:47
Using Files to write data/values(old and new file commands)
|
#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
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
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.
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.
__________________
Last edited by schnitzelmaker; 10-21-2006 at 16:47.
|
|