totalcross.io
Class CompressedByteArrayStream

totalcross.lang.Object
  extended by totalcross.io.Stream
      extended by totalcross.io.CompressedByteArrayStream

public class CompressedByteArrayStream
extends Stream

Creates a compressed byte array stream, saving memory when reading and writting huge amount of data. Arrays of 16000 bytes will be created and each byte array will be compressed once filled and will be automatically decompressed on read. This saves space but adds a slowdown to the process. It is useful when transferring FTP files to/from the server.

This class cannot be used for output AND input, but only for output OR input, in an absolutely sequential mode (the skipBytes method is NOT implemented): you must write everything, then read everything. To change the mode, use the setMode(READ_MODE or WRITE_MODE) method. No check is made to see if you're in the right mode, but your program will probably crash if you do it in the wrong one.

Sample that transfers bytes to the server:

 CompressedByteArrayStream cbas = new CompressedByteArrayStream(9); // default mode is WRITE_MODE
 for (int i = 0; i < 50000; i++)
    cbas.writeLine("1234567890"); // already appends \r\n
 cbas.flush();
 cbas.setMode(CompressedByteArrayStream.READ_MODE); // prepare for read
 ftp.sendFile(cbas, "bigfile.txt", true);
 // if you want to send another one, just call
 
 cbas.setMode(CompressedByteArrayStream.WRITE_MODE);
 
 
Sample that transfers bytes from the server:
 CompressedByteArrayStream cbas = new CompressedByteArrayStream(9);
 ftp.receiveFile("bigfile.txt", cbas);
 cbas.flush();
 totalcross.lang.String line;
 while ((line = cbas.readLine()) != null)
    // do something with the line!
 
Here is another fully functional sample:
 int i;
 totalcross.lang.String g = "1234567890";
 CompressedByteArrayStream cbas = new CompressedByteArrayStream(9); // default mode is WRITE_MODE
 for (i = 0; i < 50000; i++)
    cbas.writeLine(g); // already appends \r\n
 cbas.flush();
 Vm.debug("size: " + cbas.getCompressedSize() + " -> " + cbas.getSize());
 totalcross.lang.String s;
 for (i = 0; (s = cbas.readLine()) != null; i++)
    if (!g.equals(s))
       Vm.debug("error in " + i);
 if (i != 50000)
    Vm.debug("i differs!");
 cbas.close();
 
Note that, although the sample uses writeLine and readLine, you can store any kind of data, by attaching a DataStream as
 CompressedByteArrayStream cbas = new CompressedByteArrayStream(5);
 DataStream ds = new DataStream(cbas);
 byte[] big = new byte[200000];
 // fill big with something
 ds.writeBytes(big);
 for (int i = 0; i < 100000; i++)
 {
    ds.writeInt(0x123456);
    ds.writeString("Michelle");
    ds.writeDouble(123.456d);
 }
 // well, now we do something with these!
 int realSize = cbas.getSize(); // just for fun
 int compressed = cbas.getCompressedSize(); // just for fun
 ds.readBytes(big);
 for (int i = 0; i < 100000; i++)
 {
    int i = ds.readInt();
    totalcross.lang.String love = ds.writeString(); // Michelle
    double d = ds.writeDouble();
 }
 
Call the close method only when you're completely done in using it: all the internal buffers will be released, and reading from it will crash your program.

Note that the readLine method will not work if there are any character with accentuation.


Nested Class Summary
static class CompressedByteArrayStream.DirectCharConverter
          Implements a CharacterConverter that from char[] to byte[] which just casts the char to byte; thus, ignoring any non-ASCII character.
 
Field Summary
static byte[] crlf
          Defines the line terminator, which is by default \r\n.
static int DESTRUCTIVE_READ_MODE
          used in the setMode method.
static int READ_MODE
          Used in the setMode method.
 ZLibException rwException
          The ZLibException that the readBytes or writeBytes received.
static int WRITE_MODE
          Used in the setMode method.
 
Fields inherited from class totalcross.io.Stream
skipBuffer
 
Constructor Summary
CompressedByteArrayStream()
          Creates a new CompressedByteArrayStream using the maximum compression level (9)
CompressedByteArrayStream(int compressionLevel)
          Creates a new CompressedByteArrayStream, using the given compression level (0 = no compression, 9 = max compression).
 
Method Summary
 void close()
          Deletes all internal buffers.
 void flush()
          After everything was written, call this method to flush the internal buffers and prepare the CompressedByteArrayStream for read.
 int getCompressedSize()
          Returns the compressed size of the data written.
 int getSize()
          Returns the real (uncompressed) size of data written.
 int readBytes(byte[] buffer, int start, int count)
          Transfers count bytes from the internal buffer to the given one.
 void readFully(Stream inputStream, int retryCount, int bufSize)
          Reads all data from the input stream into our buffer.
 String readLine()
          Reads a totalcross.lang.String until the next control character (newline, enter, tab, etc) is read.
 String readUntilNextChar(char c)
          Reads the buffer until the given character is found.
 void setMode(int newMode)
          Changes the mode to the given one, calling flush if in write mode.
 int writeBytes(byte[] buffer, int start, int count)
          This method writes to the byte array, expanding it if necessary.
 void writeLine(String s)
          Writes a line of text.
 
Methods inherited from class totalcross.io.Stream
skipBytes, writeBytes, writeBytes
 
Methods inherited from class totalcross.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

rwException

public ZLibException rwException
The ZLibException that the readBytes or writeBytes received. These methods can't throw Exceptions, because they are implementations of the Stream class, which does not throw Exceptions. So, we store the exception here if you want to show it to the user. Note: you must use this member only if readBytes or writeBytes returned -1, and in no other circunstances, because it may hold an outdated exception.

Since:
TotalCross 1.0 beta 5.

READ_MODE

public static final int READ_MODE
Used in the setMode method. Turns the mode into READ.

See Also:
Constant Field Values

WRITE_MODE

public static final int WRITE_MODE
Used in the setMode method. Turns the mode into WRITE.

See Also:
Constant Field Values

DESTRUCTIVE_READ_MODE

public static final int DESTRUCTIVE_READ_MODE
used in the setMode method. Turns the mode into READ, and after reading each buffer, discards it, releasing memory. The CompressedByteArrayStream will not be able to read the buffer again. This is useful when you download data and then want to read from it, releasing memory on-demand.

See Also:
Constant Field Values

crlf

public static byte[] crlf
Defines the line terminator, which is by default \r\n. To change it to a single \n use CompressedByteArrayStream.crlf = new byte[]{'\n'};

Constructor Detail

CompressedByteArrayStream

public CompressedByteArrayStream(int compressionLevel)
Creates a new CompressedByteArrayStream, using the given compression level (0 = no compression, 9 = max compression).


CompressedByteArrayStream

public CompressedByteArrayStream()
Creates a new CompressedByteArrayStream using the maximum compression level (9)

Method Detail

flush

public void flush()
           throws ZLibException
After everything was written, call this method to flush the internal buffers and prepare the CompressedByteArrayStream for read. It is already called by setMode when it changes the modes.

Throws:
ZLibException
See Also:
setMode(int)

setMode

public void setMode(int newMode)
             throws ZLibException
Changes the mode to the given one, calling flush if in write mode.

Parameters:
newMode - the new mode
Throws:
ZLibException
See Also:
WRITE_MODE, READ_MODE, DESTRUCTIVE_READ_MODE

close

public void close()
Deletes all internal buffers. Do not try to use this class afterwards.


getSize

public int getSize()
Returns the real (uncompressed) size of data written.


getCompressedSize

public int getCompressedSize()
Returns the compressed size of the data written.


readBytes

public int readBytes(byte[] buffer,
                     int start,
                     int count)
Transfers count bytes from the internal buffer to the given one.

Specified by:
readBytes in class Stream
Parameters:
buffer - the byte array to read data into
start - the start position in the array
count - the number of bytes to read
Returns:
the number of bytes read. If an error occured, -1 is returned and the rwException public member will hold the exception.

writeBytes

public int writeBytes(byte[] buffer,
                      int start,
                      int count)
This method writes to the byte array, expanding it if necessary.

Specified by:
writeBytes in class Stream
Parameters:
buffer - the byte array to write data from
start - the start position in the byte array
count - the number of bytes to write
Returns:
the number of bytes written. If an error occured, -1 is returned and the rwException public member will hold the exception.
Since:
SuperWaba 2.0 beta 2

readLine

public String readLine()
                throws ZLibException
Reads a totalcross.lang.String until the next control character (newline, enter, tab, etc) is read.

Returns:
A line of text read from internal buffer or null if no more lines are available.
Throws:
ZLibException

readFully

public void readFully(Stream inputStream,
                      int retryCount,
                      int bufSize)
               throws IOException,
                      ZLibException
Reads all data from the input stream into our buffer. Note that setMode(WRITE) is called prior to writting. When returned, data is ready to be read.

Parameters:
inputStream - The input stream from where data will be read
retryCount - The number of times to retry if no data is read. In remote connections, use at least 5; for files, it can be 0.
bufSize - The size of buffer used to read data.
Throws:
IOException
ZLibException
Since:
SuperWaba 5.7

writeLine

public void writeLine(String s)
Writes a line of text. The \r\n line terminator is appended to the line. You can avoid this by setting CompressedByteArrayStream.crlf = new byte[0];

Parameters:
s - the totalcross.lang.String to be written; cannot be null!

readUntilNextChar

public String readUntilNextChar(char c)
                         throws ZLibException
Reads the buffer until the given character is found.

Returns:
A line of text read from internal buffer or null if no more lines are available.
Throws:
ZLibException