文件已创建但返回false

时间:2013-04-18 12:10:02

标签: java android file exists creation

我不明白为什么我们不进入第二个if。我首先检查文件是否存在(不,逻辑),我创建它,然后我再次检查,但它仍然返回false。我试了一个小时找到问题,我确定这是一个愚蠢的错误。抱歉我的英语不好

以下是代码:

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
        }
    }
}

编辑:工作代码

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

3 个答案:

答案 0 :(得分:1)

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

最可能的原因(IMO)是openFileOutput(name, MODE_WORLD_READABLE)抛出异常。

如果发生这种情况,由于这段令人震惊的代码,你不会知道它。

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

为什么骇人听闻?

  1. 您正在捕捉Exception而非您期望的特定异常(例如IOException)。
  2. 你正在“挤压”这个例外。你正在捕捉它并且默默地扔掉它。
  3. 每一件事都是不良做法。把它们放在一起是......好吧......你值得浪费一个小时就可以了!


    如果我对被压扁的异常的诊断不正确,那么还有另一种可能性。 openFileOutput的文档说:

      

    “打开与此Context的应用程序包关联的私有文件以进行编写。”

    目前还不完全清楚该文件的打开/创建位置,但它与File.exists正在寻找的位置处于不同的“位置”似乎是合理的。您会注意到openFileOutput不会将File对象作为其输出。


    最后,还有一个更微妙的问题,在这种情况下不会伤到你,但可以在其他情况下。你写了......

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

    这个问题是存在竞争条件。在调用exists和调用openFileOutput之间,有一个小时间窗口,其中一些其他应用程序可以跳进并创建文件。因此,当您再调用openFileOutput时,它可能会发现该文件已经创建。

    显然,在这种情况下它没有任何区别。但在其他情况下可能会。我们的教训是,调用File.exists()File.canWrite等以“保护”以下创建/打开文件的尝试是不可靠的。

答案 1 :(得分:1)

尝试替换它:

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

由此:

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

答案 2 :(得分:0)

如果不是下面的例外问题,它可能会缓存第一次调用exists方法的结果(不太可能)。您可以在调用之后尝试创建一个新的文件对象。

如果我是你,我将使用createNewFile方法,该方法将返回一个布尔值供您在逻辑中使用。如果它存在的话,这比不得不问IO两次要好。

public boolean createNewFile() throws IOException