My previous function had some mistakes, namely on the endianess of the data, and the fact that I coded it PHP-style and forgot that UT doesn't have things like "===" and doesn't allow me to access the string characters as an array.
(it was untested after all when I posted it)
So, I fixed it and ended up creating this class for experimentation:
Code: Select all
class IntFile extends StatLogFile;
var string data;
function open(string filename)
{
StatLogFile = filename $ ".tmp";
StatLogFinal = filename $ ".int";
OpenLog();
}
function write(string data, optional bool newline)
{
self.data = self.data $ data;
if (newline) {
self.data = self.data $ chr(13) $ chr(10);
}
}
function writeLine(string data)
{
write(data, true);
}
function close()
{
local string data;
//data
data = self.data;
if (asc(chr(1000)) == 1000) {
data = convert(self.data);
}
FileLog(data);
//flush and close
FileFlush();
CloseLog();
}
function string convert(string data)
{
local string final_data;
local int data_len, i;
//convert
data_len = len(data);
for (i = 1; i < data_len; i += 2) {
final_data = final_data $ chr((asc(mid(data, i, 1)) << 8) | asc(mid(data, i - 1, 1)));
}
//convert remaining byte
if (data_len % 2 == 1) {
final_data = final_data $ mid(data, data_len - 1, 1);
}
//return
return final_data;
}
and then ran it like this:
Code: Select all
function PostBeginPlay()
{
local IntFile file;
//file
file = Spawn(class'IntFile');
file.open("test");
file.writeLine("[MySection]");
file.writeLine("a={\"key\":\"value\"}");
file.writeLine("b=This is some ANSI text.");
file.close();
//test log
log("TEST.MySection.a = " $ Localize("MySection", "a", "TEST"), 'YOLO_TEST');
log("TEST.MySection.b = " $ Localize("MySection", "b", "TEST"), 'YOLO_TEST');
}
and it worked, and the .int file was correctly written in ANSI rather than UTF-16.
However, it has a catch: FileLog always adds a carriage return and a new line at the end, which are them forcefully converted to UTF-16, which means that in editors such as Notepad++, you will see the last lines as "NULL", this is because the editor understood the file as ANSI, and since in UTF-16 the ASCII character set only has an extra NULL byte in practice, this is what the editor is showing.
I am not sure if there's a way around that tbh, so perhaps we're better off just writing the BOM at the start if we're in a UTF-16 environment when creating an .int file rather than converting it to ANSI.
Also, this shows that binary files are possible to some extent, although there's still the overall NULL bytes problem to deal with.
But given that we're able to call batch/bash files from outside at least, this means that one possible way to write full binary files is to write them in Base64 encoding, and then write a file with the necessary scripting into itself so from outside this Base64 encoded file gets decoded and then used in some way.
There's probably a more direct way of doing it, but this alone shows it to be possible to write full binary files in one way or another, and this sounds awfully close to how to build something like a NPLoader.
PrinceOfFunky wrote:nogardilaref wrote:Hence when I created hashing functions for instance (namely MD5 and SHA family), I had to specifically create byte arrays so I could handle the NULL bytes
Idk what kind but there are two functions returning checksums:
Within StatLog.uc:
Code: Select all
native static function GetPlayerChecksum( PlayerPawn P, out string Checksum );
Within StatLogFile.uc:
Code: Select all
native final function GetChecksum( out string Checksum );
Didn't test them, but those are probably CRC32 checksums.