You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android PDF编辑APP报错:open failed: ENOENT (文件或目录不存在)

Android PDF编辑器文件找不到问题修复

问题重现

开发一款可编辑PDF并保存到手机存储的Android应用,选择PDF文件后触发java.io.FileNotFoundException: coa 2.1.pdf: open failed: ENOENT (No such file or directory)错误,无法打开选中的PDF文件。

核心原因

  1. 路径解析完全错误:getPathFromUri方法里,用MediaStore.Images.Media.DISPLAY_NAME拿到的只是文件名,不是完整文件路径;且Uri.getPath()对于content://类型的Uri(多数文件选择器返回的格式)并非真实文件路径,导致后续用FileInputStream找不到文件。
  2. 文件读取方式错误:直接通过文件名创建FileInputStream不适用于content://类型的Uri,必须通过ContentResolver获取输入流。
  3. 输出路径无效:直接用文件名作为输出路径,会默认指向应用私有目录或无权限访问的位置,无法正确保存文件。

修复方案

1. 移除错误的路径解析逻辑,直接使用Uri

不需要再尝试将Uri转为文件路径,直接通过ContentResolver操作Uri即可。

2. 修改文件读取与保存逻辑

  • 使用getContentResolver().openInputStream(uri)获取PDF文件输入流。
  • 将输出文件指定到外部公共存储的可访问目录(比如Download文件夹),确保应用有权限写入。

3. 添加权限配置

在AndroidManifest.xml中添加存储权限(针对不同Android版本做适配):

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:minSdkVersion="30" />

Android 6.0+需要动态申请READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限;Android 11+可选择使用MANAGE_EXTERNAL_STORAGE或通过MediaStore保存文件。

修改后的完整代码

MainActivity.java

package com.example.pdfeditor;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;
import java.io.FileOutputStream;

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_CODE_PICK_PDF = 1;
    private static final int REQUEST_CODE_STORAGE_PERMISSION = 2;
    private Uri selectedPdfUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button pickPdfButton = findViewById(R.id.btn);
        pickPdfButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 先检查存储权限
                if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_STORAGE_PERMISSION);
                } else {
                    openFilePicker();
                }
            }
        });
    }

    private void openFilePicker() {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("application/pdf");
        startActivityForResult(intent, REQUEST_CODE_PICK_PDF);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_STORAGE_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                openFilePicker();
            } else {
                Toast.makeText(this, "需要存储权限才能选择PDF文件", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_PICK_PDF && resultCode == RESULT_OK && data != null) {
            selectedPdfUri = data.getData();
            if (selectedPdfUri != null) {
                editAndSavePdf();
            }
        }
    }

    private void editAndSavePdf() {
        try {
            // 获取PDF输入流
            InputStream inputStream = getContentResolver().openInputStream(selectedPdfUri);

            // 创建输出文件:Download目录下的编辑后PDF
            File downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
            String fileName = "edited_" + System.currentTimeMillis() + ".pdf";
            File outputFile = new File(downloadDir, fileName);
            OutputStream outputStream = new FileOutputStream(outputFile);

            // 创建PDF文档并编辑
            Document document = new Document();
            PdfWriter writer = PdfWriter.getInstance(document, outputStream);

            document.open();
            // 添加自定义文本(这里可以替换为读取原PDF内容并编辑的逻辑)
            Font font = new Font(BaseFont.createFont("assets/fonts/arial.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED), 12);
            Paragraph p = new Paragraph("这是编辑后的PDF内容", font);
            document.add(p);

            document.close();
            writer.close();
            inputStream.close();
            outputStream.close();

            Toast.makeText(this, "PDF已保存至:" + outputFile.getAbsolutePath(), Toast.LENGTH_LONG).show();

        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(this, "错误:" + e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }
}

说明:

  • 新增了权限检查与动态申请逻辑,确保应用能访问存储。
  • 直接使用ContentResolver.openInputStream读取选中的PDF,避免路径解析错误。
  • 输出文件指定到系统Download目录,确保文件可被用户找到且有权限写入。
  • 如果需要编辑原PDF的内容而非新建文档,需要使用iText的PdfReader读取原PDF内容,再通过PdfStamper进行编辑,示例中仅做了新建文档的演示。

错误日志(中文翻译)

W/System.err: java.io.FileNotFoundException: coa 2.1.pdf: 打开失败: ENOENT (没有该文件或目录)
W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:574)
W/System.err:     at java.io.FileInputStream.<init>(FileInputStream.java:160)
W/System.err:     at java.io.FileInputStream.<init>(FileInputStream.java:115)
W/System.err:     at com.example.pdfeditor.MainActivity.openPdfFile(MainActivity.java:76)
W/System.err:     at com.example.pdfeditor.MainActivity.onActivityResult(MainActivity.java:54)
W/System.err:     at android.app.Activity.dispatchActivityResult(Activity.java:8951)
W/System.err:     at android.app.ActivityThread.deliverResults(ActivityThread.java:5987)
W/System.err:     at android.app.ActivityThread.handleSendResult(ActivityThread.java:6033)
W/System.err:     at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:67)
W/System.err:     at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)
W/System.err:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
W/System.err:     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2574)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
W/System.err:     at android.os.Looper.loopOnce(Looper.java:226)
W/System.err:     at android.os.Looper.loop(Looper.java:313)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:8757)
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (没有该文件或目录)
W/System.err:     at libcore.io.Linux.open(Native Method)
W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:563)
W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:274)
W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:563)
W/System.err:     at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8619)
W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:560)
W/System.err:     ... 19 more

内容的提问来源于stack exchange,提问作者THE Anonymous

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 20:07:05