【问题标题】:FileOutputStream failed with FileNotFoundException even though the File apparently, exists, is writeable and has permissionsFileOutputStream 因 FileNotFoundException 而失败,即使 File 显然存在、可写且具有权限
【发布时间】:2011-11-01 23:32:21
【问题描述】:

虽然我对 Android 比较陌生,但我有基于 Java 和 C 的编程经验,我目前正在使用 Eclipse 和常用工具集进行开发。我已经阅读了有关该主题的大部分帖子,并且我相信我已经包含/应用了所有建议和测试。我以前使用 FileOutputStream 写入内部的、特定于应用程序的文件,为 L8 构建,没有任何问题。我现在正在尝试使用 Build L7 for Android 2.1 写入 SD 卡上的文件。以下代码来自我用来测试基本代码的带有 3 个按钮(写入、读取和发送)的单个活动。尽管导致 FileOutputStream (FOS) 构造函数的所有包含测试(存在、可写以及 createNewFile 或 mkdirs 上的 IOException)都通过了 AOK,但 FOS 构造失败,抛出 FileNotFoundException,见下文。我已经调试并确认了问题,请参阅底部的 LogCat。这是通过 ADB 在 Eclipse 标准模拟器上运行的,其中包含 256kB 的构建中的 SD 卡。

来自我的 onw createExternalStorageFile() 方法。

File file = null;
        file = new File(Environment.getExternalStorageDirectory(), mfileName);              
        if(file != null) {
            //file.mkdirs();
            try {
                file.createNewFile();
            } catch (IOException e1) {
                Log.e(TAG, "createNewFile() failed!", e1);
                return false; 
            } 
        }
        if(!file.exists()) {
            Log.d(TAG, "file does not exist!");
        }
        if(!file.canWrite()) {
            Log.d(TAG, "cannot write to file!");
        }
        Log.d(TAG, "full file-path is: " + file.toString());

        FileOutputStream fOS = null;
        try {
            //fOS = new FileOutputStream(file);
            fOS = new FileOutputStream(file.toString());
            // *** THIS THROW THE FILENOTFOUNDEXCEPTION ***
        } catch (FileNotFoundException e1) {
            Log.e(TAG, "fOS-FileNotFoundException", e1);
            return false;
        }
        // fOS IS STILL NULL - HOW CAN THIS BE!
        if(fOS != null) {
            try {
                fOS.write(TESTDATA.getBytes());
                fOS.close();
            } catch (IOException e1) {
                Log.e(TAG, "IOException from fOS-write()!", e1);
                return false;
            }
            Log.d(TAG, "fos-fd is: " + fOS.toString());
        }
        return true;

>

我的清单文件包含如下使用权限声明:

>

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="org.eddiem.adeveloper.externalfilesend"
      android:versionCode="1" android:versionName="1.0">
    <uses-sdk android:minSdkVersion="7" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
        <activity android:name=".ExternalFileSendActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

>

所以这在声明之外,应该可以吗?

任何人都可以帮助解决这个为什么 FileOutputStream 失败的谜题,即使我的所有测试似乎都确认它应该工作?

> 日志猫: 11-02 15:40:54.754: DEBUG/MediaScannerService(154): 开始扫描外部卷 11-02 15:40:54.764:VERBOSE/MediaProvider(154):/sdcard 卷 ID:300427547 11-02 15:40:54.894:INFO/System.out(202):调试器已解决 (1479) 11-02 15:40:55.024:VERBOSE/MediaProvider(154):附加卷:外部 11-02 15:40:55.904: VERBOSE/MediaScanner(154): pruneDeadThumbnailFiles... android.database.sqlite.SQLiteCursor@44c434f0 11-02 15:40:55.915:详细/MediaScanner(154):/pruneDeadThumbnailFiles... android.database.sqlite.SQLiteCursor@44c434f0 11-02 15:40:55.925:调试/MediaScanner(154):预扫描时间:715 毫秒 11-02 15:40:55.955:调试/MediaScanner(154):扫描时间:4 毫秒 11-02 15:40:55.955:调试/MediaScanner(154):扫描后时间:55 毫秒 11-02 15:40:55.955: DEBUG/MediaScanner(154): 总时间: 774ms 11-02 15:40:55.964: DEBUG/MediaScannerService(154): 完成外部扫描卷 11-02 15:44:50.934:调试/KeyguardViewMediator(52):pokeWakelock(5000) 11-02 15:44:51.334:调试/KeyguardViewMediator(52):pokeWakelock(5000) 11-02 15:44:51.384:INFO/ActivityManager(52):显示的活动 org.eddiem.adeveloper.filesendl7/.FileSendL7Activity:239793 毫秒(总共 255760 毫秒) 11-02 15:44:51.394: INFO/ARMAssembler(52): 生成扫描线__00000077:03545404_00000A04_00000000 [29 ipp] (51 ins) at [0x46ac60:0x46ad2c] in 757079 ns 11-02 15:44:51.414: INFO/ARMAssembler(52): 生成扫描线__00000177:03515104_00001A01_00000000 [73 ipp] (98 ins) at [0x46ad30:0x46aeb8] in 657626 ns 11-02 15:45:05.884:调试/FileSendL7Activity(202):完整文件路径为:/sdcard/testFile.txt 11-02 15:45:22.484: 错误/FileSendL7Activity(202): fOS-FileNotFoundException 11-02 15:45:22.484: 错误/FileSendL7Activity(202): java.io.FileNotFoundException: /sdcard/testFile.txt 11-02 15:45:22.484: 错误/FileSendL7Activity(202): 在 org.apache.harmony.luni.platform.OSFileSystem.open(OSFileSystem.java:244) 11-02 15:45:22.484: 错误/FileSendL7Activity(202): 在 java.io.FileOutputStream.(FileOutputStream.java:97) 11-02 15:45:22.484: 错误/FileSendL7Activity(202): 在 java.io.FileOutputStream.(FileOutputStream.java:168) 11-02 15:45:22.484: 错误/FileSendL7Activity(202): 在 java.io.FileOutputStream.(FileOutputStream.java:147) 11-02 15:45:22.484: 错误/FileSendL7Activity(202): 在 org.eddiem.adeveloper.filesendl7.FileSendL7Activity.creatExternalStorageFileOS(FileSendL7Activity.java:149) 11-02 15:45:22.484: 错误/FileSendL7Activity(202): 在 org.eddiem.adeveloper.filesendl7.FileSendL7Activity.access$0(FileSendL7Activity.java:124) 11-02 15:45:22.484: 错误/FileSendL7Activity(202): 在 org.eddiem.adeveloper.filesendl7.FileSendL7Activity$1.onClick(FileSendL7Activity.java:176) 11-02 15:45:22.484: 错误/FileSendL7Activity(202): 在 android.view.View.performClick(View.java:2364)

>

谢谢

【问题讨论】:

  • 你在什么设备上测试?
  • 导致异常的行是什么?你能指点我们吗?
  • 抱歉遗漏。我正在 Eclipse 的模拟器上对此进行测试,构建版本是 Android 2.1,API 级别 7。失败的行是:fOS = new FileOutputStream(file);
  • 我也尝试使用 BufferedWrite 而不是 FileOutputStream,但仍然遇到同样的问题 (FIlENOTFOUND)。尽管使用了 DDMS FileExplore 工具中列出的我的测试文件,但还是会这样做。我也试过在我的手机上运行这个测试应用程序,运行 Android_2.3.3,但没有成功。我开始认为 Eclipse 中的构建有问题。任何更多的想法将不胜感激。

标签: android android-sdcard filenotfoundexception fileoutputstream


【解决方案1】:

从阅读本文中可以学到很多经验。 首先确保您的 Eclipse 或其他 IDE 已完全更新,并且所有包和工具都已正确加载。下一课是确保您了解所有工具的工作原理!见下文 - DDMS 中的 File_Explorer。 与这些明显的编码问题相关的最大单一问题是,我的编码实验结果(通过 Eclipse 调试工具提供)向我展示了与 Android 文档中描述的完全不同的画面。其余的问题是我自己的偏执狂造成的,我只是简单地将许多版本的代码 sn-ps 和太多的测试包含在内。

技术问题/答案如下:

  1. Android 2.1(API-L7) 和 2.2(API-L8) 实现了不同的 sdcard 文件结构。所以 getExternalStorageDirectory() 返回 /sdcard/ for L7 和 /mnt/sdcard/ 用于 L8。

  2. http://developer.android.com/guide/topics/data/data-storage.html 上的外部存储的 Android 文档是 正确的;将 Environment.getExternalStorageDirectory() 用于 2.1(L7)+ 并且仅将 Context.getExternalFilesDir(null) 用于 2.2(L8)+

  3. 构造文件对象不会为提供的名称创建文件或目录。您必须使用 mkdirs() 和 createNewFile() 如果你想实际创建一个目录树 超出根目录和其中的文件。但是,实际文件是 当您成功打开 FileOutputStream 时创建,所以有 通常不需要使用 createNewFile()。你必须使用 mkdirs 是你想要的 创建自己的目录。

  4. 在 Eclipse 中创建并与模拟器一起使用的 Android 虚拟设备实际上会创建目录和文件,您可以看到 这些在调试期间使用 DDMS 上的 File_Explorer 选项卡。笔记: 这些目录和文件是持久的而不是自动的 删除。运行后使用工具自行删除文件 或调试您的代码。

  5. 最后,使用字节数组的 BufferedOutputStream 是小文件和/或多次写入的首选选项。 FileWrite 用于 char 数组,在所有情况下都必须包含在 清单.XML

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

最后为冗长的问答道歉,但我希望有很多人阅读和学习我的痛苦。 :o)

【讨论】:

    【解决方案2】:

    试试这个

    if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Log.e("TEST", "this is bad");
    }
    
    File file = new File(getExternalFilesDir(null), "test.csv");
    
    try {
        FileOutputStream fos = new FileOutputStream(file);
    fos.write(...);
    fos.close();
    } catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    

    【讨论】:

    • 这个例子对我有用。但是,我只是尝试添加 file.createNewfile();就在创建 FileOutputStream 之前,然后我遇到了同样的错误。
    • 虽然 getExternalFilesDir() 方法出现在developer.android.com/reference/android/content/Context.html ..Eclipse 声称这在 7 级构建的上下文中没有定义。所以我对我的设置更加困惑。
    猜你喜欢
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    • 1970-01-01
    • 2019-03-08
    • 1970-01-01
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    相关资源
    最近更新 更多