简体   繁体   English

我不明白为什么 mkdir() 返回 false?

[英]I don't understand why mkdir() returns false?

I am trying to write my bitmap files to a filepath in a directory I create in androids external storage but when I run my code I recieve a null pointer exception from bitmap.compress (bitmap.CompressFormat.JPEG, 0, outputStream) .我试图将我的位图文件写入我在 androids 外部存储中创建的目录中的文件路径,但是当我运行我的代码时,我收到来自bitmap.compress (bitmap.CompressFormat.JPEG, 0, outputStream)null pointer exception From debugging I have found that my bitmap object is not null & that the outputStream object is null so the null pointer exception is occuring when I create the outputStream object & I recieve a java.io.FileNotFoundException .从调试中我发现我的bitmap对象不为 null 并且outputStream对象为 null 所以当我创建outputStream对象时发生null pointer exception & 我收到一个java.io.FileNotFoundException From debugging I know that the java.io.FileNotFoundException is occuring because dir.mkdir () returns false so no directory is created for my bitmap files.从调试中我知道java.io.FileNotFoundException正在发生,因为dir.mkdir ()返回 false 所以没有为我的位图文件创建目录。

I don't understand why dir.mkdir () returns false because I instantiate dir & check if the external storage is writable in isExternalStorageWritable() and add <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> in my manifest file and have created askPermission() , onRequestPermissionsResult() & isStoragePermissionGranted () that ask the user for permission for the external storage.我不明白为什么dir.mkdir ()返回 false 因为我实例化了dir并检查外部存储是否可以在isExternalStorageWritable()写入并在我的中添加<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> manifest 文件并创建了askPermission()onRequestPermissionsResult()isStoragePermissionGranted ()来询问用户对外部存储的许可。 So I don't understand why dir.mkdir () returns false and the directory is not created.所以我不明白为什么dir.mkdir ()返回 false 并且没有创建目录。

This is the class where the exception occurs:这是发生异常的类:

public class BitmapFiles {

public String imagePath;
public String name;
private Bitmap bitmap;
private int resourceId;
private Context context;
private OutputStream outputStream;
private File file;

public BitmapFiles (Context context, int resourceId, String name) {
    this.resourceId = resourceId;
    this.name = name;
    this.context = context;

    convertToBitmap();
    saveBitmap();
    setImagePath();
}

public void convertToBitmap () {
    bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId);

}

public void saveBitmap () {
    File filePath = Environment.getExternalStorageDirectory ();
    File dir = new File (filePath.getAbsolutePath() + "/Items");

    if (isExternalStorageWritable()) {
        Log.d ("red", "external storage is writable");//I recieve this in the log cat
    }

    if (!dir.exists ()) {
        try {
            boolean direct = dir.mkdir();//Returns false

            if (dir.exists()) {
                Log.d ("blue", "directory exists now");//I don't recieve this in the log cat
            }

            if (!direct) {
                Log.d ("green", "the directory was not created");//I recieve this in the log cat
            }

        } catch (SecurityException e) {
            e.printStackTrace();
        }

    } else {
        Log.d ("yellow", "the directory already exists");
    }

    file = new File (dir, name + ".jpg");

    try {
        outputStream = new FileOutputStream(file);
    } catch (FileNotFoundException e) {
        e.printStackTrace ();
    }

    if (outputStream == null) {
        Log.d ("grey", "outputstream is null");//I recieve this in log cat
    }

    bitmap.compress (Bitmap.CompressFormat.JPEG, 0, outputStream);

}

public boolean isExternalStorageWritable () {
    String state = Environment.getExternalStorageState();

    if (Environment.MEDIA_MOUNTED.equals (state)) {
        return true;
    }

    return false;
}

}

This is the class where I ask the user for permission:这是我向用户请求许可的课程:

public class GroceryItem extends AppCompatActivity {

private static final int STORAGE_PERMISSION_CODE = 101;

protected void onCreate (Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_grocery_item);

    askForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, STORAGE_PERMISSION_CODE);

}

public void askForPermission (String permission, int requestCode) {
    if (isStoragePermissionGranted()) {
        ActivityCompat.requestPermissions(this, new String [] {permission}, requestCode);
    } else {
        Toast.makeText (this, "Permission already granted", Toast.LENGTH_SHORT)
                .show();

    }
}

public void onRequestPermissionsResult (int requestCode, String [] permissions, int [] grantResults) {
    super.onRequestPermissionsResult (requestCode, permissions, grantResults);

    if (requestCode == STORAGE_PERMISSION_CODE) {
        if (grantResults.length > 0 && grantResults [0] == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "Storage Permission Granted", Toast.LENGTH_SHORT)
                    .show();
        } else {
            Toast.makeText(this, "Storage Permission Denied", Toast.LENGTH_SHORT)
                    .show();
        }
    }


}

public boolean isStoragePermissionGranted () {

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        Toast.makeText(this, "permission granted", Toast.LENGTH_SHORT)
                .show();
        return true;
    }

    return false;
}

}

This is the exception I recieve:这是我收到的例外:

2020-09-23 10:18:20.829 32212-32263/com.myapp.groceryapp W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Items/faan.jpg: open failed: ENOENT (No such file or directory)
2020-09-23 10:18:20.829 32212-32263/com.myapp.groceryapp W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:496)
2020-09-23 10:18:20.829 32212-32263/com.myapp.groceryapp W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:235)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at com.myapp.groceryapp.BitmapFiles.saveBitmap(BitmapFiles.java:82)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at com.myapp.groceryapp.BitmapFiles.<init>(BitmapFiles.java:30)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at com.myapp.groceryapp.MyDatabaseHelper.createBitmapFiles(MyDatabaseHelper.java:42)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at com.myapp.groceryapp.MyDatabaseHelper.upgradeDatabase(MyDatabaseHelper.java:37)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at com.myapp.groceryapp.MyDatabaseHelper.onCreate(MyDatabaseHelper.java:33)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:412)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:341)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at com.myapp.groceryapp.GroceryItem.accessDataBase(GroceryItem.java:44)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at com.myapp.groceryapp.GroceryItem$StartDatabase.doInBackground(GroceryItem.java:101)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at com.myapp.groceryapp.GroceryItem$StartDatabase.doInBackground(GroceryItem.java:93)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at android.os.AsyncTask$3.call(AsyncTask.java:378)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at java.lang.Thread.run(Thread.java:919)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at libcore.io.Linux.open(Native Method)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7581)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:482)
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp W/System.err:  ... 18 more
2020-09-23 10:18:20.830 32212-32263/com.myapp.groceryapp D/outty: outputstream is null
2020-09-23 10:18:20.836 32212-32263/com.myapp.groceryapp E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.myapp.groceryapp, PID: 32212
java.lang.RuntimeException: An error occurred while executing doInBackground()
    at android.os.AsyncTask$4.done(AsyncTask.java:399)
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
    at java.util.concurrent.FutureTask.run(FutureTask.java:271)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:919)
 Caused by: java.lang.NullPointerException
    at android.graphics.Bitmap.compress(Bitmap.java:1407)
    at com.myapp.groceryapp.BitmapFiles.saveBitmap(BitmapFiles.java:95)
    at com.myapp.groceryapp.BitmapFiles.<init>(BitmapFiles.java:30)
    at com.myapp.groceryapp.MyDatabaseHelper.createBitmapFiles(MyDatabaseHelper.java:42)
    at com.myapp.groceryapp.MyDatabaseHelper.upgradeDatabase(MyDatabaseHelper.java:37)
    at com.myapp.groceryapp.MyDatabaseHelper.onCreate(MyDatabaseHelper.java:33)
    at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:412)
    at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:341)
    at com.myapp.groceryapp.GroceryItem.accessDataBase(GroceryItem.java:44)
    at com.myapp.groceryapp.GroceryItem$StartDatabase.doInBackground(GroceryItem.java:101)
    at com.myapp.groceryapp.GroceryItem$StartDatabase.doInBackground(GroceryItem.java:93)
    at android.os.AsyncTask$3.call(AsyncTask.java:378)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
    at java.lang.Thread.run(Thread.java:919) 

The NullPointerException and FileNotFoundException are caused by incorrect error recover code. NullPointerExceptionFileNotFoundException是由错误的错误恢复代码引起的。 Put simply, your code tries too hard to write that bitmap, in situations where it is simply not possible to do so.简而言之,您的代码过于努力地编写该位图,而在这种情况下根本不可能这样做。 (If the directory doesn't exist after your attempt to create it, there is no way you could possibly save the bitmap. Persistence is futile!) (如果您尝试创建目录后该目录不存在,则您无法保存位图。持久化是徒劳的!)

The root cause of the cascade of problems is that mkdir() is (in some circumstances) by creating the the required directory.一系列问题的根本原因是mkdir()是(在某些情况下)通过创建所需的目录。

I don't understand why mkdir() returns false.我不明白为什么mkdir()返回 false。

This could be happening for a variety of reasons, including some of the following:这种情况可能是出于各种原因,包括以下一些:

  • The parent directory for the directory may not exist该目录的父目录可能不存在
  • The parent directory's ownership and permissions may be wrong父目录的所有权和权限可能有误
  • The app may not be permitted to write in this file system.可能不允许应用在此文件系统中写入。
  • The device could be read only该设备可以是只读的
  • The device could be corrupted or experiencing hardware errors设备可能已损坏或遇到硬件错误
  • The file system could be so full that a directory cannot be created.文件系统可能太满以致无法创建目录。

The problem is that it is not possible to find out which of those possible causes is the actual cause.问题是无法找出这些可能原因中的哪一个是实际原因。 File.mkdir() doesn't tell you, and doesn't provide a way to find out. File.mkdir()不会告诉您,也没有提供查找方法。 java.io.File is a clunky old interface ... and you shouldn't be using it anymore. java.io.File是一个笨重的旧界面......你不应该再使用它了。 (It was superseded in Java 7!) (它在 Java 7 中被取代了!)

The first step in solving this is to change your application to using the NIO2 Files and Path APIs.解决此问题的第一步是将您的应用程序更改为使用 NIO2 FilesPath API。 In particular, you need to use one of:特别是,您需要使用以下之一:

  • Files.createDirectory(Path dir, FileAttribute<?>... attrs) ( javadoc ) Files.createDirectory(Path dir, FileAttribute<?>... attrs) ( javadoc )
  • Files.createDirectories(Path dir, FileAttribute<?>... attrs) ( javadoc ) Files.createDirectories(Path dir, FileAttribute<?>... attrs) ( javadoc )

These both will throw an exception if the directory could not be created.如果无法创建目录,这两者都会引发异常。 In addition, createDirectory will throw an exception if the directory already exists.此外,如果目录已经存在, createDirectory将抛出异常。

In either case, the exception and its message should tell you why the operation failed.在任何一种情况下,异常及其消息都应该告诉您操作失败的原因。 This will help you to figure out what is really going on ... and hence work out how to fix it.这将帮助您弄清楚到底发生了什么……从而找出解决方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM