Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Java:将文件从zip文件读入webview/string,为什么ZipInputStream会限制读取性能?_Java_Android_Zip_Android Webview_Unzip - Fatal编程技术网

Android Java:将文件从zip文件读入webview/string,为什么ZipInputStream会限制读取性能?

Android Java:将文件从zip文件读入webview/string,为什么ZipInputStream会限制读取性能?,java,android,zip,android-webview,unzip,Java,Android,Zip,Android Webview,Unzip,让我们先解释一下 我正在使用webView加载HTML应用程序。为了稍微保护源代码(脚本kiddie protection),我想从一个(受保护的)zip文件加载html代码。html代码已经打包、缩小、组合等,因此大小只有700kb(未打包)。这工作得很好,但有一个问题,它有点慢 在下面的示例中,我从zip读取html文件,并将结果放入字符串中。此字符串将用于使用以下代码将html代码加载到webview: this.webView.loadDataWithBaseURL("file:///a

让我们先解释一下

我正在使用webView加载HTML应用程序。为了稍微保护源代码(脚本kiddie protection),我想从一个(受保护的)zip文件加载html代码。html代码已经打包、缩小、组合等,因此大小只有700kb(未打包)。这工作得很好,但有一个问题,它有点慢

在下面的示例中,我从zip读取html文件,并将结果放入字符串中。此字符串将用于使用以下代码将html代码加载到
webview

this.webView.loadDataWithBaseURL("file:///android_asset/", this.unzipStream(sFileName), "text/html", "UTF-8", "");  
我使用了不同的解决方案来加快速度,并发现瓶颈在于从zip读取内容。我增加了读取缓冲区的块大小,但没有帮助,它从不读取完整的块大小。例如,当我使用4096字节(4kb)作为块大小时,它一次只能读取700到1100字节

问题:

  • 如何强制读取函数使用指定的完整块大小
  • 否则,还有其他更好的方法吗(例如,将其直接放入webview)
以下是我编写的代码:

   public String unzipStream( String sFileName ) 
    { 
        final int BLOCKSIZE = 4096;
        //String sResult = ""; 
        long iSize   = 0;
        int iReaded = 0;
        ByteArrayOutputStream sb = new ByteArrayOutputStream(); 

        try  { 
          InputStream is = this.activity.getAssets().open( sFileName );
          BufferedInputStream fin = new BufferedInputStream( is ); 
          ZipInputStream zin = new ZipInputStream(fin); 
          ZipEntry ze;

          while( (iSize == 0) && ((ze = zin.getNextEntry()) != null) && !ze.isDirectory() ) 
          {
               byte data[]  = new byte[BLOCKSIZE];
               long iTotal  = ze.getSize();

               while ((iReaded = zin.read(data,0,BLOCKSIZE)) > 0 && ((iSize+=iReaded) <= iTotal) ) 
               {   
                   sb.write(data,0,iReaded);
               }
               zin.closeEntry(); 
          } 

          zin.close(); 
        } 
        catch(Exception e) 
        { 
             System.out.println("Error unzip: "+e.getMessage());
             //sResult = "";
             iSize = 0;
        } 

        if( iSize > 0 )
        {
            //Base64.
            try {
                return sb.toString("UTF-8");
                //sResult = new String( Base64.decode(sb.toString("UTF-8"), Base64.DEFAULT), Charset.forName("UTF-8") );
            }
            catch(Exception ee)
            {
               //sResult = "";
            }
        }

        return "";
      } 
公共字符串解压流(字符串sFileName)
{ 
最终整数块大小=4096;
//字符串sResult=“”;
long-iSize=0;
int-iReaded=0;
ByteArrayOutputStream sb=新建ByteArrayOutputStream();
试试{
InputStream=this.activity.getAssets().open(sFileName);
BufferedInputStream fin=新的BufferedInputStream(is);
ZipInputStream zin=新的ZipInputStream(fin);
紫丁香;
而((iSize==0)&&((ze=zin.getnextery())!=null)&&&!ze.isDirectory())
{
字节数据[]=新字节[块大小];
long iTotal=ze.getSize();
而((iReaded=zin.read(数据,0,块大小))>0&((iSize+=iReaded)0)
{
//Base64。
试一试{
使某人返回到字符串(“UTF-8”);
//sResult=新字符串(Base64.decode(sb.toString(“UTF-8”)、Base64.DEFAULT)、Charset.forName(“UTF-8”);
}
捕获(异常ee)
{
//sResult=“”;
}
}
返回“”;
} 
也许还有另一种方法:


还找到了此java zipfile类。它使处理(受密码保护)zip文件更容易,但不包括将其解压缩为字符串的函数(至少我认为是这样)。在搜索时找不到任何内容。使用此类是否仍然可以这样做?

尝试设置流的内部缓冲区大小:

    BufferedInputStream fin = new BufferedInputStream(is,  BLOCKSIZE); 
    ZipInputStream zin = new ZipInputStream(fin){ { buf = new byte[BLOCKSIZE]; }  }; 

之后,可能标题可能是“ZipInputStream限制读取性能”或类似内容,因为其他类型的流不限制读取大小。当您想要获得4096字节时,您将获得4096字节。例如,使用文本文件对此进行了测试。我仍然不知道ZipInputStream限制读取性能的原因

我不确定是否有真正的性能提升(有时是,有时不是),但使用apache的“Commons IO”包中的now IOUtils-。这也简化了整个“操作”

我也见过一些使用通道的解决方案,但似乎只适用于文件流,因此无法使用它(或者无法找出如何将其应用于这种情况)。 另见:(见公认答案)

这是我制作的新版本(也将对象名称更改为有意义的名称):


使用而不是loadDataWithBaseUrl可能会提高性能。这不会解决块大小问题,但会允许WebKit在完成整个解压缩之前开始解析内容

您使用它的方式是:

class MyWebViewClient extends WebViewClient {
@Override
public WebResourceResponse shouldInterceptRequest (WebView view, String url) {
    // this method is *not* called on the UI thread, be careful to not touch UI classes.
    if (Uri.parse(url).getHost().equals(Uri.parse("file:///android_asset/..."))) {
        // This assumes you pass in the AssetManager to the MyWebViewClient constructor.
        InputStream is = assetManager.open(sFileName);
        ZipInputStream zipInputStream = new ZipInputStream(is); 
        return new WebResourceResponse("text/html", "UTF-8", zipInputStream);
    }
    return super.shouldInterceptRequest(view, url);
}

您好,谢谢您的回答,但没有加快任何速度。看起来很有趣,我们将很快尝试。另外,请查看marcin.kosiba的解决方案/答案,将两者结合起来。
class MyWebViewClient extends WebViewClient {
@Override
public WebResourceResponse shouldInterceptRequest (WebView view, String url) {
    // this method is *not* called on the UI thread, be careful to not touch UI classes.
    if (Uri.parse(url).getHost().equals(Uri.parse("file:///android_asset/..."))) {
        // This assumes you pass in the AssetManager to the MyWebViewClient constructor.
        InputStream is = assetManager.open(sFileName);
        ZipInputStream zipInputStream = new ZipInputStream(is); 
        return new WebResourceResponse("text/html", "UTF-8", zipInputStream);
    }
    return super.shouldInterceptRequest(view, url);
}