質問

I don't understand why we don't enter in the second if. I first check if the file exists (no, logic), I create it, and I check again but it still returns false. I tried an hour find the problem and I'm sure it's a stupid error. Sorry for my poor english

Here is the code:

package com.example.testcreatefileonclick;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class Main extends Activity implements android.view.View.OnClickListener{

    Button button;
    Button addTeam;
    Boolean append = true;

    String name = "nomFichier.txt";

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

        button = (Button)findViewById(R.id.button1);
        button.setOnClickListener((OnClickListener) this);
        addTeam = (Button)findViewById(R.id.button2);
        addTeam.setOnClickListener((OnClickListener) this);

    }

    @Override
    public void onClick(View v) {
        try {
            File fichier = new File(name);


            if (!fichier.exists()) {
                System.out.println("File doesn't exists");
            }


            FileOutputStream fOut = openFileOutput(name, MODE_WORLD_READABLE);
            OutputStreamWriter osw = new OutputStreamWriter(fOut); 
            osw.write("text");
            osw.flush();
            osw.close();

            //Why don't we go in this if ?
            if (fichier.exists()) {
                System.out.println("File exists");
            }


        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}

Edit: Working Code

package com.example.testcreatefileonclick;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class Main extends Activity implements android.view.View.OnClickListener{

    Button button;
    Button addTeam;
    Boolean append = true;
    String name = "nomFichier.txt";

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

        button = (Button)findViewById(R.id.button1);
        button.setOnClickListener((OnClickListener) this);
        addTeam = (Button)findViewById(R.id.button2);
        addTeam.setOnClickListener((OnClickListener) this);

    }

    @Override
    public void onClick(View v) {
        try {
            String filePath = (this.getFilesDir().getPath().toString());
            File fichier = new File(filePath + name);

            if (!fichier.exists()) {
                System.out.println("File doesn't exists");
            }

            fichier.createNewFile();
            FileWriter file = new FileWriter(filePath + name);
            file.write("text");
            file.flush();
            file.close();

            if (fichier.exists()) {
                System.out.println("File exists");
            }


        } catch (IOException e) {
            System.out.println("Exception");
            e.printStackTrace();
        }
    }
}
役に立ちましたか?

解決

Try replacing this :

FileOutputStream fOut = openFileOutput(name, MODE_WORLD_READABLE);
        OutputStreamWriter osw = new OutputStreamWriter(fOut); 
        osw.write("text");
        osw.flush();
        osw.close();

by this :

fichier.createNewFile();
FileWriter file = new FileWriter(name);
file.write("text");
file.flush();
file.close();

他のヒント

// Why don't we go in this if ?

The most likely reason (IMO) is that openFileOutput(name, MODE_WORLD_READABLE) throws an exception.

If that happens, you won't know about it because of this appalling piece of code.

    } catch (Exception e) {
        // TODO: handle exception
    }

Why appalling?

  1. You are catching Exception rather than the specific exceptions that you expect to be thrown (e.g. IOException).
  2. You are "squashing" the exception. You are catching it and silently throwing it away.

Each of those things individually is bad practice. Doing them together is ... well ... you deserve to have wasted an hour on this!


If my diagnosis of a squashed exception is incorrect, then there's another possibility. The docs for openFileOutput say:

"Open a private file associated with this Context's application package for writing.".

It is not entirely clear where that file would be opened / created, but it is plausible that it is in a different "place" to where File.exists is looking. You will notice that openFileOutput does NOT take a File object as its output.


Finally, there is also a more subtle problem, that won't hurt you in this context, but could in others. You wrote ...

        if (!fichier.exists()) {
            System.out.println("File doesn't exists");
        }
        FileOutputStream fOut = openFileOutput(name, MODE_WORLD_READABLE);

The problem with this is that there is a race condition. In between calling exists and calling openFileOutput, there is a small time window in which some other application could leap in and create the file. So when you then call openFileOutput, it might discover that the file has already been created.

Clearly, in this case it makes no difference. But in other cases it might. The lesson is that calling File.exists(), File.canWrite and so on to "guard" a following attempt to create / open a file is not reliable.

If not the exception issue below, it may be caching the result from your first call to the exists method (unlikely). You could try creating a new file object after the call to test this.

If I woas you I would be using the createNewFile method, which will return a boolean for you to use in your logic. This would be better than having to ask IO twice if it exists.

public boolean createNewFile() throws IOException
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top