Ошибка записи файла в getFilesDir() - NoSuchElementException

вот что я делаю:

1- Получение файла из моих ассетов и помещение его в строку - УСПЕШНО

2- Сделать файл в getFilesDir() - НЕУДАЧА (еще нет сбоя)

3- Запишите строку, которую я получил в этот файл, используя FileWriter - НЕУДАЧА (еще нет сбоя)

4- Прочитайте новый файл, который я только что сделал - НЕУДАЧА (выдает NoSuchElementException)

Вот то, что вы должны увидеть:

Небольшой полезный метод, который я использовал:

public String inputStreamToString(InputStream stream){

        Scanner s = new Scanner(stream).useDelimiter("\\A");
        String aa = s.next();
        return aa;

    }

Фрагмент MainActivity.java:

//B2 and text are a well defined Button and TextView respectively, ensured through previous testings
B2.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                AssetManager as = getAssets();
                InputStream stream = null;
                try {
                    stream = as.open("updater-script");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                Scanner s = new Scanner(stream).useDelimiter("\\A");
                String aa = s.next();
                text.setText(aa);

                File file = new File(getFilesDir() + "/updater-script");
                try {
                    boolean b = file.createNewFile(); //returns false, indicating the file wasn't made
                    text.setText(text.getText()+String.valueOf(b));
                    new File(getFilesDir().getAbsolutePath()).mkdirs();
                    FileWriter write = new FileWriter(getFilesDir().toString()+File.pathSeparator+"updater-script");
                    Show(getFilesDir().toString());
                    write.write(aa);
                    write.close();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                }
        });
        B2.setOnLongClickListener(new View.OnLongClickListener() {

            @Override
            public boolean onLongClick(View v) {
                File file = new File(getFilesDir(), "updater-script");
                try {
                    FileInputStream in = new FileInputStream(file);
                    String aa = inputStreamToString(in);
                    text.setText(aa);
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }


                return true;
            }
        });

Мой манифест:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="seaskyways.testingproject"
    android:versionCode="1"
    android:versionName="beta" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="17" />

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STROAGE"/>
    <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.Sherlock" >
        <activity
            android:name="seaskyways.testingproject.MainActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Holo"
            android:uiOptions="splitActionBarWhenNarrow" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="seaskyways.testingproject.MenuActivity"
            android:label="@string/title_activity_menu" >
        </activity>
        <activity
            android:name="seaskyways.testingproject.Splash"
            android:label="@string/title_activity_splash"
            android:theme="@style/Theme.Sherlock.Dialog" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <activity
            android:name="seaskyways.testingproject.HorizontalScrollView"
            android:label="@string/title_activity_splash" >
            <intent-filter>
                <action android:name="android.intent.action.HSV" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <activity
            android:name="seaskyways.testingproject.ExpandableLists"
            android:label="@string/title_activity_expandable_lists"
            android:parentActivityName="seaskyways.testingproject.MainActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="seaskyways.testingproject.MainActivity" />
        </activity>
        <activity
            android:name="seaskyways.testingproject.SwipeStrips"
            android:label="@string/title_activity_swipe_tabs"
            android:parentActivityName="seaskyways.testingproject.MainActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="seaskyways.testingproject.MainActivity" />
        </activity>
        <activity
            android:name="seaskyways.testingproject.SwipeTabs"
            android:label="@string/title_activity_swipe_tabs"
            android:parentActivityName="seaskyways.testingproject.MainActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="seaskyways.testingproject.MainActivity" />
        </activity>
    </application>

</manifest>

Трассировки стека :

03-11 21:23:08.241: E/AndroidRuntime(3958): FATAL EXCEPTION: main
03-11 21:23:08.241: E/AndroidRuntime(3958): java.util.NoSuchElementException
03-11 21:23:08.241: E/AndroidRuntime(3958):     at java.util.Scanner.next(Scanner.java:1007)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at java.util.Scanner.next(Scanner.java:980)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at seaskyways.testingproject.MainActivity.inputStreamToString(MainActivity.java:44)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at seaskyways.testingproject.MainActivity$7.onLongClick(MainActivity.java:171)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at android.view.View.performLongClick(View.java:4240)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at android.widget.TextView.performLongClick(TextView.java:8060)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at android.view.View$CheckForLongPress.run(View.java:17339)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at android.os.Handler.handleCallback(Handler.java:725)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at android.os.Handler.dispatchMessage(Handler.java:92)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at android.os.Looper.loop(Looper.java:137)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at android.app.ActivityThread.main(ActivityThread.java:5237)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at java.lang.reflect.Method.invokeNative(Native Method)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at java.lang.reflect.Method.invoke(Method.java:511)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:799)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
03-11 21:23:08.241: E/AndroidRuntime(3958):     at dalvik.system.NativeStart.main(Native Method)

Пожалуйста , никаких обходных путей , потому что у меня есть планы на будущее ... Спасибо за любую помощь ! Если вам нужна дополнительная информация, я здесь, а поле для комментариев находится на несколько сантиметров ниже: P


person Seaskyways    schedule 11.03.2013    source источник
comment
Ваш logcat на самом деле предполагает, что ваша ошибка находится в s.next();   -  person DigCamara    schedule 11.03.2013
comment
логическое значение b = file.createNewFile(); //возвращает false, указывая на то, что файл не был создан. Прочтите документацию для createNewFile() developer.android.com/reference/java/io/ Если файл не может быть создан, он выдаст ошибку IOException. Если вы получаете false в ответ на вызов, а не исключение, то это потому, что файл уже существует.   -  person Squonk    schedule 12.03.2013
comment
или, как указывает мой измененный ответ, потому что разрешения немного неверны...   -  person DigCamara    schedule 12.03.2013
comment
@DigCamara: getFilesDir() возвращает путь во внутреннем хранилище, поэтому разрешения на запись во внешнее хранилище не требуются. Но вы правы насчет опечатки в манифесте.   -  person Squonk    schedule 12.03.2013
comment
Что ж, если последнее предложение не сработает, я оставлю этот вопрос с советом, который дал другой человек, который также не мог создавать файлы с помощью этих инструкций: stackoverflow.com/questions/1525060/   -  person DigCamara    schedule 12.03.2013
comment
Мне кажется, что просто использование openFileOutput(...) и openFileInput(...) будет иметь смысл.   -  person Squonk    schedule 12.03.2013
comment
давайте продолжим это обсуждение в чате   -  person DigCamara    schedule 12.03.2013
comment
@Squonk, да, я зашел в каталог, где должен быть файл (от имени root), и нашел там свой файл (скрипт обновления) размером 0 КБ, получается, что проблема в записи в файл ... Для запись, я декомпилировал какое-то приложение, которое использует нужные мне функции (используя специализированный декомпилятор из apk в исходный код), оно не использует никаких разрешений для записи файла в getFilesDir(), оно делает это просто! Я увижу ваше предложение Squonk! Спасибо за помощь ребята!   -  person Seaskyways    schedule 12.03.2013
comment
@Squonk, nop, openFileInput не использует разделители путей, что вызовет исключение IllegalArguementException...   -  person Seaskyways    schedule 12.03.2013
comment
@Seaskyways : нет, openFileInput не использует разделители путей - Да, я это знаю. Не используйте разделитель пути, просто используйте имя файла. Весь смысл openFileInput(...) и openFileOutput(...) в том, что они являются вспомогательными методами, которые абстрагируются от необходимости знать что-либо о пути к файлу и каталоге, из которого он читается/записывается.   -  person Squonk    schedule 12.03.2013


Ответы (2)


Из этой документации Я понимаю, что на самом деле вы должны защищать свои вызовы .next() с помощью .hasNext().

Вот, например:

public String inputStreamToString(InputStream stream){

    Scanner s = new Scanner(stream).useDelimiter("\\A");
    if (s.hasNext()){
       return s.next();
    }else{
       return null;
    }       
}

И, если ваши разрешения написаны правильно, это

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

разрешения на самом деле не существует. Должен быть

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
person DigCamara    schedule 11.03.2013
comment
Если вы хорошо прочитали то, что я написал, вы должны были знать, что моя трассировка стека указывает на мой s.next(), потому что boolean b =file.createNewFile(); возвращает false, указывая на то, что файл не был создан, а это означает, что мой сканер не найдет next(), вызывая исключение. .. Это не ответ, это приведет к исключению NullPointerException... - person Seaskyways; 12.03.2013
comment
Ты прав. И я добавил в свой ответ новый раздел, который может объяснить, почему у вас нет прав на создание файла. Если это не поможет, я с радостью сниму свой ответ. - person DigCamara; 12.03.2013
comment
Возможно, вам придется очистить проект и переустановить его. Eclipse не очень хорошо обнаруживает изменения, внесенные в манифест (конечно, если вы используете Eclipse). - person DigCamara; 12.03.2013

Я сказал: "boolean b = file.createNewFile(); // возвращает false, указывая на то, что файл не был создан", что неверно, b = false без каких-либо исключений означает, что файл уже создан ... Но сбой был вызван тем, что в созданном файле нет текста для чтения, что, да, вызовет сбой, поскольку я ничего не читаю...

Поэтому, чтобы исправить это, мне не нужны никакие разрешения, только Java... Все, что мне нужно сделать, это либо написать что-то в этот файл, прежде чем пытаться его прочитать, либо запрограммировать мой класс, который дает мне String из InputStream, чтобы что-то вернуть вместо ничего и сбоя:

Итак, первое решение выглядит так:

File file = new File(get_data_dir(getApplicationContext()), "updater-script");
                try {

                    InputStream stream = null;
                    try {
                        stream = getAssets().open("updater-script");
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    FileOutputStream ou = new FileOutputStream(file);
                    byte[] buffer = inputStreamToString(stream).getBytes();
                    ou.write(buffer);//Now the file has something to be read ...


                    FileInputStream in = new FileInputStream(file);



                    String aa = inputStreamToString(in);

И второе решение, которое кажется проще, таково:

public String inputStreamToString(InputStream stream){
        String aa;
        Scanner s = new Scanner(stream).useDelimiter("\\A");
        if(s.hasNext()){
            aa = s.next();
        }else{
            aa = "";
        }

        return aa;//Now it returns something no matter what ...

    }
person Seaskyways    schedule 12.03.2013