【问题标题】:Android: FileNotFoundException using FileInputStreamAndroid:使用 FileInputStream 的 FileNotFoundException
【发布时间】:2016-08-01 20:53:04
【问题描述】:

我正在构建一个 FileManager 类来处理我所有的文件管理需求。理想情况下,这个 FileManager 应该完全依赖于 Android SDK 提供的方法。就正确管理子目录而言,我遇到了障碍。当我尝试使用新的 FileInputStream 对象加载文件时,遇到了 FileNotFoundException。如果我尝试将 context.openFileInput 与自定义文件路径一起使用,则会遇到与路径分隔符相关的 IllegalArgumentException。

这是我的 writefile 和 readfile 方法。传递给这些方法的所有 Directory 字符串都是内部存储中的子目录(例如 data/user/0/com.app.package/files/recordings,其中 recordings 是我创建的子目录)。 :

 /**
 * Writes the provided data to a file based on the designated filename and directory
 * @param data - Array of Strings to be written to the file
 * @param fileName - Relative path of the file being written
 * @param dir - Path of the directory where the file will be written
 * @throws IOException
 */
    private void writeFile(String[] data, String fileName, String dir) throws     IOException {
    Log.v(LOG_TAG, "writeFile");
    if(fileName == null) {
        Log.w(LOG_TAG, "No File Path Provided. File Not Written.");
        return;
    }

    /* Creates and Appends the directory to the provided filename */
    if(dir != null && dir.length() > 0) {
        createDirectory(dir);
        fileName = String.format("%s/%s", dir, fileName);
    }

    /* Opens the Output Stream */
    FileOutputStream fileStream = context.openFileOutput(fileName, Context.MODE_PRIVATE);

    /* Joins String Array into one string to be written to the file */
    String text = TextUtils.join(" ", data);

    /* Writes the String in bytes to the file stream */
    fileStream.write(text.getBytes());

    /* Closes the output stream */
    fileStream.close();

    //This Commented block was part of my previous method of writing files.
    /*
    OutputStreamWriter outputStream = new OutputStreamWriter(fileStream);

    for(int i = 0; i < data.length; i++){
        outputStream.write(data[i]);
        if(i < data.length - 1)
            outputStream.write("\n");
    }
    outputStream.close();
    */
}

 /**
 *
 * @param filePath - Relative Filepath of the file being accessed
 * @param dir - Path of the Directory the file can be found in
 * @return - Array of Strings for containing each line of the accessed file.
 * @throws IOException
 */
private String[] readFile(String filePath, String dir) throws IOException {
    Log.v(LOG_TAG, "readFile");
    if(filePath == null)
        return null;

    /* Updates the Filepath with the directory */
    if(dir != null && dir.length() > 0)
        filePath = String.format("%s/%s", dir, filePath);

    String temp;
    ArrayList<String> list = new ArrayList<>();

    /* Initializing Input Stream & Reader */
    FileInputStream fileStream = new FileInputStream(new File(filePath));
    InputStreamReader inputStream = new InputStreamReader(fileStream);
    BufferedReader input = new BufferedReader(inputStream);

    /* Reads Each line into an Array List */
    while((temp = input.readLine()) != null){
        list.add(temp);
    }

    /* Close the Input Streams */
    input.close();
    inputStream.close();

    if(list.size() < 1)
        return null;

    String[] arr = new String[list.size()];
    arr = list.toArray(arr);

    return arr;
}

我需要能够一致地读取、写入和删除文本文件及其包含在内部存储器中的目录,我对自己做错了什么感到很困惑,因为我知道这应该相对简单.非常感谢有关为什么这些方法没有按预期运行的一些信息。

【问题讨论】:

  • 您是否已授予应用访问文件/文件夹的权限?
  • @Robotia - 应用程序始终拥有对其内部存储文件夹的权限,除非对方授予世界访问权限,否则无法获得其他任何人的权限。这更多的是对文件名的误解和文件方法的误用。
  • 正如 Chris 所说,我真的不需要它,但无论如何我的清单中都有 WRITE_EXTERNAL_STORAGE 权限,因为我也打算提供此功能(一次一步,当然)。
  • 我的错,没有明白内部是指内部应用存储!

标签: java android file filenotfoundexception illegalargumentexception


【解决方案1】:

在您的 readFile 方法中,您将获得文件路径,我认为它可能如下所示:data/user/0/com.app.package/files/recordings/examplefile1.xml 和这个路径目录,在这种情况下可能看起来像这样: data/user/0/com.app.package/files/recordings.

然后,您将这两个字符串与中间的路径分隔符连接起来。这将导致在我的示例中:data/user/0/com.app.package/files/recordings/data/user/0/com.app.package/files/recordings/examplefile1.xml

假设你传入的目录如下:data/user/0/com.app.package/files/recordings/ 然后,此路径将导致以下结果:data/user/0/com.app.package/files/recordings//data/user/0/com.app.package/files/recordings/examplefile1.xml

所以我看到了两点

  1. 您必须确保filePath 参数只包含文件名
  2. 您必须确保dir 参数末尾没有路径分隔符

【讨论】:

  • 确实——但实际上比这更糟。 Context 的 openFileInput() 和 openFileOutput() 方法本身期望没有路径的裸文件名,因此如果没有抛出异常,则目录路径实际上会在其中 3 次在最终尝试的任何访问中.
  • 我已确认您的两点都符合。这是 logcat 输出(只有 2 行),指示每个变量的值(每个方法调用都是统一的):08-01 22:31:13.647 7183-7183/com.app.package D/FILE-MANAGER: Directory: data/user/0/com.app.package/files/recordings 08-01 22:31:13.647 7183-7183/com.app.package D/FILE-MANAGER: Filepath: 2016_08_02_02_31_13.txt
  • 您是如何获得目录的?我刚刚测试了使用getFilesDir-方法获取自己应用程序的内部存储路径,在我的情况下,它有一个前导路径分隔符......所以它看起来像这样/data/data/com.jonny9298.backboardtest/files
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-19
  • 1970-01-01
  • 1970-01-01
  • 2019-01-13
相关资源
最近更新 更多