Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/178.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 跟踪复制文件的进度_Android_Compression_Progress - Fatal编程技术网

Android 跟踪复制文件的进度

Android 跟踪复制文件的进度,android,compression,progress,Android,Compression,Progress,我正在尝试跟踪压缩进度的进度。我是这样做的: public static void compressGzipTest(final OutputStream os, final File source) throws CompressorException, IOException { final CountingInputStream cis = new CountingInputStream(new FileInputStream(source)

我正在尝试跟踪压缩进度的进度。我是这样做的:

public static void compressGzipTest(final OutputStream os, final File source) throws CompressorException,
            IOException
    {
        final CountingInputStream cis = new CountingInputStream(new FileInputStream(source));
        final GzipCompressorOutputStream gzipOut = (GzipCompressorOutputStream) new CompressorStreamFactory()
                .createCompressorOutputStream(CompressorStreamFactory.GZIP,os);

        new Thread() {
            public void run()
            {
                try
                {
                    long fileSize = source.length();

                    while (fileSize > cis.getBytesRead())
                    {
                        Thread.sleep(1000);
                        System.out.println(cis.getBytesRead() / (fileSize / 100.0));
                    }
                }
                catch (Exception ex)
                {
                    ex.printStackTrace();
                }
            }
        }.start();

        IOUtils.copy(cis,gzipOut);
    }
while (-1 != (n = input.read(buffer)))
    {
        output.write(buffer,0,n);
        count += n;
        while(n % 2097152 == 0)
        {
          listener.onProgress(n);
        }
    }
    return count;
File ungzippedFile = Util.unGzip(movedFile, offlineDataDirFile, new ProgressListener() {
    @Override
    public void onProgressUpdate(int percentage) {
        notificationBuilder.setProgress(100, percentage, false);
        notificationManagerCompat.notify(1, notificationBuilder.build());
    }
});

这很好,但我需要一个线程,它提供关于进度的反馈,而不是在这个方法中实现,而是在调用它时(为了在android设备上创建类似progressbar的东西)。所以这更像是一个架构问题。关于如何解决这个问题,您有什么想法吗?

您应该在AsyncTask中实现复制机制。 它在后台线程上运行,但您可以使用publishProgress方法发布进度。 之后,您可以使用AsyncTask的onProgressUpdate回调在UI线程上处理这些事件

编辑: 例如:


同时,我通过添加一个接口作为参数覆盖IOUtils.copy()解决了这个问题:

public static long copy(final InputStream input, final OutputStream output, int buffersize,
        ProgressListener listener) throws IOException
{
    final byte[] buffer = new byte[buffersize];
    int n = 0;
    long count = 0;
    while (-1 != (n = input.read(buffer)))
    {
        output.write(buffer,0,n);
        count += n;
        listener.onProgress(n);
    }
    return count;
}
这就是我们所说的

copy(input, output, 4096, new ProgressListener() {

                long totalCounter = 0;

                DecimalFormat f = new DecimalFormat("#0.00");

                @Override
                public void onProgress(long bytesRead)
                {
                    totalCounter += bytesRead;
                    System.out.println(f.format(totalCounter / (fileSize / 100.0)));
                }
            });
我现在面临的唯一挑战是,限制控制台上的输出不是每个字节[4096],而是每两兆字节。我试过这样的方法:

public static void compressGzipTest(final OutputStream os, final File source) throws CompressorException,
            IOException
    {
        final CountingInputStream cis = new CountingInputStream(new FileInputStream(source));
        final GzipCompressorOutputStream gzipOut = (GzipCompressorOutputStream) new CompressorStreamFactory()
                .createCompressorOutputStream(CompressorStreamFactory.GZIP,os);

        new Thread() {
            public void run()
            {
                try
                {
                    long fileSize = source.length();

                    while (fileSize > cis.getBytesRead())
                    {
                        Thread.sleep(1000);
                        System.out.println(cis.getBytesRead() / (fileSize / 100.0));
                    }
                }
                catch (Exception ex)
                {
                    ex.printStackTrace();
                }
            }
        }.start();

        IOUtils.copy(cis,gzipOut);
    }
while (-1 != (n = input.read(buffer)))
    {
        output.write(buffer,0,n);
        count += n;
        while(n % 2097152 == 0)
        {
          listener.onProgress(n);
        }
    }
    return count;
File ungzippedFile = Util.unGzip(movedFile, offlineDataDirFile, new ProgressListener() {
    @Override
    public void onProgressUpdate(int percentage) {
        notificationBuilder.setProgress(100, percentage, false);
        notificationManagerCompat.notify(1, notificationBuilder.build());
    }
});

但这根本没有给我任何输出

我有一个与作者提出的解决方案非常相似的解决方案。我采用了
IOUtils
中的
copy
方法,并添加了两个参数:要复制的文件的原始文件大小和用于更新进度的侦听器。我的复制发生在解包
.gz
文件的过程中,由于解包的文件大约比打包的文件大3倍,我估计最终结果文件的大小(因此行
复制(in,out,inputFile.length()*3,progressListener);
)。整个过程都是基于Android的,因此侦听器会根据进度更新通知

public static File unGzip(final File inputFile, final File outputDir, ProgressListener progressListener)
        throws FileNotFoundException, IOException {
    final File outputFile = new File(outputDir, inputFile.getName()
            .substring(0, inputFile.getName().length() - 3));
    final GZIPInputStream in = new GZIPInputStream(new FileInputStream(inputFile));
    final FileOutputStream out = new FileOutputStream(outputFile);
    copy(in, out, inputFile.length()*3, progressListener);
    in.close();
    out.close();
    return outputFile;
}

public static long copy(InputStream input, OutputStream output, long inputfilesize,
                        ProgressListener progressListener)
        throws IOException {
    byte[] buffer = new byte[8024];
    boolean n = false;
    long percent = 0;
    long count;
    int n1;
    for(count = 0L; -1 != (n1 = input.read(buffer)); count += (long)n1) {
        output.write(buffer, 0, n1);
        if ((count*100)/inputfilesize > percent) {
            percent = (count*100)/inputfilesize;
            progressListener.onProgressUpdate((int)percent);
        }
    }
    return count;
}
调用所有这些的类的代码如下所示:

public static void compressGzipTest(final OutputStream os, final File source) throws CompressorException,
            IOException
    {
        final CountingInputStream cis = new CountingInputStream(new FileInputStream(source));
        final GzipCompressorOutputStream gzipOut = (GzipCompressorOutputStream) new CompressorStreamFactory()
                .createCompressorOutputStream(CompressorStreamFactory.GZIP,os);

        new Thread() {
            public void run()
            {
                try
                {
                    long fileSize = source.length();

                    while (fileSize > cis.getBytesRead())
                    {
                        Thread.sleep(1000);
                        System.out.println(cis.getBytesRead() / (fileSize / 100.0));
                    }
                }
                catch (Exception ex)
                {
                    ex.printStackTrace();
                }
            }
        }.start();

        IOUtils.copy(cis,gzipOut);
    }
while (-1 != (n = input.read(buffer)))
    {
        output.write(buffer,0,n);
        count += n;
        while(n % 2097152 == 0)
        {
          listener.onProgress(n);
        }
    }
    return count;
File ungzippedFile = Util.unGzip(movedFile, offlineDataDirFile, new ProgressListener() {
    @Override
    public void onProgressUpdate(int percentage) {
        notificationBuilder.setProgress(100, percentage, false);
        notificationManagerCompat.notify(1, notificationBuilder.build());
    }
});
此类还包含以下接口:

public interface ProgressListener {
    void onProgressUpdate(int percentage);
}

我通过将InputStream作为一个参数传递,暂时解决了这个问题。但是我说得对吗,PublishProgressUpdate/onProgressUpdate默认情况下会处理我方法的进度,还是我仍然需要实现如何接收进度反馈?请查看我编辑的答案,在那里你可以看到一个关于它的示例。