在 TOIT 中压缩数据
Compressing data in TOIT
TOIT库包含zip.toit模块,希望系统支持数据压缩和解压。不幸的是,没有例子。能否给出最简单的数据压缩解压的例子,比如字符串或者二进制数组?
zlib
库目前仅支持压缩。
基本上你必须:
- 创建压缩器(zlib 或 gzip)。
- 在一个任务中提供数据
- read/use另一个任务中的压缩数据。
这是一个例子:
import zlib
import bytes
import monitor
main:
// We use a semaphore to let the main task know when all the
// compressed data has been handled.
// If the data is just sent over the network, then the semaphore
// wouldn't be necessary. The second task (`t`) would just finish
// once all data has been processed.
done := monitor.Semaphore
// We use a byte-buffer to accumulate all the data. If the data is
// to be sent somewhere, then it's better to just do that directly,
// instead of using memory here.
accumulator := bytes.Buffer
// There are other encoders as well, but the gzip-encoder has
// the advantage that it produces `.gz` compatible data.
compressor := zlib.RunLengthGzipEncoder
// We create a second task that takes out the already compressed
// data of the compressor.
t := task::
while data := compressor.read:
accumulator.write data
// We increment the semaphore, so that the other (original) task
// knows that we are done processing the data.
done.up
// In this task we now add data. As example, it's just "foo", but any
// string or byte-array would work.
// Can be called multiple times.
compressor.write "foo"
// The compressor must be closed.
// This flushes the last remaining data, and lets the reading
// task know that it is done.
compressor.close
// We wait for the reading task to signal that all data is handled.
done.down
// Show the data that was accumulated.
// You would normally just send it somewhere, and not print it.
print accumulator.buffer.size
print accumulator.buffer
小NB。您还可以在 android 中解码生成的二进制数组。我通过编写一个小的 java 应用程序来测试这个:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class MainActivity extends AppCompatActivity {
// byte array from toit:
byte[] bytes = { 31, -117, 8, 0, 0, 0, 0, 0, 0, -1, 75, -53, -49, 7, 0, 33, 101, 115, -116, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static final String TAG = "GZip";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String foo = null;
try {
foo = decompress(bytes);
}
catch(IOException exception) {
Log.d(TAG, exception.toString());
}
Log.d(TAG, "decompress->[" + foo + "]");
}
public static String decompress(byte[] compressed) throws IOException {
final int BUFFER_SIZE = 32;
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
StringBuilder string = new StringBuilder();
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
string.append(new String(data, 0, bytesRead));
}
gis.close();
is.close();
return string.toString();
}
TOIT库包含zip.toit模块,希望系统支持数据压缩和解压。不幸的是,没有例子。能否给出最简单的数据压缩解压的例子,比如字符串或者二进制数组?
zlib
库目前仅支持压缩。
基本上你必须:
- 创建压缩器(zlib 或 gzip)。
- 在一个任务中提供数据
- read/use另一个任务中的压缩数据。
这是一个例子:
import zlib
import bytes
import monitor
main:
// We use a semaphore to let the main task know when all the
// compressed data has been handled.
// If the data is just sent over the network, then the semaphore
// wouldn't be necessary. The second task (`t`) would just finish
// once all data has been processed.
done := monitor.Semaphore
// We use a byte-buffer to accumulate all the data. If the data is
// to be sent somewhere, then it's better to just do that directly,
// instead of using memory here.
accumulator := bytes.Buffer
// There are other encoders as well, but the gzip-encoder has
// the advantage that it produces `.gz` compatible data.
compressor := zlib.RunLengthGzipEncoder
// We create a second task that takes out the already compressed
// data of the compressor.
t := task::
while data := compressor.read:
accumulator.write data
// We increment the semaphore, so that the other (original) task
// knows that we are done processing the data.
done.up
// In this task we now add data. As example, it's just "foo", but any
// string or byte-array would work.
// Can be called multiple times.
compressor.write "foo"
// The compressor must be closed.
// This flushes the last remaining data, and lets the reading
// task know that it is done.
compressor.close
// We wait for the reading task to signal that all data is handled.
done.down
// Show the data that was accumulated.
// You would normally just send it somewhere, and not print it.
print accumulator.buffer.size
print accumulator.buffer
小NB。您还可以在 android 中解码生成的二进制数组。我通过编写一个小的 java 应用程序来测试这个:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class MainActivity extends AppCompatActivity {
// byte array from toit:
byte[] bytes = { 31, -117, 8, 0, 0, 0, 0, 0, 0, -1, 75, -53, -49, 7, 0, 33, 101, 115, -116, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static final String TAG = "GZip";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String foo = null;
try {
foo = decompress(bytes);
}
catch(IOException exception) {
Log.d(TAG, exception.toString());
}
Log.d(TAG, "decompress->[" + foo + "]");
}
public static String decompress(byte[] compressed) throws IOException {
final int BUFFER_SIZE = 32;
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
StringBuilder string = new StringBuilder();
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
string.append(new String(data, 0, bytesRead));
}
gis.close();
is.close();
return string.toString();
}