From 81a6a5b64b423bad8f1bf0e3f24d0f65c585f44b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Reimar=20D=C3=B6ffinger?= Date: Fri, 23 Jun 2017 23:09:02 +0200 Subject: [PATCH] Fix performance of unpacking zip files. Unfortunately the zip functions absolutely need the input stream to be buffered, or performance will be very bad. Also the zip read functions return very short reads (< 1 kB on average), so we need to buffer them up to get a usable write size. Using a FileChannel improves performance a little bit in addition, but it's probably the least critical change. --- .../dictionary/DictionaryManagerActivity.java | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/com/hughes/android/dictionary/DictionaryManagerActivity.java b/src/com/hughes/android/dictionary/DictionaryManagerActivity.java index 6d76954..266ea87 100644 --- a/src/com/hughes/android/dictionary/DictionaryManagerActivity.java +++ b/src/com/hughes/android/dictionary/DictionaryManagerActivity.java @@ -70,6 +70,7 @@ import android.widget.ToggleButton; import com.hughes.android.dictionary.DictionaryInfo.IndexInfo; import com.hughes.android.util.IntentLauncher; +import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -78,6 +79,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -190,7 +193,7 @@ public class DictionaryManagerActivity extends ActionBarActivity { File localZipFile = null; InputStream zipFileStream = null; ZipInputStream zipFile = null; - OutputStream zipOut = null; + FileOutputStream zipOut = null; try { if (zipUri.getScheme().equals("content")) { zipFileStream = context.getContentResolver().openInputStream(zipUri); @@ -199,7 +202,7 @@ public class DictionaryManagerActivity extends ActionBarActivity { localZipFile = new File(zipUri.getPath()); zipFileStream = new FileInputStream(localZipFile); } - zipFile = new ZipInputStream(zipFileStream); + zipFile = new ZipInputStream(new BufferedInputStream(zipFileStream)); final ZipEntry zipEntry = zipFile.getNextEntry(); Log.d(LOG, "Unzipping entry: " + zipEntry.getName()); File targetFile = new File(application.getDictDir(), zipEntry.getName()); @@ -385,16 +388,24 @@ public class DictionaryManagerActivity extends ActionBarActivity { unregisterReceiver(broadcastReceiver); } - private static int copyStream(final InputStream in, final OutputStream out) + private static void copyStream(final InputStream ins, final FileOutputStream outs) throws IOException { + ByteBuffer buf = ByteBuffer.allocateDirect(1024 * 64); + FileChannel out = outs.getChannel(); int bytesRead; - final byte[] bytes = new byte[1024 * 16]; - while ((bytesRead = in.read(bytes)) != -1) { - out.write(bytes, 0, bytesRead); - } - in.close(); - out.close(); - return bytesRead; + int pos = 0; + final byte[] bytes = new byte[1024 * 64]; + do { + bytesRead = ins.read(bytes, pos, bytes.length - pos); + if (bytesRead != -1) pos += bytesRead; + if (bytesRead == -1 ? pos != 0 : 2*pos >= bytes.length) { + buf.put(bytes, 0, pos); + pos = 0; + buf.flip(); + while (buf.hasRemaining()) out.write(buf); + buf.clear(); + } + } while (bytesRead != -1); } @Override -- 2.43.0