Android Getting Started tutorial | Android compressed string

Android compressed string

Android can compress strings. When transmitting a large number of simple text, you can compress the string before sending it. The receiver receives it and then decompresses it. You can also compress the string and store it in the database.

Class library used

  • GZIPInputStream
  • GZIPOutputStream

Code example

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
​
public class StrZipUtil {
​
 /**
 * @param input String that needs to be compressed
 * @return Compressed string
 * @throws IOException IO
 */
 public static String compress(String input) throws IOException {
 if (input == null || input.length() == 0) {
 return input;
 }
 ByteArrayOutputStream out = new ByteArrayOutputStream();
 GZIPOutputStream gzipOs = new GZIPOutputStream(out);
 gzipOs.write(input.getBytes());
 gzipOs.close();
 return out.toString("ISO-8859-1");
 }
​
 /**
 * @param zippedStr Compressed string
 * @return Decompressed
 * @throws IOException IO
 */
 public static String uncompress(String zippedStr) throws IOException {
 if (zippedStr == null || zippedStr.length() == 0) {
 return zippedStr;
 }
 ByteArrayOutputStream out = new ByteArrayOutputStream();
 ByteArrayInputStream in = new ByteArrayInputStream(zippedStr
 .getBytes("ISO-8859-1"));
 GZIPInputStream gzipIs = new GZIPInputStream(in);
 byte[] buffer = new byte[256];
 int n;
 while ((n = gzipIs.read(buffer)) >= 0) {
 out.write(buffer, 0, n);
 }
 // toString() uses the platform default encoding, and can also be explicitly specified, such as toString("GBK")
 return out.toString();
 }
}

Red rice mobile phone test output

08-09 13:16:53.388 32248-32267/com.rustfisher.ndkproj D/rustApp: Start saving to database ori1 len=304304
08-09 13:16:53.418 32248-32267/com.rustfisher.ndkproj D/rustApp: Stored in database  ori1 len=304304 , It takes about 37 minutes ms
08-09 13:16:53.418 32248-32267/com.rustfisher.ndkproj D/rustApp: Start compression  ori1 len=304304
08-09 13:16:53.438 32248-32267/com.rustfisher.ndkproj D/rustApp: Compression complete  zip1 len=1112 , It takes about 19 minutes ms
08-09 13:16:53.438 32248-32267/com.rustfisher.ndkproj D/rustApp: Save the compressed data into the database zip1.length=1112
08-09 13:16:53.448 32248-32267/com.rustfisher.ndkproj D/rustApp: The compressed data has been entered into the database zip1.length=1112 , It takes about 8 hours ms
08-09 13:16:53.448 32248-32267/com.rustfisher.ndkproj D/rustApp: Decompression start
08-09 13:16:53.488 32248-32267/com.rustfisher.ndkproj D/rustApp: The decompression takes about 36 minutes ms

The storage time is affected by the length of the stored string. String length is positively correlated with storage time.

Glory mobile phone test

08-09 10:38:42.759 23075-23109/com.rustfisher D/rustApp: Start compression  ori1 len=304304
08-09 10:38:42.764 23075-23109/com.rustfisher D/rustApp: Compression complete  zip1 len=1112
08-09 10:38:42.764 23075-23109/com.rustfisher D/rustApp: Decompression start
08-09 10:38:42.789 23075-23109/com.rustfisher D/rustApp: Decompression complete

In this example, the glory compression takes about 5ms and the decompression takes about 25ms.

It can be seen that the ratio of compressed length to the original length is 1112 / 304304, about 0.365%, and the compression and decompression time depends on the mobile phone.

Unzip using ZipFile

Implemented using Kotlin

ZipFile and related classes are used for file decompression in Android.

  • java.util.zip.ZipEntry describes the files in the zip
  • java.util.zip.ZipFile description zip file
  • java.util.zip.ZipInputStream contains ZipEntry information

1. Un zip the assets

This example handles the zip file in assets. In the example, extract a web page file.

ZipFile requires a File object. The files in assets cannot be directly used as files. The first step is to copy a copy of the target zip. The following is the code to perform the copy operation.

val tempFile = File(targetLocation, "tmp-$assetsZipName.zip")
try {
 val inputStream = assets.open(assetsZipName)
 if (tempFile.exists()) {
 tempFile.delete()
 }
 tempFile.createNewFile()
 val copyOs: OutputStream = FileOutputStream(tempFile)
 val tmp = ByteArray(1024)
 var len: Int
 while (((inputStream.read(tmp)).also { len = it }) != -1) {
 copyOs.write(tmp, 0, len)
 }
 copyOs.flush()
 copyOs.close()
 inputStream.close()
 Log.d(TAG, "Copy of temporary files completed")
} catch (e: Exception) {
 Log.e(TAG, "unzipAssetsFile: ", e)
 return
}

If the file is stored in the app or SD card, it won't be so troublesome.

After obtaining the temporary zip, use the temporary zip to decompress.

ZipInputStream is obtained from the file, which contains the information of each file inside the compressed file. Use ZipEntry to describe.

Get the ZipFile object, use the getInputStream(entry) method to get the input stream of each file (directory), and then use the stream to copy each compressed file.

val zipInputStream = ZipInputStream(FileInputStream(tempFile))
val zipFile = ZipFile(tempFile)
var entry: ZipEntry?
​
while (zipInputStream.nextEntry.also { entry = it } != null) {
 val outFile = File(targetLocation, entry!!.name)
 Log.d(TAG, "Current file: $entry -> $outFile")
 if (outFile.parentFile != null && !outFile.parentFile!!.exists()) {
 outFile.parentFile!!.mkdir()
 }
​
 if (!outFile.exists()) {
 if (entry!!.isDirectory) {
 outFile.mkdirs()
 continue
 } else {
 outFile.createNewFile()
 }
 }
​
 val bis = BufferedInputStream(zipFile.getInputStream(entry))
 val bos = BufferedOutputStream(FileOutputStream(outFile))
 val entryTmpArr = ByteArray(1024)
 while (true) {
 val readLen = bis.read(entryTmpArr)
 if (readLen == -1) {
 break
 }
 bos.write(entryTmpArr, 0, readLen)
 }
 bos.close()
 bis.close()
 Log.d(TAG, "Extract the file $outFile")
}

The whole method code is as follows

/**
 * Unzip a zip specified in assets
 */
private fun unzipAssetsFile(assetsZipName: String, targetLocation: String) {
 Log.d(TAG, "[unzipAssetsFile] targetLocation: $targetLocation")
 val targetDir = File(targetLocation)
 if (!targetDir.exists()) {
 targetDir.mkdirs()
 }
 val tempFile = File(targetLocation, "tmp-$assetsZipName.zip")
 try {
 val inputStream = assets.open(assetsZipName)
 if (tempFile.exists()) {
 tempFile.delete()
 }
 tempFile.createNewFile()
 val copyOs: OutputStream = FileOutputStream(tempFile)
 val tmp = ByteArray(1024)
 var len: Int
 while (((inputStream.read(tmp)).also { len = it }) != -1) {
 copyOs.write(tmp, 0, len)
 }
 copyOs.flush()
 copyOs.close()
 inputStream.close()
 Log.d(TAG, "Copy of temporary files completed")
 } catch (e: Exception) {
 Log.e(TAG, "unzipAssetsFile: ", e)
 return
 }
​
 val zipInputStream = ZipInputStream(FileInputStream(tempFile))
 val zipFile = ZipFile(tempFile)
 var entry: ZipEntry?
​
 while (zipInputStream.nextEntry.also { entry = it } != null) {
 val outFile = File(targetLocation, entry!!.name)
 Log.d(TAG, "Current file: $entry -> $outFile")
 if (outFile.parentFile != null && !outFile.parentFile!!.exists()) {
 outFile.parentFile!!.mkdir()
 }
​
 if (!outFile.exists()) {
 if (entry!!.isDirectory) {
 outFile.mkdirs()
 continue
 } else {
 outFile.createNewFile()
 }
 }
​
 val bis = BufferedInputStream(zipFile.getInputStream(entry))
 val bos = BufferedOutputStream(FileOutputStream(outFile))
 val entryTmpArr = ByteArray(1024)
 while (true) {
 val readLen = bis.read(entryTmpArr)
 if (readLen == -1) {
 break
 }
 bos.write(entryTmpArr, 0, readLen)
 }
 bos.close()
 bis.close()
 Log.d(TAG, "Extract the file $outFile")
 }
 val delTmp = tempFile.delete()
 Log.d(TAG, "After decompression, delete the temporary file $delTmp")
}

2. Computer compressed zip

If the mac is compressed in the Finder, the system may create one during operation__ Directory of MACOS. To avoid this directory. We can use the zip command to compress.

zip -r target.zip sourceDir

[Android zero foundation tutorial video reference]

Keywords: Android

Added by Carlo Gambino on Fri, 17 Dec 2021 17:41:23 +0200