var fData:ByteArray = new ByteArray();
I need to remove some bytes in this array, but can't find any public method in Flash to do that.
I searched something like fData.remove(start,length) but with no success.
here is a code
function _dlProgressHandler(evt:ProgressEvent):void { //this is progressEvent for URLStream
............... ///some code
var ff:ByteArray = new ByteArray();
stream.readBytes(ff,0,stream.bytesAvailable);
fileData.writeBytes(ff,0,ff.length); //stream writes into fileData byteArray
//and here is cutter:
fileData.position=0;
fileData.writeBytes(ff,100,fileData.length);
fileData.length=fileData.length-100);
}
So, fileData cut itself unpredictably sometimes.
Sometimes old blocks're found twice, sometimes they're not found at all.
You can always just only read the bytes that you want, which will have the same effect as discarding the bytes that you don't want. As a very simple example, assume you have a ByteArray that is 10 bytes long and you want to discard the first 3 bytes:
var newBytes:ByteArray = new ByteArray();
newBytes.writeBytes(fData, 2, 7);
So instead of removing the bytes that you don't want from fData, you just create a new ByteArray and only get they bytes that you want from fData.
Obviously, if the sequence of bytes you want to remove is not just a sequence from the beginning or end of fData it will be a little more complicated, but the method remains the same: read the bytes that you want, instead of removing the ones you don't.
AS-3 is actually very nice sometimes. This removes bytes from your array anywhere you want. Beginning, middle or the end. Just need to check indices to avoid IndexOutOfBounds
var array: ByteArray = ...; // create the byte array or load one
var index: int = 4;
var count: int = 5;
array.position = index;
array.writeBytes(array, index + count, array.length - (index + count));
array.length = array.length - count;
I tested this and it works well, just the checks are missing
a byte array can write to itself
Related
I am attempting to read the data directly from a SharedObject (.sol) file in as3. I've been able to extract the header information :
// HEADER BYTES
var header1:int = stream.readShort();
// LENGTH
var length:int = header1 & 0x3f;
if (length == 0x3f)
length = stream.readInt();
// FILETYPE - should be "TCSO"
var sig:String = stream.readUTFBytes( 4 );
// PAD: Unused, 6 bytes long 0x00 0x04 0x00 0x00 0x00 0x00 0x00
var pad:ByteArray = new ByteArray();
stream.readBytes( pad, 0, 6 );
// NAME
// 2 byte short length
var nameLength:int = stream.readUnsignedShort();
var name:String = stream.readUTFBytes( nameLength );
var amfVersion:int = stream.readInt();
But I am having troubles interpreting the data that follows:
var data:ByteArray = new ByteArray();
stream.readBytes( data );
I was under the belief it was stored as AMF data and hence the ByteArray.readObject function should correctly decode it:
var sharedObjectData:Object = data.readObject();
However this fails with all of my test objects with a Range Error.
Does anyone know the format of the data in a SharedObject or how to decode it?
REASON: I am doing this because we have an app deployed and accidentally changed the name of the swf which made the SharedObject inaccessible using the SharedObject class.
ie. SharedObject in app_new.swf can't read #SharedObjects/app.swf/objectname.sol
So need to parse the sol SharedObject file using direct File access.
I don't use sharedObjects (never needed them) so I can only advise about bytes. Anytime you get "out of range/bounds" error it can be fixed with checking & correcting the byte array's .position.
In your case, first trace position and length of data to be sure there is enough data in front (from current position) to read an Object out of those remaining bytes.
Other options to try for solving "Out of range" error: (use .writeBytes instead of .readBytes)
var data:ByteArray = new ByteArray();
//or replace "stream.position" with offset value where you think "Object" data begins
data.writeBytes( stream, stream.position, stream.bytesAvailable );
data.position = 0; //reset before reading
var sharedObjectData:Object = data.readObject();
Also look at Inflate and Uncompress just incase data must be expanded before usage.
Goal is to show progress of jpeg encoding from bitmap. I have couple of bitmaps that need to be encoded. So I get the total number of bytes as was suggested here:
for (var i:int = 0; i < bitmaps.length; i++)
{
bmp = bitmaps[i];
total_bytes += bmp.getPixels(bmp.rect).length;
}
Then I'm trying to show progress when doing asychronous encoding. I get a ProgressEvent which gives me bytesLoaded. So I calculate the progress like so:
total_loaded_bytes += event.bytesLoaded;
var percentage:int = ((total_loaded_bytes / total_bytes) * 100);
However, total_bytes does not add up to total_loaded_bytes. Total bytes loaded is way highter.
A wrong approach to use bytesLoaded property. This is not to be blandly added up, as this contains the total of already loaded bytes bu the Loader object that issued the event. And a wrong approach on getting total bytes too, you need to use event.bytesTotal from within the progress event listener, since you are loading bytes, not pixels. Even if you are uploading. Also, the exact progress may be totally unavailable for asynchronous encoding, you are only displaying the uploading/downloading progress.
Update: to receive an accumulated progress, do something like this:
var loaders:Array=[]; // array of loaders. Fill manually
var progress:Array=[]; // fill with zeroes alongside loaders, should be same size
function updateProgress(e:ProgressEvent):void {
var loader:Loader=e.target as Loader;
if (!loader) return; // or skip type coercion, we just need the reference
var i:int=loaders.indexOf(loader); // now get an index from array
if (i<0) return; // not found, drop it
progress[i]=e.bytesLoaded; // and update progress array with new value
// now sum up progress array and divide by aggregated bytesTotal
// this one is up to you
}
I am a beginner in ActionScript 3, I am trying to traverse an array of MovieClips and pick hundred random Clips out of that and place those instances on stage but sometimes the code produce an undefined error. I am confused why as the code works well most of the times and there are never any compile time errors.
Here is my code:
for(var i:int = 0; i<100;i++)
{
var rndNum:Number = Math.round(Math.random()*arr.length);
this.addChild(arr[rndNum]);
}
Because you are rounding the randomly generated index which could result in an index out of bound Exception, and that is because you are generating a number up to the array's Length and the number representing the total length of an array can never be a valid index for that Array since the index starts at 0.
Simply change the Math.round to Math.floor
var rndNum:Number = Math.floor(Math.random()*arr.length);
or do a -1 from the arr's length:
var rndNum:Number = Math.round(Math.random()*(arr.length-1));
I am trying to understand the significance of null bytes in a ByteArray. Do they act like a terminator? I mean, can we not write further into the ByteArray once a null byte has been written?
For instance,
import flash.utils.*;
public class print3r{
public function print3r{
Util.print(nullout());
}
public function nullout:ByteArray (){
var bytes:ByteArray = new ByteArray();
bytes.writeInt(((403705888 + 1) - 1)); // Non Printable Characters
bytes.writeInt(((403705872 - 1) + 1)); // Non Printable Characters
bytes.writeInt(0x18101000); // Notice the NullByte in this DWORD
bytes.writeInt(0x41424344); // ASCII Characters ABCD
return bytes;
}
}
new print3r;
This gives a blank output.
Now, if I replace the DWORD, 0x18101000 with 0x18101010, this time I can see the ASCII padding, ABCD in the output.
My question is that, is it possible to write past the null byte into the ByteArray()?
The reason I ask is because I have seen in an ActionScript code, that a lot of writeInt and writeByte operations are performed on the ByteArray even after the null byte is written.
Thanks.
is it possible to write past the null byte into the ByteArray()?
Of course it is. ByteArray -- is a chunk of raw data. You can write whatever you like there, and you can read in whatever way you like (using zero bytes as delimiters or whatever else you may want to do).
What you see when you send your bytes to standard output with trace(), depends solely on what you actually do with your data to convert it to a string. There are several ways of converting an array of bytes to string. So, your question is missing the explanation of what Util.print() method does.
Here are several options for converting bytes to a string:
Loop through bytes and output characters, encoding is up to you.
Read a string with ByteArray.readUTFBytes(). This method reads utf-encoded symbols; it stops when zero character is encountered.
Read a string with ByteArray.readUTF(). This method expects your string to be prefixed with unsigned short indicating its length. In other terms it is the same as ByteArray.readUTFBytes().
Use ByteArray.toString(). This is what happens when you simply do trace(byteArray);. This method ignores zero bytes and outputs the rest. This method uses System.useCodePage setting to decide on the encoding, and can use UTF BOM if the data begins with it.
Here are some tests that illustrate the above:
var test:ByteArray = new ByteArray();
// latin (1 byte per character)
test.writeUTFBytes("ABC");
// zero byte
test.writeByte(0);
// cyrillic (2 bytes per character)
test.writeUTFBytes("\u0410\u0411\u0412");
trace(test); // ABCАБВ
trace(test.toString()); // ABCАБВ
test.position = 0;
trace(test.readUTFBytes(test.length)); // ABC
// simple loop
var output:String = "";
var byte:uint;
for (var i:uint = 0; i<test.length; i+=1) {
byte = uint(test[i]);
if (output.length && i%4 == 0) {
output += " ";
}
output += (byte > 0xF ? "" : "0") + byte.toString(16);
}
trace(output); // 41424300 d090d091 d092
Writing a null to a byte array has no significance as far as I know. The print function might however use it as a string terminator.
var bytes:ByteArray = new ByteArray;
bytes.writeInt(0);
trace(bytes.length); // prints 4
trace(bytes.toString().length); // prints 4
When I run the above code the output suggests that every character in the string returned by toString contains one byte from the ByteArray. This is of course great if you want to display the content of the ByteArray, but not so great if you want to send its content encoded in a string and the size of the string matters.
Is it possible to get a string from the ByteArray where every character in the string contains two bytes from the ByteArray?
You can reinterpret your ByteArray as containing only shorts. This lets you read two bytes at a time and get a single number value representing them both. Next, you can take these numbers and reinterpret them as being character codes. Finally, create a String from these character codes and you're done.
public static function encode(ba:ByteArray):String {
var origPos:uint = ba.position;
var result:Array = new Array();
for (ba.position = 0; ba.position < ba.length - 1; )
result.push(ba.readShort());
if (ba.position != ba.length)
result.push(ba.readByte() << 8);
ba.position = origPos;
return String.fromCharCode.apply(null, result);
}
There is one special circumstance to pay attention to. If you try reading a short from a ByteArray when there is only one byte remaining in it, an exception will be thrown. In this case, you should call readByte with the value shifted 8 bits instead. This is the same as if the original ByteArray had an extra 0 byte at the end. (making it even in length)
Now, as for decoding this String... Get the character code of each character, and place them into a new ByteArray as shorts. It will be identical to the original, except if the original had an odd number of bytes, in which case the decoded ByteArray will have an extra 0 byte at the end.
public static function decode(str:String):ByteArray {
var result:ByteArray = new ByteArray();
for (var i:int = 0; i < str.length; ++i) {
result.writeShort(str.charCodeAt(i));
}
result.position = 0;
return result;
}
In action:
var ba:ByteArray = new ByteArray();
ba.writeInt(47);
ba.writeUTF("Goodbye, cruel world!");
var str:String = encode(ba);
ba = decode(str);
trace(ba.readInt());
trace(ba.readUTF());
Your question is a bit confusing. You have written a 4 byte int to your ByteArray. You haven't written any characters (unicode or other) to it. If you want to pass text, write text and pass it as UTF8. It will take less space than having two bytes for every character, at least for most western languages.
But honestly, I'm not sure I understood what you are trying to accomplish. Do you want to send numbers or text? What backend are you talking to? Do you need a ByteArray at all?