Page 1 of 2

You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 1:19 pm
by PrinceOfFunky
"You cannot write on files using Unreal" - they said.
"You can only write on INI files and read from INI and INT files using Unreal" - they said.

Fake! Like in any other programming language you can write on file and perform all the needed operations on it, like creating the file itself, opening, flushing and closing it.
This works like a charm:

Code: Select all

local StatLogFile file;
	
	file = Spawn(class'StatLogFile');
	//tmp file name.
	file.StatLogFile = "test.tmp";
	//final file name.
	file.StatLogFinal = "test.log";
	file.OpenLog();
	file.FileLog("HERE GOES WHAT YOU WANT TO WRITE ON THE FILE");
	file.FileFlush();
	file.CloseLog();
Video proof:
BhBSJanAYVM

BeginPlay set the timer to 30 and the Timer logs players info, so if you don't want your file to include the players info every 30 seconds, you should disable Timer() or overwrite BeginPlay().

StatLogFile variable can be whatever directory, the parent class of StatLogFile contains some useful functions I didn't read, so basing on what I wrote here, you could create a script file from scratch and then execute it using Unreal for the whole process.

I'm not sure if you want to see the mutator I showed in the vid, if you need it just tell me and I'll post it on here.
I think if people will start using new directories, we should make a standard before we get a lot of folders spread around.

(And I was even making Unreal communicating through TCP just to write few info using Java -__-")

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 2:39 pm
by nogardilaref
I truly wonder how I have missed this actor myself for all these years... very interesting indeed, this will certainly allow the sort of thing I aim to do in the future a lot more easily.
Although this is as powerful as it is dangerous, for obvious reasons.

As for appending, perhaps if you do not call "file.CloseLog();" and keep global reference in your class rather than a local one, it might keep appending stuff to it instead, until the actual actor itself is destroyed on map change or on exit.

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 3:03 pm
by sektor2111
nogardilaref wrote:As for appending, perhaps if you do not call "file.CloseLog();" and keep global reference in your class rather than a local one, it might keep appending stuff to it instead, until the actual actor itself is destroyed on map change or on exit.
I did not recall any chatlog file removed from my system all this time - IT USES THE same way for writing files outta sandbox. Yeah, Funky, it's done already...

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 3:15 pm
by PrinceOfFunky
sektor2111 wrote:
nogardilaref wrote:As for appending, perhaps if you do not call "file.CloseLog();" and keep global reference in your class rather than a local one, it might keep appending stuff to it instead, until the actual actor itself is destroyed on map change or on exit.
I did not recall any chatlog file removed from my system all this time - IT USES THE same way for writing files outta sandbox. Yeah, Funky, it's done already...
Yeah IkIk that the appending works, but I meant appending after closing/reopening the file.
I think the best thing would be to read files other than writing them, I mean we can read from INI and INTs but they must be in a standard format, reading from whatever structure would be a lot better.

EDIT: Also:
nogardilaref wrote:I truly wonder how I have missed this actor myself for all these years...
Maybe cause the name of the class/file is StatLogFile and not something like FileWriter and basing on what we are used to read in unrealscript classes, like that when you read things that are not usually from the unrealscript world we tend to think that those things must be hardcoded natively.

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 4:22 pm
by nogardilaref
PrinceOfFunky wrote:
nogardilaref wrote:I truly wonder how I have missed this actor myself for all these years...
Maybe cause the name of the class/file is StatLogFile and not something like FileWriter and basing on what we are used to read in unrealscript classes, like that when you read things that are not usually from the unrealscript world we tend to think that those things must be hardcoded natively.
Nah, I am used to weird names and all, and in this case is called "StatLogFile" which is actually pretty obvious, so I think it was mostly over the fact that I barely look into Info classes and I didn't expect something like this to be under "Info" at all, and be an actual actor to top it off (I assumed it would be an non-actor, so there's where I looked in the past).

Which means I will probably have to recheck every class again one of these days, once I pick stuff like this again. :mrgreen:

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 5:06 pm
by Higor
You can only write 16 bit characters using statlog.
And in a certain UT build you cannot even generate characters outside of the 8 bit range.

Worthless.

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 5:33 pm
by nogardilaref
Well... that would at least make it a lot less dangerous, but .int files are localization files, which UT should be able to load from 16-bit characters as well, right?

Given that we can use this class to perhaps create .int files themselves, and Localize to read them, if both work well enough (with the special case of Localize remaining cached in the engine itself), there is still some very useful stuff which can be done, and which fits exactly what I need in my particular case for what I intend to do in the future.


@PrinceOfFunky: did you test to write a "new" .int file with the proper format using this, and then read it with Localize to check if it works at all?

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 7:46 pm
by Higor
Self-localizing in UT has platform-specific code that requires different UnrealScript code for both windows and linux.
Also, UTF localization files require an additional character at the beginning of the text file to indicate UT should read it as UTF.

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 9:13 pm
by nogardilaref
Yeah, I just went ahead and tested it myself... bummer.
Well, at least with this you're not bound to a single log file, and this can still be used for plenty of stuff other than logging, although to read back it's indeed quite pointless the way things are saved.

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 9:59 pm
by Higor
Forget about windows and linux, let's talk about ANSI or UNICODE

Essentially:
- ANSI: log as usual.
- UNICODE: add the special character start of file, then log as usual.

Try the following

Code: Select all

function StartHeader( string FirstLine)
{
	if ( asc(chr(1000)) == 1000 ) //ANSI UT will fail this check
		AddString( chr(65279)$ FirstLine);
	else
		AddString( FirstLine);
}
EDIT: That will only work on INT files btw.
INI will fail.

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 10:28 pm
by nogardilaref
Image

Worked like a charm :rock: , here's the code:

Code: Select all

function PostBeginPlay()
{
local StatLogFile file;

	//open
	file = Spawn(class'StatLogFile');
	file.StatLogFile = "TEST.tmp";
	file.StatLogFinal = "TEST.int";
	file.OpenLog();

	//header
	if (Asc(Chr(1000)) == 1000) { //ANSI UT will fail this check
		file.FileLog(Chr(65279));
	}

	//data
	file.FileLog("[MySection]");
	file.FileLog("a={\"key\":\"value\"}");
	file.FileLog("b=This proves Higor is THE MAN!");

	//finish
	file.FileFlush();
	file.CloseLog();

	//load
	Log("TEST.MySection.a = " $ Localize("MySection", "a", "TEST"), 'YOLO_TEST');
	Log("TEST.MySection.b = " $ Localize("MySection", "b", "TEST"), 'YOLO_TEST');
}
and here's the log:

Code: Select all

YOLO_TEST: TEST.MySection.a = {"key":"value"}
YOLO_TEST: TEST.MySection.b = This proves Higor is THE MAN!

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 11:06 pm
by Higor
You can also create entire ANSI files using windows statlog, at least to be able to write binary files (pair amount of bytes only).
But you'll need to do a lot of buffering and character conversion, without proper unrealscript optimization the UNICODE build of the statlog may be extremely slow.

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 11:16 pm
by PrinceOfFunky
nogardilaref wrote:

Code: Select all

//header
Is it cause of the missing header that this localization doesn't work?:

Code: Select all

local StatLogFile file;
	
	file = Spawn(class'StatLogFile');
	
	//tmp file name.
	file.StatLogFile = "test_2.tmp";
	//final file name.
	file.StatLogFinal = "test_2.int";
	file.OpenLog();
	file.FileLog("[tests]");
	file.FileFlush();
	file.FileLog("test1=hello");
	file.FileFlush();
	file.CloseLog();
	
	Level.Game.BroadcastMessage(Localize("tests", "test1", "test_2"));
EDIT:
Higor wrote:You can also create entire ANSI files using windows statlog, at least to be able to write binary files (pair amount of bytes only).
But you'll need to do a lot of buffering and character conversion, without proper unrealscript optimization the UNICODE build of the statlog may be extremely slow.
Or you run an external script which converts the file from ANSI to UNICODE.

Re: You can create and write a file using Unreal

Posted: Sat Dec 09, 2017 11:22 pm
by Higor
Quick Goolag search results in this: http://www.fileformat.info/info/unicode ... /index.htm

Re: You can create and write a file using Unreal

Posted: Sun Dec 10, 2017 12:26 am
by nogardilaref
@PrinceOfFunky: Yeah, what I commented as header is essentially what Higor posted right before and is simply the UTF-16 BOM (Byte Order Mark), which hints a text reader in which encoding the file is, be it ANSI, UTF-8, UTF-16 or something else, as well as endianess.
In the case of UTF-16, is what Higor just posted, hence that "magic" number at the start, so when the engine loads the .int file, it gets correctly interpreted as UTF-16 rather than ANSI.

As for the first check with Chr(1000), 1000 is just a random UTF-16 character just to check if UT is able to recognize UTF-16 or not.
To be honest, until Higor posted it, I thought that Chr was limited to 255 (ANSI) for some reason, perhaps because there's a difference depending on the version from what he said which I was completely unaware about. I'm glad he sorted it out. :mrgreen:
Higor wrote:You can also create entire ANSI files using windows statlog, at least to be able to write binary files (pair amount of bytes only).
But you'll need to do a lot of buffering and character conversion, without proper unrealscript optimization the UNICODE build of the statlog may be extremely slow.
I guess it would be something like this then? (untested code)

Code: Select all

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(data[i - 1]) << 8) | asc(data[i]));
	}
	
	//convert remaining byte
	if (data_len % 2 === 1) {
		final_data = final_data $ chr(asc(data[data_len - 1]) << 8);
	}
	
	//return
	return final_data;
}
But then, I am worried about the NULL bytes, because they break strings in this engine, given that strings are NULL terminated after all.
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, unless I am missing something here...