繁体   English   中英

Android java.io.IOException:写入失败:EBADF(错误的文件号)

[英]Android java.io.IOException: write failed: EBADF (Bad file number)

我已经阅读了几篇有关EBADF错误的文章,但并不能解决我的问题。 使我的案子与众不同的原因是,我尝试写入getFilesDir,该文件应可由应用程序写入。

执行加密方法时,出现EBADF错误。 file参数是使用以下命令创建的:

new File(mContext.getFilesDir(), "file.dat")

加密方法清单在哪里:

public static void encrypt(File file, String password, List<Object> objects) {

    byte[] salt = generateSalt();
    byte[] iv = generateIV();
    Cipher c = createCipher(password, salt, Cipher.ENCRYPT_MODE, iv);

    try (FileOutputStream fos = new FileOutputStream(file)) {
        fos.write(salt);
        fos.write(iv);
        try (CipherOutputStream cos = new CipherOutputStream(fos, c);
        ObjectOutputStream oos = new ObjectOutputStream(cos)) {
            for (Object o : objects) {
                oos.writeObject(o);
            }
        }

    } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

谁能看到我为什么得到例外?

这是异常日志:

 Caused by: java.lang.RuntimeException: java.io.IOException: write failed: EBADF (Bad file number)
    at za.co.lot24media.password.util.EncryptUtil.encrypt(EncryptUtil.java:69)
    at za.co.lot24media.password.store.Store.save(Store.java:94)
    at za.co.lot24media.password.store.Store.createSamples(Store.java:179)
    at za.co.lot24media.password.store.Store.load(Store.java:76)
    at za.co.lot24media.password.activity.login.LoginAction$2.doInBackground(LoginAction.java:62)
    at za.co.lot24media.password.activity.login.LoginAction$2.doInBackground(LoginAction.java:55)
    at android.os.AsyncTask$2.call(AsyncTask.java:292)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
    at java.lang.Thread.run(Thread.java:818) 
 Caused by: java.io.IOException: write failed: EBADF (Bad file number)
    at libcore.io.IoBridge.write(IoBridge.java:502)
    at java.io.FileOutputStream.write(FileOutputStream.java:186)
    at java.io.OutputStream.write(OutputStream.java:82)
    at javax.crypto.CipherOutputStream.close(CipherOutputStream.java:129)
    at za.co.lot24media.password.util.EncryptUtil.encrypt(EncryptUtil.java:64)

**编辑**

问题似乎出在ObjectOutputStream写入CipherOutputStream上。 当我从crypto()方法中删除ObjectOutputStream时,该方法成功。 以下代码有效:

    public static void encrypt(File file, String password, StoreDataRecord storeDataRecord) {

    byte[] salt = generateSalt();
    byte[] iv = generateIV();
    Cipher c = createCipher(password, salt, Cipher.ENCRYPT_MODE, iv);

    try (FileOutputStream fos = new FileOutputStream(file)) {
        fos.write(salt);
        fos.write(iv);

        try (CipherOutputStream cos = new CipherOutputStream(fos, c)) {
            cos.write(new byte[10]);
        }

    } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

我使用byte [10]只是将任意数据写入流。

**编辑2 **

以下解决方案也有效,首先将数据写入ByteArrayOutputStream:

public static void encrypt(File file, String password, StoreDataRecord storeDataRecord) {

    byte[] salt = generateSalt();
    byte[] iv = generateIV();
    Cipher c = createCipher(password, salt, Cipher.ENCRYPT_MODE, iv);

    try (FileOutputStream fos = new FileOutputStream(file)) {
        fos.write(salt);
        fos.write(iv);

        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(bos);
             CipherOutputStream cos = new CipherOutputStream(fos, c)) {
            oos.writeObject(storeDataRecord.getVersion());
            oos.writeObject(storeDataRecord.getItems());
            cos.write(bos.toByteArray());
        }
    } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

正如我在doInBackground上看到您的encrypt方法调用doInBackground ,它可能会产生一些复杂的情况,例如移至另一个片段或创建两个片段实例,这使android感到困惑。 最好的方法是在调用onDestroy()时忽略encrypt方法。

并确保在使用流之前未关闭它们。

希望对您有所帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM