• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

[SOLVED] Store entire text file contents in string (GM 8.1)

S

Sam (Deleted User)

Guest
I wrote a script for my Execute Statement extension which allows me to read the entire contents of a VBScript text file. It works in GMStuido 1.4 and 2. But for whatever reason I can't get it working in GM 8.1. It's obvious legacy GM can do this too, but needs to be done slightly different in order for it to work, I just can't remember how it used to be done.

Code:
// ExecuteVBScriptFile executes .VBS script files.
// argument0: The VBScript script file to execute.

if (file_exists(argument0) == true) {

    var __vbsFile__, __vbsString__;

    __vbsFile__   = file_text_open_read(argument0);
    __vbsString__ = "";

    while (file_text_eof(__vbsFile__) == false) {

        __vbsString__ += file_text_readln(__vbsFile__);

    }

    file_text_close(__vbsFile__);

    ExecuteStatement(__vbsString__, "VBScript");

} else {

    show_message("File not found!");

}
Anyone know what I should do differently?

Thanks!
Samuel
 
C

CedSharp

Guest
The code you posed seems perfectly fine.
Try doing a show_message(__vbsString__);
I suspect it's related to the DLL loading code instead.
 

trg601

Member
I was actually working with GM8 recently and encountered a similar problem.
In GM8, the function file_text_readln() doesn't return a string like it does in GMS. From the documention:
file_text_readln(fileid) Skips the rest of the line in the file and starts at the start of the next line.

file_text_read_string(fileid) Reads a string from the file with the given file id and returns this string. A string ends at the end of line.
Since file_text_read_string() reads the whole line you need to do this instead:
Code:
__vbsString__ += file_text_read_string(__vbsFile__);
file_text_readln(__vbsFile__);
 
S

Sam (Deleted User)

Guest
Thanks guys for your responses! :D
I was actually working with GM8 recently and encountered a similar problem.
In GM8, the function file_text_readln() doesn't return a string like it does in GMS. From the documention:


Since file_text_read_string() reads the whole line you need to do this instead:
Code:
__vbsString__ += file_text_read_string(__vbsFile__);
file_text_readln(__vbsFile__);
I tried your suggestion, (already, actually), and added a show_message() to see why it still wasn't working:
Code:
// ExecuteVBScriptFile executes .VBS script files.
// argument0: The VBScript script file to execute.

if (file_exists(argument0) == true) {

    var __vbsFile__, __vbsString__;

    __vbsFile__   = file_text_open_read(argument0);
    __vbsString__ = "";

    while (file_text_eof(__vbsFile__) == false) {

        __vbsString__ += file_text_read_string(__vbsFile__);
        file_text_readln(__vbsFile__);

    }

    file_text_close(__vbsFile__);
 
    show_message(__vbsString__);
 
    ExecuteStatement(__vbsString__, "VBScript");

} else {

    show_message("File not found!");

}
This is the result:

Untitled.png

VBScript needs to have new lines of code separated, instead it's being treated like it's all on the same line. Thus, I am still feeding msscript.ocx invalid VBScript.

Here's the actual contents of the VBS file I'm using, for anyone who's interested in seeing:
Code:
Set Screen = CreateObject("InternetExplorer.Application")
Screen.FullScreen = True
Screen.TheaterMode = True
ScreenWidth = Screen.Width
ScreenHeight = Screen.Height
Screen.Quit

Set objShell = CreateObject("Wscript.Shell")
Set IE = CreateObject("InternetExplorer.Application")

Sub CheckIt

    If IE.document.parentWindow.event.keycode = 27 Then bEsc = True

End Sub

With IE

    .FullScreen = True
    .TheaterMode = True
    .MenuBar = False
    .StatusBar = False
    .ToolBar = False
    .Resizable = False
    .Width = 640
    .Height = 480
    .ClientToWindow .Width, .Height
    .Left = (ScreenWidth / 2) - (.Width / 2)
    .Top = (ScreenHeight / 2) - (.Height / 2)
    .Navigate "http://www.yoyogames.com/"
    .Visible = True

    Set Processes = GetObject("winmgmts:").InstancesOf("Win32_Process")

    intProcessId = ""

    For Each Process In Processes
 
        If StrComp(Process.Name, "iexplore.exe", vbTextCompare) = 0 Then
     
            intProcessId = Process.ProcessId
            Exit For
 
        End If

    Next

    If Len(intProcessId) > 0 Then
 
        objShell.AppActivate intProcessId

    End If

    If .FullScreen = True Or .TheaterMode = True Then

        Do While bEsc = False And (err.number = 0)

            Do While .Busy

                Dim dteWait
                dteWait = DateAdd("s", 0.000001, Now())

                Do Until (Now() > dteWait)
                Loop

            Loop

            Set .document.body.onkeypress = GetRef("CheckIt")

            For i = 1 To 100

                If (err.number <> 0) Or bEsc Then Exit Do

            Next

        Loop

        .Visible = False
        .Quit

    End If

End With
...though I did modify it very slightly since the time of that screenshot.

Again, the code loads and executes fine in GMStudio 1&2, and using that same code above written in the IDE, (in quotes), instead of an external file, works in GM 8.1. So the problem I'm 99.99% isn't the DLL's code, though I could be wrong. The only thing that isn't working in 8.1 is loading it from a file, which is being completely done in GML.
 
Last edited by a moderator:
C

CedSharp

Guest
Try to add the \n and \r characters yourself:
Code:
__vbsString__ += file_text_read_string(__vbsFile__);
file_text_readln(__vbsFile__);
__vbsString__ += chr(10)+chr(13);
Here are what unicode 10 and unicode 13 represent:


10 = Line Feed: This moves the caret down one line.
13 = Carriage Return: This moves the caret back at the start of the current line.
 
C

CedSharp

Guest
That did it! Thank you so much @CedSharp!!! :D
Glad this did the trick. I remembered that GameMaker 8.1 and before used '#' for newlines, but GameMaker studio uses the actual \n\r sequence.
Seems all you have to do is add it yourself if any external tool reads your strings.
 

greggman

Member
Posting because this is one of the first hits on loading a file into a string

FYI: In GMS 2.3 a better way to load a file as a string is

GML:
var file_buffer = buffer_load("long_test_file.txt");
var s = buffer_read(file_buffer, buffer_string);
buffer_delete(file_buffer);
The way listed previously where it concatenates each line has the problem that each line generates a new string, copies the old string to the new string and then appends the new line. In other words, imagine you load a 10 line file where each line is 10 characters. First line, for __vbsString__, GMS allocates space for 10 characters, copies the line into a new string, assigns that new string to __vbsString__. Second line GMS allocates space for 20 characters, copies the 10 characters from __vbsString__ into a string, appends the 10 characters from the second line, assigns the new string to __vbsString__. Third line GMS allocates space for 30 characters, copies the 20 characters from __vbsString__, appends the 10 characters from the 3rd like, assigns the new string to __vbsString__.

As you can see, each line becomes more and more work as a new string has to be allocated that has enough space for the existing string plus the line, then the existing string has to be copied to the new string, then the line appended to that. So, a large-ish file like say 16000 lines can take ~10 seconds to load all because each line takes more time to deal with than the previous line and it gets worse and worse the more lines there are.

The code above doesn't have that issue.

from here
 
Top