FileOutputStream не удалось с FileNotFoundException, хотя файл, очевидно, существует, доступен для записи и имеет разрешения - PullRequest
4 голосов
/ 02 ноября 2011

Хотя я относительно новичок в Android, у меня есть опыт программирования на Java и C, и в настоящее время я использую Eclipse с обычным набором инструментов для разработки.Я прочитал большинство постов на эту тему и считаю, что я включил / применил все рекомендации и тесты.Ранее я использовал FileOutputStream для записи во внутренние, специфичные для приложения файлы, сборки для L8, без каких-либо проблем.Сейчас я пытаюсь записать файл на SD-карту с помощью Build L7 для Android 2.1.Следующий код взят из одного действия с 3 кнопками (запись, чтение и отправка), которые я использую для проверки основного кода.Хотя все включенные тесты (существуют, доступны для записи и IOException для createNewFile или mkdirs), ведущие к конструктору FileOutputStream (FOS), проходят AOK, конструкция FOS завершается неудачно, вызывая исключение FileNotFoundException, см. Ниже.Я прошел через отладку и подтвердил проблему, см. LogCat внизу.Это выполняется на стандартном эмуляторе Eclipse через ADB с SD-картой, включенной в сборку на 256 КБ.

Из моего метода 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;

>

Файл My Manifest содержит следующую декларацию разрешения использования:

>

<?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 терпит неудачу, хотя всемои тесты, кажется, подтверждают, что это должно работать?

> LogCat: 11-02 15: 40: 54.754: DEBUG / MediaScannerService (154): запустить сканирование тома внешнее 11-02 15: 40: 54.764: VERBOSE / MediaProvider (154): / sdcardID тома: 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: VERBOSE / MediaScanner (154): / pruneDeadThumbnailFiles ...roid и.database.sqlite.SQLiteCursor@44c434f0 11-02 15: 40: 55.925: DEBUG / MediaScanner (154): время предварительного сканирования: 715 мс 11-02 15: 40: 55.955: DEBUG / MediaScanner (154): время сканирования: 4 мс 11-0215: 40: 55.955: DEBUG / MediaScanner (154): время постсканирования: 55мс 11-02 15: 40: 55.955: DEBUG / MediaScanner (154): общее время: 774мс 11-02 15: 40: 55.964: DEBUG / MediaScannerService (154): выполнено сканирование тома внешнего 11-02 15: 44: 50.934: DEBUG / KeyguardViewMediator (52): pokeWakelock (5000) 11-02 15: 44: 51.334:DEBUG / KeyguardViewMediator (52): pokeWakelock (5000) 11-02 15: 44: 51.384: INFO / ActivityManager (52): отображаемая активность org.eddiem.adeveloper.filesendl7 / .FileSendL7Activity: 239793 мс (всего 255760 мс) 11-0215: 44: 51.394: INFO / ARMAssembler (52): сгенерированный scanline__00000077: 03545404_00000A04_00000000 [29 ipp] (51 дюйм) при [0x46ac60: 0x46ad2c] в 757079 нс 11-02 15: 44: 51.414: INFO / ARMAssemble (52)сгенерированная scanline__00000177: 03515104_00001A01_00000000 [73 ipp] (98 дюймов) в [0x46ad30: 0x46aeb8] в 657626 нс 11-02 15: 45: 05.884: DEBUG / FileSendL7Activity (202): полный путь к файлу: /sdcard/testFilet.-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: ERROR / FileSendL7Activity (202): в java.io.FileOutputStream. (FileOutputStream.java:168) 11-02 15: 45: 22.484: ERROR / 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)

>

Спасибо

Ответы [ 2 ]

4 голосов
/ 05 ноября 2011

Из прочитанного можно извлечь несколько уроков.Сначала убедитесь, что Eclipse или другая IDE полностью обновлены и что все пакеты и инструменты загружены правильно.Следующий урок - убедиться, что вы знаете, как работают все инструменты!Смотрите ниже - File_Explorer в DDMS.Самая большая проблема, которая была связана с этими очевидными проблемами кодирования, заключалась в том, что результаты моих экспериментов по кодированию, представленные с помощью инструментов отладки Eclipse, показали мне совершенно другую картину, чем описанная в документации Android.Моя собственная паранойя создала остальные проблемы, и я просто включил во многие версии фрагментов кода и слишком много тестов.

Техническая проблема / ответы следующие:

  1. В Android 2.1 (API-L7) и 2.2 (API-L8) реализована другая структура файлов SDCard.,Таким образом, getExternalStorageDirectory () возвращает / sdcard / для L7 и / mnt / sdcard / для L8.

  2. Документация Android для внешнего хранилища в http://developer.android.com/guide/topics/data/data-storage.html верна;Используйте Environment.getExternalStorageDirectory () для 2.1 (L7) + и используйте только Context.getExternalFilesDir (null) для 2.2 (L8) +

  3. Создание объекта File не создает файл иликаталоги для названных имен.Вы должны использовать mkdirs () и createNewFile (), если вы хотите создать дерево каталогов за пределами корня и файл внутри него.Однако фактический файл создается при успешном открытии FileOutputStream, поэтому часто нет необходимости использовать createNewFile ().Вы ДОЛЖНЫ использовать mkdirs, если хотите создать свои собственные каталоги.

  4. Виртуальные устройства Android, созданные в Eclipse и используемые с эмулятором, на самом деле создают каталоги и файлы, и вы можете увидеть их, используя Вкладка File_Explorer на DDMS во время отладки.ПРИМЕЧАНИЕ. Эти каталоги и файлы являются постоянными и НЕ удаляются автоматически.Используйте инструменты для самостоятельного удаления файлов после запуска или отладки кода.

  5. Наконец, BufferedOutputStream с использованием байтовых массивов является предпочтительным вариантом для небольших файлов и / или множественных записей.FileWrite используется для массивов символов, и во всех случаях вы должны включить в свой Manifest.XML

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

Последнее извинение за многословные вопросы и ответы, но я надеюсь, что многие людичитать и учиться для моей боли.: О)

1 голос
/ 02 ноября 2011

Попробуйте это

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();
}
...