【问题标题】:Create a directory if it does not exist and then create the files in that directory as well如果目录不存在,则创建一个目录,然后在该目录中创建文件
【发布时间】:2015-05-10 22:03:03
【问题描述】:

条件是如果目录存在,则必须在该特定目录中创建文件而不创建新目录。

下面的代码只为新目录创建一个文件,而不是为现有目录创建一个文件。例如,目录名称类似于“GETDIRECTION”:

String PATH = "/remote/dir/server/";
    
String fileName = PATH.append(id).concat(getTimeStamp()).append(".txt");  
             
String directoryName = PATH.append(this.getClassName());   
              
File file  = new File(String.valueOf(fileName));

File directory = new File(String.valueOf(directoryName));

if (!directory.exists()) {
        directory.mkdir();
        if (!file.exists() && !checkEnoughDiskSpace()) {
            file.getParentFile().mkdir();
            file.createNewFile();
        }
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(value);
bw.close();

【问题讨论】:

    标签: java java-io


    【解决方案1】:

    此代码首先检查目录是否存在,如果不存在则创建它,然后创建文件。请注意,由于我没有您的完整代码,因此我无法验证您的某些方法调用,因此我假设对 getTimeStamp()getClassName() 之类的调用将起作用。您还应该对使用任何 java.io.* 类时可能抛出的 IOException 做一些事情 - 编写文件的函数应该抛出这个异常(并且它在其他地方处理),或者你应该在方法直接。另外,我假设 id 的类型为 String - 我不知道,因为您的代码没有明确定义它。如果它是 int 之类的其他东西,您可能应该将其转换为 String,然后再像我在这里所做的那样在文件名中使用它。

    此外,我将您的 append 电话替换为 concat+,因为我认为合适。

    public void writeFile(String value){
        String PATH = "/remote/dir/server/";
        String directoryName = PATH.concat(this.getClassName());
        String fileName = id + getTimeStamp() + ".txt";
    
        File directory = new File(directoryName);
        if (! directory.exists()){
            directory.mkdir();
            // If you require it to make the entire directory path including parents,
            // use directory.mkdirs(); here instead.
        }
    
        File file = new File(directoryName + "/" + fileName);
        try{
            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(value);
            bw.close();
        }
        catch (IOException e){
            e.printStackTrace();
            System.exit(-1);
        }
    }
    

    如果您想在 Microsoft Windows 上运行代码,您可能不应该使用这样的裸路径名 - 我不确定文件名中的 / 会做什么。为了实现完全的可移植性,您可能应该使用File.separator 之类的东西来构建您的路径。

    编辑:根据下面JosefScript 的评论,没有必要测试目录是否存在。如果创建了目录,directory.mkdir() 调用将返回 true,如果没有,则返回 false,包括目录已经存在的情况。

    【讨论】:

    • 通话工作正常。当我尝试上面的 coed 时,它仍在将文件写入 PATH 但不写入目录。我已使用 File.seperator 来创建新文件。
    • 请准确解释(使用类名和示例变量)您期望的输出。我在pastebin.com/3eEg6jQv 处附上了我的完整示例程序,这样你就可以看到它做了你所描述的事情(据我所知)。
    • 文件 file = new File(directoryName + "/" + fileName);我将上面的代码 sn-p 替换为 StringBuffer fullFilePath = new StringBuffer(directoryName).append(File.separator).append(fileName);文件 file = new File(String.valueOf(fullFilePath));它奏效了
    • 为什么要检查目录是否存在?我玩过这个,据我所知,如果我两次创建同一个目录,它似乎没有什么区别。即使包含的文件也不会被覆盖。我错过了什么吗?
    • 据我所知,Java(至少是 Java 8)现在对正斜杠是 Windows 和(显然)Linux 中的目录分隔符感到满意。
    【解决方案2】:

    代码:

    // Create Directory if not exist then Copy a file.
    
    
    public static void copyFile_Directory(String origin, String destDir, String destination) throws IOException {
    
        Path FROM = Paths.get(origin);
        Path TO = Paths.get(destination);
        File directory = new File(String.valueOf(destDir));
    
        if (!directory.exists()) {
            directory.mkdir();
        }
            //overwrite the destination file if it exists, and copy
            // the file attributes, including the rwx permissions
         CopyOption[] options = new CopyOption[]{
                    StandardCopyOption.REPLACE_EXISTING,
                    StandardCopyOption.COPY_ATTRIBUTES
    
            };
            Files.copy(FROM, TO, options);
    
    
    }
    

    【讨论】:

      【解决方案3】:

      对于 Java8+,我建议如下。

      /**
       * Creates a File if the file does not exist, or returns a
       * reference to the File if it already exists.
       */
      private File createOrRetrieve(final String target) throws IOException{
      
          final Path path = Paths.get(target);
      
          if(Files.notExists(path)){
              LOG.info("Target file \"" + target + "\" will be created.");
              return Files.createFile(Files.createDirectories(path)).toFile();
          }
          LOG.info("Target file \"" + target + "\" will be retrieved.");
          return path.toFile();
      }
      
      /**
       * Deletes the target if it exists then creates a new empty file.
       */
      private File createOrReplaceFileAndDirectories(final String target) throws IOException{
      
          final Path path = Paths.get(target);
          // Create only if it does not exist already
          Files.walk(path)
              .filter(p -> Files.exists(p))
              .sorted(Comparator.reverseOrder())
              .peek(p -> LOG.info("Deleted existing file or directory \"" + p + "\"."))
              .forEach(p -> {
                  try{
                      Files.createFile(Files.createDirectories(p));
                  }
                  catch(IOException e){
                      throw new IllegalStateException(e);
                  }
              });
      
          LOG.info("Target file \"" + target + "\" will be created.");
      
          return Files.createFile(
              Files.createDirectories(path)
          ).toFile();
      }
      

      【讨论】:

      • Files.createFile(Files.createDirectories(path)).toFile() 应该是 Files.createDirectories(path).toFile() 原因是 Access Denied
      • @Pytry, Files.createFile(Files.createDirectories(path)) 不像上面评论中描述的那样工作。 createDirectories 已经创建了一个具有文件名的目录,例如“test.txt”,因此createFile 将失败。
      【解决方案4】:

      尽量使这个过程简短而简单。如果目录不存在则创建目录,然后返回所需文件:

      /** Creates parent directories if necessary. Then returns file */
      private static File fileWithDirectoryAssurance(String directory, String filename) {
          File dir = new File(directory);
          if (!dir.exists()) dir.mkdirs();
          return new File(directory + "/" + filename);
      }
      

      【讨论】:

      • 首选使用 File.separatorChar 而不是“/”。
      【解决方案5】:

      使用java.nio.Path 的简单解决方案

      public static Path createFileWithDir(String directory, String filename) {
              File dir = new File(directory);
              if (!dir.exists()) dir.mkdirs();
              return Paths.get(directory + File.separatorChar + filename);
          }
      

      【讨论】:

        【解决方案6】:

        如果您创建基于 Web 的应用程序,更好的解决方案是检查目录是否存在,如果不存在则创建文件。如果存在,请重新创建。

            private File createFile(String path, String fileName) throws IOException {
               ClassLoader classLoader = getClass().getClassLoader();
               File file = new File(classLoader.getResource(".").getFile() + path + fileName);
        
               // Lets create the directory
               try {
                  file.getParentFile().mkdir();
               } catch (Exception err){
                   System.out.println("ERROR (Directory Create)" + err.getMessage());
               }
        
               // Lets create the file if we have credential
               try {
                   file.createNewFile();
               } catch (Exception err){
                   System.out.println("ERROR (File Create)" + err.getMessage());
               }
               return  file;
           }
        

        【讨论】:

          【解决方案7】:

          Java 8+ 版本:

          Files.createDirectories(Paths.get("/Your/Path/Here"));
          

          Files.createDirectories() 创建一个新目录和不存在的父目录。如果目录已经存在,此方法不会抛出异常。

          【讨论】:

          • 如果需要创建权限会怎样?
          • 对于 Android 它仅适用于 API 26 及更高版本,因此请确保检查此行 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) developer.android.com/reference/java/nio/file/…
          • @AjayTakur 如果您在尝试创建新目录的目录中没有写入权限,则会引发 IOException
          • 如何让进程获得在Windows 10上创建目录的权限?