[Include] file_system [reduce memory usage - faster than y_ini!]
#1

file_system.inc
sscanf2 - reduce memory usage - faster than y_ini!

(registration system example at the end)


Introduction
This include allow you to read/write in any file with any extension. Using te easiest way to do it and becoming it faster than y_ini!
From this new version you can handle many files at same time without warranties. Also you will save a lot of memory by using a new system of writing/reading dates!



Benchmarks:
Код:
Loop of 2000 rounds: open a file; write/read 3 values; close it.

* WRITE:
[y_ini] 10414ms
[file_system] 4406ms - 2.36x faster than y_ini
[file_system ex] 4208ms - 2.47x faster than y_ini


* READ:
[y_ini] 1664ms
[file_system] 524 - 3.18x faster than y_ini
[file_system ex] 475ms - 3.5x faster than y_ini
PHP код:
#include <a_samp>
#include <sscanf2>
#include <file_system>
#include <YSI\y_ini>
static abimy_intbool:my_boolFloat:my_floatmy_str[10], INI:INIFile:file;
public 
OnFilterScriptInit()
{
    
// WRITE
    // y_ini
    
print("* WRITE:");
    
GetTickCount();
    for(
02000i++)
    {
        
INI INI_Open("y_ini.txt");
        
INI_WriteInt(INI"1"123);
        
INI_WriteFloat(INI"2"123.0);
        
INI_WriteString(INI"3""abc");
        
INI_Close(INI);
    }
    
GetTickCount();
    
printf("[y_ini] %ims"a);
    
// file_system.inc
    
GetTickCount();
    for(
02000i++)
    {
        
file fopen("file_system.txt"io_write)
        
File_WriteInt(file"1"123);
        
File_WriteFloat(file"2"123.0);
        
File_WriteStr(file"3""abc");
        
fclose(file);
    }
    
GetTickCount();
    
printf("[file_system] %ims"a);
    
// write_ex
    
GetTickCount();
    for(
02000i++)
    {
        
file fopen("[ex]file_system.txt"io_write)
        
File_WriteEx(file"ifs"123123.0"abc");
        
fclose(file);
    }
    
GetTickCount();
    
printf("[file_system ex] %ims\n"a);
    
// READ
    // y_ini
    
print("* READ:");
    
GetTickCount();
    for(
02000i++)
    {
        
INI_ParseFile("y_ini.txt""Y_INI");
    }
    
GetTickCount();
    
printf("[y_ini] %ims"a);
    
// file_system
    
GetTickCount();
    for(
02000i++)
    {
        
file fopen("file_system.txt"io_read)
        
File_ReadInt(file"1"my_int);
        
File_ReadFloat(file"2"my_float);
        
File_ReadStr(file"3"my_str);
        
fclose(file);
    }
    
GetTickCount();
    
printf("[file_system] %i"a);
    
// ex
    
GetTickCount();
    for(
02000i++)
    {
        
file fopen("[ex]file_system.txt"io_read)
           
File_ReadEx(file"ifs[10]"my_intmy_floatmy_str);
         
fclose(file);
    }
    
GetTickCount();
    
printf("[file_system ex] %ims\n"a);
    return 
1;
}
forward Y_INI(name[], value[]);
public 
Y_INI(name[], value[])
{
    
INI_Int("1"my_int);
    
INI_Float("2"my_float);
    
INI_String("3"my_str10);
    return 
0;



How to use:

Writing
PHP код:
public OnFilterScriptInit()
{
    new 
File:my_file fopen("file.txt"io_write)
    
File_WriteStr(my_file"String""My String");
    
File_WriteInt(my_file"Int"90412);
    
File_WriteFloat(my_file"Float"3293.0341);
    
File_WriteBool(my_file"Bool"true);
    
fclose(my_file);
    return 
1;

In the file will output:
Код:
String = My String
Int = 90412
Float = 3293.0341
Bool = true
Reading
PHP код:
public OnFilterScriptInit()
{
    new 
File:my_filemy_str[10], my_intFloat:my_floatbool:my_bool;
    
    
my_file fopen("test.txt"io_read)
    
File_ReadStr(my_file"String"my_str);
    
File_ReadInt(my_file"Int"my_int);
    
File_ReadFloat(my_file"Float"my_float);
    
File_ReadBool(my_file"Bool"my_bool);
    
fclose(my_file);
    
printf("'%s' - %i - %f - %i"my_strmy_intmy_floatmy_bool);
    return 
1;

Output:
Код:
'MyString' - 90412 - 3293.0341 - 1

Be careful! You will get wrongs values if you wrote incorrect names.
For example, you saved a value as "Password", and you are trying to read it using "Paswor", it will read this:
Код:
= MyPassword
Anyway, there's no check for these issues. You can read same value even using another word.
Example, I wrote a value as "Password", and I'm trying to read it as "LastDead", it will return the correct value because "Password" and "LastDead" has same lenght.
(keep reading below!)




Debug Mode:
"debug mode" version will help you finding some typical issues.
Just use this as usual and check out your server console, and verify that all is going good!

What does this verify?
  • 1. Check if there's a separator (Name = Value) in file line.
    2. Check if there's a line splitter (\r\n).
    3. Check out values name match.
Anyway, if is an invalid value name, it will try to read the value that was stored.
For use it, just replace "#include <file_system>" to "#include <file_system_debug>".




Using "File_*Ex" functions:
This system of write/read will save memory and write/read faster than previous examples.
You only can read/write one line per file.

Writing
PHP код:
new File:file fopen("test.txt"io_write)
File_WriteEx(file"sif""MyString"123123.123);
fclose(file); 
Output:
Код:
MyString 123 123.123000
Reading
PHP код:
new File:filemy_str[10], my_intmy_float;
file fopen("test.txt"io_read)
File_ReadEx(file"s[10]if"my_strmy_intmy_float);
fclose(file);
printf("'%s' - %i - %f"my_strmy_intmy_float); 
Output:
Код:
'My String' - 123 - 123.123000
Specifiers:
WriteEx: https://sampwiki.blast.hk/wiki/Format
ReadEx: https://sampforum.blast.hk/showthread.php?tid=602923




Registration system example:
PHP код:
#include <a_samp>
#include <sscanf2>
#include <file_system>
#define DIALOG_LOGIN            (1)
#define DIALOG_REGISTER         (2)
enum pInfo_enum
{
    
bool:LoggedIn,
    
Password[21],
    
Kills,
    
Deaths,
    
JoinsCount
};
new 
pInfo[MAX_PLAYERS][pInfo_enum];
public 
OnPlayerConnect(playerid)
{
    new 
dir[34], name[21], File:fileany;
    
GetPlayerName(playeridnamesizeof(name));
    
format(dirsizeof(dir), "users/%s.txt"name);
    
file fopen(dirio_read);
    if(
file// Check if is an registered account
    
{
        
File_ReadEx(file"s[21]i"pInfo[playerid][Password], any); // "any" is used for avoid bugs!
        
ShowPlayerDialog(playeridDIALOG_LOGINDIALOG_STYLE_PASSWORD"{00FFFF}Welcome back!""{FFFFFF}Welcome back!\nType your password below to logg in.""Next""Exit");
    }
    else 
ShowPlayerDialog(playeridDIALOG_REGISTERDIALOG_STYLE_PASSWORD"{00FFFF}Sing In.""{FFFFFF}Welcome!\nType your password below to sign in and create your data file.""Next""Exit");
    
fclose(file);
    return 
1;
}
public 
OnPlayerDisconnect(playeridreason)
{
    if(!
pInfo[playerid][LoggedIn]) return 1// Avoid bugs
    
new File:filedir[34], name[21];
    
GetPlayerName(playeridnamesizeof(name));
    
format(dirsizeof(dir), "users/%s.txt"name);
    
file fopen(dirio_write);
    
File_WriteEx(file"siii"pInfo[playerid][Password], pInfo[playerid][Kills], pInfo[playerid][Deaths], pInfo[playerid][JoinsCount]);
    
fclose(file);
    return 
1;
}
public 
OnDialogResponse(playeriddialogidresponselistiteminputtext[])
{
    switch(
dialogid)
    {
        case 
DIALOG_LOGIN:
        {
            if(!
response) return Kick(playerid);
            if(!(
<= strlen(inputtext) <= 20)) return ShowPlayerDialog(playeriddialogidDIALOG_STYLE_PASSWORD"{00FFFF}Welcome back!""{FFFFFF}Password must be between 3 and 19 chars.\nTry again:""Next""Exit");
            if(
strcmp(pInfo[playerid][Password], inputtext)) return ShowPlayerDialog(playeriddialogidDIALOG_STYLE_PASSWORD"{00FFFF}Welcome back!""{FFFFFF}That password doesn't match with this account password.\nTry again:""Next""Exit");
            new 
File:filedir[128], name[21];
            
GetPlayerName(playeridnamesizeof(name));
            
format(dir34"users/%s.txt"name);
            
file fopen(dirio_read);
            
File_ReadEx(file"s[10]iii"pInfo[playerid][Password], pInfo[playerid][Kills], pInfo[playerid][Deaths], pInfo[playerid][JoinsCount]);
            
fclose(file);
            
format(dirsizeof(dir), "[ACC] %i kills - %i deaths - %i times joined"pInfo[playerid][Kills], pInfo[playerid][Deaths], ++pInfo[playerid][JoinsCount]);
            
SendClientMessage(playerid0x00FF00FF"[ACC] You logged in successfully!");
            
SendClientMessage(playerid0x00FF00FFdir);
            return 
1;
        }
        case 
DIALOG_REGISTER:
        {
            if(!
response) return Kick(playerid);
            new 
len strlen(inputtext);
            if(!(
<= len <= 20)) return ShowPlayerDialog(playeriddialogidDIALOG_STYLE_PASSWORD"{00FFFF}Welcome back!""{FFFFFF}Password must be between 3 and 19 chars.\nTry again:""Next""Exit");
            for(new 
0<= leni++)
            {
                if(
inputtext[i] == ' ') return ShowPlayerDialog(playeriddialogidDIALOG_STYLE_PASSWORD"{00FFFF}Welcome back!""{FFFFFF}Your password cannot have spaces.\nTry again:""Next""Exit");
            }
            new 
File:filedir[34], name[21];
            
GetPlayerName(playeridnamesizeof(name));
            
format(dir34"users/%s.txt"name);
            
file fopen(dirio_write);
            
format(pInfo[playerid][Password], 21"%s"inputtext);
            
File_WriteEx(file"siii"pInfo[playerid][Password], 000);
            
fclose(file);
            
SendClientMessage(playerid0x00FF00FF"[ACC] You has been registered successfully!");
            return 
1;
        }
    }
    return 
1;
}
public 
OnPlayerDeath(playeridkilleridreason)
{
    
pInfo[playerid][Deaths] ++;
    if(
killerid != 0xFFFpInfo[killerid][Kills] ++;
    return 
1;


Updates:
v06/12/16.
v11/12/16.


Download
http://pastebin.com/sSQWnwcc

Last compilation: 06/12/16:
Reply
#2

I like how you made it simple to use for example

pawn Код:
File_WriteBool(File:file, name[], bool:value)
And loading shit is preety damn easy. Good job man

PS: I suggest that you put up a small tutorial like registration system (Ofc using your own file system) so you can gain some popularity on this project
Reply
#3

Thanks I've added it, and one attachment for people who don't know how to convert it to ".inc"

Look at this:
Код:
* WRITE:
[y_ini] 10414ms
[file_system] 4406ms - 2.36x faster than y_ini
[file_system ex] 4208ms - 2.47x faster than y_ini


* READ:
[y_ini] 1664ms
[file_system] 524 - 3.18x faster than y_ini
[file_system ex] 475ms - 3.5x faster than y_ini
I think this include should be used by people who needs save simple data and memory! In a easy, faster and safe way
Reply
#4

I'll be testing this out later, but you should add a highlighted (so it can be seen) warning,
saying that in reading (Without File_ReadEx), the order should be exactly the same.
Because if the order is wrong, there will be different results (Since this uses fseek)

I think it's a pretty cool concept but it's too risky, especially since this is supposed to be 'beginner-friendly'.
Reply
#5

Quote:
Originally Posted by Stinged
Посмотреть сообщение
I'll be testing this out later, but you should add a highlighted (so it can be seen) warning,
saying that in reading (Without File_ReadEx), the order should be exactly the same.
Because if the order is wrong, there will be different results (Since this uses fseek)

I think it's a pretty cool concept but it's too risky, especially since this is supposed to be 'beginner-friendly'.
So I think I should make a debug mode version for detect/avoid mistakes in the order while reading values Thanks!
Reply
#6

That's nice mate, great job.
Reply
#7

Very nice!
Reply
#8

Quote:
Originally Posted by EnzoMetlc
Посмотреть сообщение
So I think I should make a debug mode version for detect/avoid mistakes in the order while reading values Thanks!
Exactly, good job by the way!
Reply
#9

Okay, I added a "debug mode" version. Just check the main post and attached files!
Reply
#10

Updated - 06/12/16:

- File_*Ex improved.
- File_Read* now returns if the line was readed.
- File_Create & File_Close were removed - I think these functions are not necessary and may improve your script (do it with native functions).

----------

If you need help with some script by using this include, just tell me, I'll do it
Reply
#11

Quote:
Originally Posted by Swedky
Посмотреть сообщение
Updated - 06/12/16:

- File_*Ex improved.
- File_Read* now returns if the line was readed.
- File_Create & File_Close were removed - I think these functions are not necessary and may improve your script (do it with native functions).

----------

If you need help with some script by using this include, just tell me, I'll do it
I was looking for something like this, although with the debug version you forgot to define "gFileStr":

Код:
file_system_debug.inc(138) : error 017: undefined symbol "gFileStr"
Reply
#12

Quote:
Originally Posted by CantBeJohn
Посмотреть сообщение
I was looking for something like this, although with the debug version you forgot to define "gFileStr":

Код:
file_system_debug.inc(138) : error 017: undefined symbol "gFileStr"
Thanks for reporting, fixed!

--------

Updated - 11/12/16:

- File_Write* optional param "len" added. Set a length for "format" function.
- File_Read* optional params "size" (set how many dates will be read) and "pack" (for packed strings) added.
- File_Copy added. Copy a file data and paste it in a new one (it will overwrite if new directory exists). Example:
PHP код:
// native File_Copy(const from[], to[], bool:remove = false); if "remove" param it's true, it will delete the old file!
File_Copy("my_file1.txt""my_file2.txt"true); // Example 1
File_Copy("Folder1/my_file1.txt""Folder2/my_file2.txt"false); // Example 1 
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)