Android mkdirs()创build一个零字节的文件,而不是一个文件夹

在我的Android应用程序中,我试图在SD卡上创build以下文件夹:

/mnt/sdcard/OSGiComponents/admin/felix-cache/ 

代码如下:

 File cacheDir = new File( Environment.getExternalStorageDirectory().getAbsolutePath() + "/OSGiComponents/admin/felix-cache/" ); // Create the folder cacheDir.mkdirs(); // Check if it exists if ( ! cacheDir.exists() ) { Log.e ( "Debug" , "Cache directory cannot be created" ); } 

我有Android清单文件的清单标记下的WRITE_STORAGE_PERMISSION。 我能够创build其他文件夹和文件在SD卡上没有问题。 该应用程序在以下手机上正常工作:

  1. Nexus S(扎根)运行姜饼(2.3)
  2. 运行Jelly Bean的Nexus S(无根)(4.1​​.2)
  3. HTC Desire(扎根)运行Froyo(2.2)
  4. HTC Desire(无根)运行Froyo(2.2)

然而在三星Galaxy Nexus手机(无根)运行冰淇淋三明治(4.0.4),该目录是创build为零大小的文件,这可以在Astro中看到。 exists()调用返回false。

Astro显示零字节felix-cache文件

  1. 从文件夹名称可以看出,我使用的是Apache Felix。 如果Felix不存在,Felix会自动创buildcaching目录。 在Galaxy Nexus上,它总是抱怨无法创buildcaching目录。 Astro显示一个0字节的文件,而不是一个文件夹。 这就是为什么我决定尝试在初始化Felix之前自己创buildcaching文件夹。
  2. 所以,我自己创build了caching文件夹。 该应用程序工作正常,第一次,我可以看到在Astro罚款的文件夹。 如果我closures应用程序,然后删除Astro中的文件夹,然后重新启动应用程序,即使我的代码神秘不能创buildcaching目录,Astro显示一个0字节的文件。
  3. 在Astro中不能删除0字节的文件。 但是,当我重新启动手机,文件夹神奇地在那里,确定。
  4. 我使用FileInstall来观看OSGiComponents /安装文件夹。 当我将捆绑包放入该文件夹时,除了Galaxy Nexus(当应用程序第一次运行时),它会在所有手机上检测到并安装。 FileInstall没有关于无法看到目录的日志/错误。
  5. 我已经在2款Galaxy Nexus手机上testing过这个问题。

我怀疑这是一个权限问题,但我不知道它是什么,为什么一个0字节的文件被创build而exists()返回false。 我没有在代码中创build此文件。

有什么build议可能是什么问题?

谢谢 :)

更新:我想我已经确定了这个问题,请看我发布的答案。

Solutions Collecting From Web of "Android mkdirs()创build一个零字节的文件,而不是一个文件夹"

请使用,而不是

  File cacheDir = new File( Environment.getExternalStorageDirectory().getAbsolutePath() + "/OSGiComponents/admin/felix-cache/" ); cacheDir.mkdirs(); 

  File cacheDir = new File( Environment.getExternalStorageDirectory().getAbsolutePath() + "/OSGiComponents/admin/felix-cache" ); cacheDir.mkdir(); 

我find了解决这个问题的解决方法。 每当我删除一个文件/目录,而不是直接使用delete(),我重命名文件/文件夹,然后删除()它。 这个奇怪的解决方法似乎消除了这个问题。

通过看到这个问题的答案,我得到了这个想法 – 打开失败的EBUSY设备或资源忙

但是,我不确定这是为什么起作用,或者是什么原因造成了这个问题。

如果其他人在Galaxy Nexus上使用Felix并遇到同样的问题,只需更改Felix源代码,如下所示:

org.apache.felix.framework.util.SecureAction.java:

 public boolean deleteFile(File target) { if (System.getSecurityManager() != null) { try { Actions actions = (Actions) m_actions.get(); actions.set(Actions.DELETE_FILE_ACTION, target); return ((Boolean) AccessController.doPrivileged(actions, m_acc)) .booleanValue(); } catch (PrivilegedActionException ex) { throw (RuntimeException) ex.getException(); } } else { // Solution: Rename before deleting // https://stackoverflow.com/questions/11539657/open-failed-ebusy-device-or-resource-busy File to = new File(target.getAbsolutePath() + System.currentTimeMillis()); boolean renameStatus = target.renameTo(to); boolean deleteStatus = to.delete(); boolean returnStatus = ( renameStatus && deleteStatus ); // Debug SecureAction //boolean returnStatus = target.delete(); Log.e ( "SecureAction" , "Deleting " + target + " delete(): " + returnStatus ); return returnStatus; } } 

我build议您使用adb连接到设备,并使用目录中的命令ls -l来检查什么是操作系统报告这个0 size file (权限等)。 这最终可能会带来一些问题。

如果你不能找出一个可行的解决scheme,也许你可以使用exec()来直接执行一个mkdir

你可以使用cobe波纹pipe来做到这一点:

 public static boolean execCmd(String command, ArrayList<String> results){ Process process; try { process = Runtime.getRuntime().exec(new String [] {"sh", "-c", command}); } catch (IOException e) { e.printStackTrace(); return false; } int result; try { result = process.waitFor(); } catch (InterruptedException e1) { e1.printStackTrace(); return false; } if(result != 0){ //error executing command Log.d("execCmd", "result code : " + result); String line; BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); try { while ((line = bufferedReader.readLine()) != null){ if(results != null) results.add(line); Log.d("execCmd", "Error: " + line); } } catch (IOException e) { e.printStackTrace(); return false; } return false; } //Command execution is OK BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; try { while ((line = bufferedReader.readLine()) != null){ if(results != null) results.add(line); Log.d("execCmd", line); } } catch (IOException e) { e.printStackTrace(); return false; } return true; } 

要使用它:

 boolean res= execCmd("mkdir "+ Environment.getExternalStorageDirectory().getAbsolutePath() + "/OSGiComponents", results); if(!res) return error; res= execCmd("mkdir "+ Environment.getExternalStorageDirectory().getAbsolutePath() + "/OSGiComponents/admin", results); if(!res) return error; res= execCmd("mkdir "+ Environment.getExternalStorageDirectory().getAbsolutePath() + "/OSGiComponents/admin/felix-cache", results); if(!res) return error; 

问候。

 String root = Environment.getExternalStorageDirectory() .getAbsolutePath()+"/OSGiComponents/admin/felix-cache"; File myDir = new File(root); String fname = "Image Name as you want"; File file = new File(myDir, fname); if (file.exists()) file.delete(); try { FileOutputStream out = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.PNG, 90, out); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); } 

虽然不是直接回答您的问题,但下面提到的信息可能会帮助您:

在某些设备中, Environment.getExternalStorageDirectory().getAbsolutePath()不需要反映实际的外部SD卡path。 有时代表内部存储。

例如在Galaxy Note 2中:

 Log.i(TAG,Environment.getExternalStorageDirectory().getAbsolutePath()); 

将打印

12-19 17:35:11.366:E / sample.Examples(10420):/ storage / sdcard0

同时实际​​的外部SD卡应该是:

/存储/ extSdCard

以下是几个有关这个问题的post,可以帮助你:

build立一个实用程序,以获得每次外部可移动存储的path

检查SDCard是否存在,布尔值始终为true

我怎样才能在三星和所有其他设备上获得正确的外部存储?

Android如何使用Environment.getExternalStorageDirectory()