java - 带有文本文件的不完整 Java 文件输出流

标签 java encryption fileoutputstream zipoutputstream

我正在编写一个小工具来加密和解密文件。加密的文件将添加到 zip 存档中。到目前为止,以下代码正在运行。我可以加密除文本文件之外的任何文件。如果我选择一个文本文件,它会被写入不完整。如果有如下文字: “一二三测试检查检查测试”它像“一二三测试检查”一样被剪切。

没有抛出异常,只是丢失了几个字节。任何其他文件(pdf、mp3、mp4、exe 等)均已完整写入。

package encryptme.crypto;

import encryptme.fileoperations.FileIn;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;

public class Encrypt {

    private String algorithm;
    private int keylength;
    private Key key;
    private KeyPair keypair;
    private File[] source;
    private String destination;

    public Encrypt(String a, int kl, Key k, File[] s, String dest) {
        this.algorithm = a;
        this.keylength = kl;
        this.key = k;
        this.source = s;
        this.destination = dest;
        this.output = o;
    }

    public void encOut() {
        CipherOutputStream cout = null;
        ZipOutputStream zout = null;
        OutputStream out = null;
        Cipher cipher;
        try {
            out = new FileOutputStream(this.destination);
            System.out.println(this.destination);
            zout = new ZipOutputStream(out);
            cipher = Cipher.getInstance(this.algorithm);
            cipher.init(Cipher.ENCRYPT_MODE, this.key);
            for (int i = 0; i < this.source.length; i++) {
                FileInputStream in = new FileInputStream(this.source[i].getAbsolutePath());
                ZipEntry ze = new ZipEntry(this.source[i].getName());                 
                zout.putNextEntry(ze);
                cout = new CipherOutputStream(zout, cipher);
                byte[] buffer = new byte[1024];
                long bytesRead = 0;
                for (bytesRead = 0; (bytesRead = in.read(buffer)) != -1;) {
                    cout.write(buffer, 0, (int) bytesRead);
                }
                zout.closeEntry();
                in.close();
            }
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(Encrypt.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchPaddingException ex) {
            Logger.getLogger(Encrypt.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidKeyException ex) {
            Logger.getLogger(Encrypt.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Encrypt.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Encrypt.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                if (cout != null) {
                    cout.close();
                }
                if (zout != null) {
                    zout.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException ex) {
                Logger.getLogger(Encrypt.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

使用 jFileChooser 选择要加密的文件,并将其添加到一个数组中,该数组作为参数传递给上面的类。我考虑过使用 PrintWriter 来处理那些通过结尾来识别它们的文本文件,例如“textfile.txt”或“textfile.odt”。但是如果文件没有像“textfile”那样的结尾我该怎么办?

我对 Java 和编码都很陌生,所以我希望只是一个严重的错误导致了这个问题。

最佳答案

您需要在调用 zout.closeEntry 之前关闭 cout,以便清除密码缓冲的所有剩余数据。不幸的是,cout.close() 将调用 zout.close(),我们绝对不希望这样做,因为这会阻止您编写任何进一步的条目。

我会使用CloseShieldOutputStream from commons-io :

cout = new CipherOutputStream(new CloseShieldOutputStream(zout), cipher);

此类旨在阻止 close() 调用传播到底层包装流(在本例中为 zout)。

关于java - 带有文本文件的不完整 Java 文件输出流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20291976/

相关文章:

java - Scala 在编译器镜像中返回 "error while loading package, Missing dependency ' 对象 java.lang.Object'"

c++ - 使用 C++ 进行异或加密

java - 写入文件的问题

java HashMap 键与低吞吐量的比较

java - 是否可以用 JSR-330 @Scope 变体替换 Spring @Scope ("request")?

c++ - 在 C++ 中使用 OpenSSL 使用 AES128 加密字符串时出错

java - DSA 问题 - 使用 .NET 创建 DSA 公钥/私钥,通过 Java(android) 使用公钥

Android FileOutputStream 在 api 级别 22 中返回 FileNotFoundException

android - 将数据库从 Assets 复制到设备数据文件夹时出现 FileNotFoundException

java - Lombok 承认 setter/getter ,但编译失败