代码之家  ›  专栏  ›  技术社区  ›  Franckyi

Java-解压和进度条

  •  2
  • Franckyi  · 技术社区  · 9 年前

    我的程序使用JavaFX中的任务下载和解压文件,并在屏幕上显示进度,方法是使用 updateProgress(workDone, max) 方法和 progressProperty().bind(observable) 方法 它适用于下载:

    package com.franckyi.lan.installer;
    
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.URL;
    import java.net.URLConnection;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    
    import javafx.concurrent.Task;
    
    public class DownloadTask extends Task<Void> {
    
        private String file;
        private String url;
    
        public DownloadTask(String dir, String fileurl) {
            file = dir;
            url = fileurl;
        }
    
        @Override
        protected Void call() throws Exception {
            URLConnection connection = new URL(url).openConnection();
            long fileLength = connection.getContentLengthLong();
    
            try (InputStream is = connection.getInputStream();
                    OutputStream os = Files.newOutputStream(Paths.get(file))) {
    
                long nread = 0L;
                byte[] buf = new byte[1024];
                int n;
                while ((n = is.read(buf)) > 0) {
                    os.write(buf, 0, n);
                    nread += n;
                    updateProgress(nread, fileLength);
                }
            }
            return null;
        }
    
        @Override
        protected void succeeded(){
            System.out.println("Download succeeded");
        }
    
    }
    

    但解压时效果不好:文件被正确解压,但我得到了一个错误的进度条(最后是空的)。

    package com.franckyi.lan.installer;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipInputStream;
    
    import javafx.concurrent.Task;
    
    public class UnZipTask extends Task<Void>{
    
        private File zipfile;
        private File folder;
    
        public UnZipTask(File zipfile, File folder){
            this.zipfile = zipfile;
            this.folder = folder;
        }
    
        @Override
        protected Void call() throws Exception {
            ZipInputStream zis = new ZipInputStream(
                new BufferedInputStream(new FileInputStream(zipfile.getCanonicalFile())));
            ZipEntry ze = null;
            try {
                while ((ze = zis.getNextEntry()) != null) {
                     File f = new File(folder.getCanonicalPath(), ze.getName());
                    if (ze.isDirectory()) {
                        f.mkdirs();
                        continue;
                    }
                    f.getParentFile().mkdirs();
                    OutputStream fos = new BufferedOutputStream(new FileOutputStream(f));
                    try {
                        try {
                            final byte[] buf = new byte[1024];
                            int bytesRead;
                            long nread = 0L;
                            long length = zipfile.length();
    
                            while (-1 != (bytesRead = zis.read(buf))){
                                fos.write(buf, 0, bytesRead);
                                nread += bytesRead;
                                System.out.println(nread + "/" + length);
                                updateProgress(nread, length);
                            }
                        } finally {
                            fos.close();
                        }
                    } catch (final IOException ioe) {
                        f.delete();
                        throw ioe;
                    }
                }
            } finally {
                zis.close();
            }
            return null;
        }
    
        @Override
        protected void succeeded(){
            System.out.println("Unzip succeeded");
        }
    
    }
    

    这是我在控制台中得到的:

    Download succeeded
    1024/91804
    2048/91804
    2815/91804
    362/91804
    326/91804
    290/91804
    386/91804
    257/91804
    250/91804
    588/91804
    1101/91804
    1613/91804
    2128/91804
    2646/91804
    3159/91804
    3672/91804
    4185/91804
    4701/91804
    5214/91804
    5731/91804
    6243/91804
    6755/91804
    7272/91804
    7793/91804
    8326/91804
    8862/91804
    9379/91804
    9897/91804
    10411/91804
    10927/91804
    11442/91804
    11956/91804
    12437/91804
    447/91804
    437/91804
    978/91804
    1525/91804
    2040/91804
    454/91804
    1056/91804
    1568/91804
    2089/91804
    2672/91804
    3198/91804
    3728/91804
    4282/91804
    4826/91804
    5377/91804
    5891/91804
    6413/91804
    6941/91804
    7480/91804
    8027/91804
    8565/91804
    9088/91804
    9609/91804
    9794/91804
    507/91804
    1019/91804
    1531/91804
    2043/91804
    2239/91804
    134/91804
    548/91804
    1292/91804
    2316/91804
    2584/91804
    507/91804
    837/91804
    135/91804
    486/91804
    1001/91804
    1514/91804
    2027/91804
    2545/91804
    3057/91804
    3571/91804
    4086/91804
    4599/91804
    5113/91804
    5627/91804
    6144/91804
    6655/91804
    7166/91804
    7679/91804
    8196/91804
    8710/91804
    9229/91804
    9745/91804
    10259/91804
    10773/91804
    11288/91804
    11802/91804
    12321/91804
    12834/91804
    13348/91804
    13864/91804
    14378/91804
    14893/91804
    15407/91804
    15918/91804
    16431/91804
    16944/91804
    17458/91804
    17971/91804
    18484/91804
    18997/91804
    19508/91804
    20021/91804
    20535/91804
    21047/91804
    21560/91804
    22072/91804
    22584/91804
    23096/91804
    23609/91804
    24122/91804
    24638/91804
    25149/91804
    25664/91804
    26176/91804
    26689/91804
    27203/91804
    27715/91804
    28227/91804
    28739/91804
    29251/91804
    29764/91804
    30277/91804
    30789/91804
    31301/91804
    31813/91804
    32325/91804
    32838/91804
    33306/91804
    33819/91804
    34333/91804
    34846/91804
    35357/91804
    35869/91804
    36381/91804
    36894/91804
    37407/91804
    37922/91804
    38435/91804
    38948/91804
    39460/91804
    39972/91804
    40488/91804
    41002/91804
    41514/91804
    42028/91804
    42540/91804
    43052/91804
    43566/91804
    44079/91804
    44594/91804
    45105/91804
    45619/91804
    46132/91804
    46644/91804
    47156/91804
    47668/91804
    48180/91804
    48692/91804
    49204/91804
    49716/91804
    50228/91804
    50741/91804
    51252/91804
    51765/91804
    52277/91804
    52790/91804
    53305/91804
    53821/91804
    54335/91804
    54852/91804
    55365/91804
    55881/91804
    56396/91804
    56442/91804
    545/91804
    1287/91804
    2311/91804
    2584/91804
    507/91804
    845/91804
    4/91804
    Unzip succeeded
    

    有人能帮我吗?

    1 回复  |  直到 9 年前
        1
  •  5
  •   Krzysztof Cichocki    9 年前

    这是因为您使用压缩zipFile的长度作为最大值,并使用每个未压缩zipEntry的字节数作为位置-压缩文件的大小在大多数情况下与未压缩文件不同,此外,您可以在zip包中有多个文件,因此在这种情况下,progres将从0跳到每个文件的某个值(实际zipEntry的大小,而不是压缩的zipFile长度)。要获得zip文件中的实际位置,请获取 FileChannel FileInputStream ,使用此方法: FileInputStream#getChannel();

    然后,当需要更新progres时,请执行以下操作:

     updateProgress(channel.position(), length);
    

    package com.franckyi.lan.installer;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipInputStream;
    
    import javafx.concurrent.Task;
    
    public class UnZipTask extends Task<Void>{
    
        private File zipfile;
        private File folder;
    
        public UnZipTask(File zipfile, File folder){
            this.zipfile = zipfile;
            this.folder = folder;
        }
    
        @Override
        protected Void call() throws Exception {
            FileInputStream is = new FileInputStream(zipfile.getCanonicalFile());
            FileChannel channel = is.getChannel();
            ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is));
            ZipEntry ze = null;
            try {
                while ((ze = zis.getNextEntry()) != null) {
                     File f = new File(folder.getCanonicalPath(), ze.getName());
                    if (ze.isDirectory()) {
                        f.mkdirs();
                        continue;
                    }
                    f.getParentFile().mkdirs();
                    OutputStream fos = new BufferedOutputStream(new FileOutputStream(f));
                    try {
                        try {
                            final byte[] buf = new byte[1024];
                            int bytesRead;
                            long nread = 0L;
                            long length = zipfile.length();
    
                            while (-1 != (bytesRead = zis.read(buf))){
                                fos.write(buf, 0, bytesRead);
                                nread += bytesRead;
                                System.out.println(nread + "/" + length);
                                updateProgress(channel.position(), length);
                            }
                        } finally {
                            fos.close();
                        }
                    } catch (final IOException ioe) {
                        f.delete();
                        throw ioe;
                    }
                }
            } finally {
                zis.close();
            }
            return null;
        }
    
        @Override
        protected void succeeded(){
            System.out.println("Unzip succeeded");
        }
    
    }