How can I avoid error #2030: End of file was encountered. - AS3 - actionscript-3

I am trying to make this game in Flash / AS3 which goes on as long as the player doesn't lose. The longer the player goes for, the higher his/her score is.
I also need to save the high score, so I decided to save this using a text file. I open the file with mode UPDATE so that if the file doesn't exist it is created and I can read/write. But obviously, when the file is first created it is empty so when I try to read the data in the file it returns error #2030. It then doesn't execute any of the code that involves the file stream. Also even if there is a number in the file, I can't read it because the program doesn't know how many digits the high score is going to be. This is the code that I am using:
var file:File = File.documentsDirectory;
file = file.resolvePath("hscore.txt");
var fileStream:FileStream = new FileStream();
fileStream.openAsync(file, FileMode.UPDATE);
var buffer:Number = fileStream.readInt();
if (buffer > 0){
if (score > buffer){
buffer = score;
fileStream.writeInt(buffer);
}
else{
highScore.text = String(buffer);
}
}
else{
fileStream.writeInt(score);
highScore.text = String(score);
}
fileStream.close();
I have tried using readUTF/writeUTF and readUTFBytes/writeUTFBytes instead of readInt/writeInt, but with readUTF/writeUTF it just gives me the same error and with readUTFBytes/writeUTFBytes the program would need to know how many digits the high score is. If anyone knows how to get around a 2030 error or knows how to read a file without reaching the end or knows how to see how many digits there are in the file please let me know.
I could have added a line to the file telling the program how many digits there are but when the file is new the file stream would reach the end of the file while trying to read the number of digits. I am also open to other methods of storing the high score and reading it later. Thanks in advance for any help.
P.S. I am trying to do this with Adobe AIR for Android

Answering my own question based on help from comments:
Open and close the file without making any changes so that if file doesn't exist the file is created.
Check the file size, 1 byte = 1 digit (stored in UTF-8).
Read appropriate number of bytes, make changes as needed, etc.
]
Error 2030 avoided! :D
Thanks to #Vesper and #Craig
*****Edit*****
Realised you don't need to close the file in the first step...
*****Edit2*****
Not UTF-8, ASCII

Related

Append string to a Flash AS3 shared object: For science

So I have a little flash app I made for an experiment where users interact with the app in a lab, and the lab logs the interactions.
The app currently traces a timestamp and a string when the user interacts, it's a useful little data log in the console:
trace(Object(root).my_date + ": User selected the cupcake.");
But I need to move away from using traces that show up in the debug console, because it won't work outside of the developer environment of Flash CS6.
I want to make a log, instead, in a SO ("Shared Object", the little locally saved Flash cookies.) Ya' know, one of these deals:
submit.addEventListener("mouseDown", sendData)
function sendData(evt:Event){
{
so = SharedObject.getLocal("experimentalflashcookieWOWCOOL")
so.data.Title = Title.text
so.data.Comments = Comments.text
so.data.Image = Image.text
so.flush()
}
I don't want to create any kind of architecture or server interaction, just append my timestamps and strings to an SO. Screw complexity! I intend to use all 100kb of the SO allocation with pride!
But I have absolutely no clue how to append data to the shared object. (Cough)
Any ideas how I could create a log file out of a shared object? I'll be logging about 200 lines per so it'd be awkward to generate new variable names for each line then save the variable after 4 hours of use. Appending to a single variable would be awesome.
You could just replace your so.data.Title line with this:
so.data.Title = (so.data.Title is String) ? so.data.Title + Title.text : Title.text; //check whether so.data.Title is a String, if it is append to it, if not, overwrite it/set it
Please consider not using capitalized first letter for instance names (as in Title). In Actionscript (and most C based languages) instance names / variables are usually written with lowercase first letter.

how to organize more than 40000 mp3 files in wp8?

I want to place about 45000 mp3 files in my wp8 app,
all of them are sound effect and less than 5k bytes,
however the total space are more than 150m bytes.
I think there are 2 ways to store them.
store each of mp3 as a separate file, it need more than 150m space in logical and actually more than 220m
use a binary file to save all of them in one file, maybe like below structure:
first 4bytes : --length of mp3 file name;
first byte[]: --store the mp3 file name;
senc 4bytes: --length of mp3 file;
senc byte[]: --store the real content of mp3;
and repeat this to append all of them to one file.
It need only 150m , however I have to seek the position of each mp3 file.
Which one you think is better? I prefer to the second solution. However I don't find any api can seek from offset 0 to offset 150*1024*1024,and maybe this will raise performance issue.
I'd use the second option with an index and use of BinaryReader. You can seek to a position (reference) in a file (something like this):
byte[] mp3File;
// Get the file.
var file = await dataFolder.OpenStreamForReadAsync("combined_mp3s.bin");
using (var binReader = new BinaryReader(file))
{
binReader.Postion = offset; // using your math ...
var fileName = binReader.ReadString(); (length prefixed string read)
// or you could read the size on your own and read the characters
var mp3FileLen = binReader.ReadInt32();
mp3File = binReader.ReaderBytes(mp3FileLen);
}
I would suggest you have a hash/dictionary of the file names and starting position of the data for each file stored separately so your application can quickly locate the contents of a file without doing a scan.
Downloading
You may also want to consider breaking the huge file into some smaller files for a better download experience. You could append to the huge file as the contents of a group or individual file is available on the phone.
The problem with your second alternative is that by avoiding the filesystem, you lose a great deal of convenience that the filesystem would afford you.
Perhaps most importantly, you can now (using your proposed data-structure) no longer retrieve a file with a particular name without scanning (potentially) the entire file.
The extra space in the filesystem is probably well used.

Saving and Loading progress in action script 3

I've looked everywhere for this answer..but I am not quite sure on how to do it exactly...
I am making a Flash Game using Flash AS3...
I need options where user can save and load their progress..
can somebody give a step by step on how to do this please? I am very new to actionscript...
usually other tuts shows u how to save certain variables
Cookies!
Lucky us it's very simple. Unlucky us it's not obvious how it's done:
// have that referenced all the time:
var cookies: SharedObject = SharedObject.getLocal("myGameData");
// start saving
cookies.data.progress = 50;
cookies.data.lives = 5;
cookies.data.anyRandomVariable = "my name or something";
cookies.flush();
// now it's saved
// start loading
var progress: Number = cookies.data.progress;
var lives: int = cookies.data.lives = 5;
var anyRandomBlah: String = cookies.data.anyRandomVariable;
// now it's loaded
(following the comments above...)
Yes, pretty much along those lines. I was asking questions to try to get you to see that you do actually have variables/data which you'd save. =b
If you want to save in the middle of the level, it is up to you... I don't know how you've designed your game, but basically you can write the saving code to trigger whenever you want based on any conditions you want.
For saving in the middle of levels, since you are handling the saving and loading you could try having a value like level "7.5" or whatever notation you want to indicate a level that is partway done. Or just use whole numbers like 750 and treat it as a percentage (level 7 at 50% done). And so forth. It's up to you.
A very similar question has been asked how to save a current frame value using a SharedObject. In your case, replace 'current frame' with whatever values you want to save:
Actionscript 3 saving currentframe location to local hard drive?

Actionscript 3 saving currentframe location to local hard drive?

I asked similar question sometime ago, but I am making new one to be much more specific with my question with some example!
I´ve found this code snippet/tutorial from googling, but I cant seem to figure out how to modify it for my needs:
// open a local shared object called "myStuff", if there is no such object - create a new one
var savedstuff:SharedObject = SharedObject.getLocal("myStuff");
// manage buttons
btnSave.addEventListener(MouseEvent.CLICK, SaveData);
btnLoad.addEventListener(MouseEvent.CLICK, LoadData);
function SaveData(MouseEvent){
savedstuff.data.username = nameField.text // changes var username in sharedobject
savedstuff.flush(); // saves data on hard drive
}
function LoadData(MouseEvent){
if(savedstuff.size>0){ // checks if there is something saved
nameField.text = savedstuff.data.username} // change field text to username variable
}
// if something was saved before, show it on start
if(savedstuff.size>0){
nameField.text = savedstuff.data.username}
So what I am trying to figure out how to do, is to save users current frame to local hard drive, as my flash progress is based on frame location. yeah, so how do I modify it so that it stores data of current frame? and how about current frame inside movieclip, if that is makes things different?
help MUUUCH appreciated! thanks!
In your example it looks like it is already saving something to the shared object:
savedstuff.data.username = nameField.text;
Just replace it with the movie clip frame value instead (and probably under a different property name other then "username").
Then on load, there is another line where it loads the data:
nameField.text = savedstuff.data.username;
It would be the same way, except replace "username" with whatever property name you choose. Then you may have to parse into an int again and use it to restore progress however way you have it set up.

When trying to select a column of type BLOB, SQLStatement throws a RangeError #2006: The supplied index is out of bounds

var imageData:ByteArray = new ByteArray();
var headshotStatement:SQLStatement = new SQLStatement();
headshotStatement.sqlConnection = dbConnection;
var headshotStr:String = "SELECT headshot FROM ac_images WHERE id = " + idx;
headshotStatement.text = headshotStr;
headshotStatement.execute();
Error references the final line in this block. I found a few references online where people are unable to select a BLOB using AS3 that has had data inserted into it from an external program, which is my exact situation.
Exact error trace is:
RangeError: Error #2006: The supplied index is out of bounds.
at flash.data::SQLStatement/internalExecute()
at flash.data::SQLStatement/execute()
at edu.bu::DataManager/getHeadshotImageData()[omitted/DataManager.as:396]
at edu.bu::CustomStudentProfileEditorWindow/editStudent()[omitted/CustomStudentProfileEditorWindow.mxml:194]
at edu.bu::CustomStudentProfileEditorWindow/profileEditor_completeHandler()[omitted/CustomStudentProfileEditorWindow.mxml:37]
at edu.bu::CustomStudentProfileEditorWindow/___CustomStudentProfileEditorWindow_Window1_creationComplete()[omitted/CustomStudentProfileEditorWindow.mxml:9]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.core::UIComponent/dispatchEvent()[E:\dev\4.x\frameworks\projects\framework\src\mx\core\UIComponent.as:12528]
at mx.core::UIComponent/set initialized()[E:\dev\4.x\frameworks\projects\framework\src\mx\core\UIComponent.as:1627]
at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\4.x\frameworks\projects\framework\src\mx\managers\LayoutManager.as:759]
at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\4.x\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1072]
Any ideas what could be wrong with the data that is causing AS3 to choke?
Edit: I've tried to insert the same data into a binary type field using SQLite Manager 3.5 for OS X with the same result. I'm working with a JPG, going to try other image formats, though I can't begin to guess which supplied index is out of bounds given that trying to jump to the definition just states that it's getting it from a SWC and I can't see. Grasping at straws before I distribute the data in a zip and decompress it on the fly, which I don't want to do.
Edit 2, Workaround Edition: For now, I've written a quick MXML Window that prompts for the images and inserts the data into the database. Would still love to know why another application can't store BLOB data in a way that SQLStatement understands. I'm essentially setting up a few buttons that prompt for file paths to the images I want in the database, reading them in with readBytes() to a ByteArray, and storing that into the SQLite db using SQLStatement. I am then able to read the image back without difficulty.
Edit 3: Here is an image of the table structure. Note, this same table is being used successfully when I have Flash do the database image insert, as opposed to some other tool which properly stores the data in the BLOB field for every other application but Flash...
From the Air docs, CAST is supported to bring in non-AMF blobs as of Air 2.5. I had the same issue with a database/blob field created in python and used in Air and this solved it for me.
example from docs:
stmt.text = "SELECT CAST(data AS ByteArray) AS data FROM pictures;";
stmt.execute();
var result:SQLResult = stmt.getResult();
var bytes:ByteArray = result.data[0].data;
http://help.adobe.com/en_US/as3/dev/WSd47bd22bdd97276f1365b8c112629d7c47c-8000.html
I found your question because I have experienced the same problem.
I have finally been able to fix and solve my problem maybe you should look on my solution maybe this can help you solves yours: What is the first bytes in a Blob column SQlite Adobe AIR? Blob Sizeinfo?
It's all fault of Adobe AIR and AMF (ActionScript Message Format) which try to store the ByteArray object as a formatted binary. So it add a first byte 12 which is the TypeCode for the ByteArray followed by a int-29 integer for the size-length and finally the raw data.
So if you want to store a binary blob data into a sqlite which must be read by Adobe AIR you must add those informations to allow Adobe Air to convert everything back into a ByteArray.