View Javadoc
1   // ******************************************************************************
2   //
3   // Title:       Force Field X.
4   // Description: Force Field X - Software for Molecular Biophysics.
5   // Copyright:   Copyright (c) Michael J. Schnieders 2001-2025.
6   //
7   // This file is part of Force Field X.
8   //
9   // Force Field X is free software; you can redistribute it and/or modify it
10  // under the terms of the GNU General Public License version 3 as published by
11  // the Free Software Foundation.
12  //
13  // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16  // details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA 02111-1307 USA
21  //
22  // Linking this library statically or dynamically with other modules is making a
23  // combined work based on this library. Thus, the terms and conditions of the
24  // GNU General Public License cover the whole combination.
25  //
26  // As a special exception, the copyright holders of this library give you
27  // permission to link this library with independent modules to produce an
28  // executable, regardless of the license terms of these independent modules, and
29  // to copy and distribute the resulting executable under terms of your choice,
30  // provided that you also meet, for each linked independent module, the terms
31  // and conditions of the license of that module. An independent module is a
32  // module which is not derived from or based on this library. If you modify this
33  // library, you may extend this exception to your version of the library, but
34  // you are not obligated to do so. If you do not wish to do so, delete this
35  // exception statement from your version.
36  //
37  // ******************************************************************************
38  package ffx.utilities;
39  
40  import java.io.BufferedOutputStream;
41  import java.io.File;
42  import java.io.FileOutputStream;
43  import java.io.FileWriter;
44  import java.io.IOException;
45  import java.io.InputStream;
46  import java.io.OutputStream;
47  import java.nio.file.Files;
48  import java.nio.file.Path;
49  import java.util.ArrayList;
50  import java.util.List;
51  import java.util.logging.Logger;
52  import java.util.regex.Pattern;
53  import java.util.stream.Collectors;
54  import java.util.stream.Stream;
55  
56  import static java.io.File.createTempFile;
57  import static java.lang.String.format;
58  import static java.nio.file.Paths.get;
59  
60  /**
61   * FileUtils class.
62   *
63   * @author Michael J. Schnieders
64   * @since 1.0
65   */
66  public class FileUtils {
67  
68    private static final Logger logger = Logger.getLogger(FileUtils.class.getName());
69  
70    /**
71     * Private constructor to prevent instantiation.
72     */
73    private FileUtils() {
74      // Empty constructor.
75    }
76  
77    /**
78     * Returns the file name of a temporary copy of <code>input</code> content.
79     *
80     * @param input  The input stream contents are copied to a temporary file.
81     * @param prefix Temporary file prefix.
82     * @param name   Temporary file name.
83     * @param suffix Temporary file suffix.
84     * @return The temporary file.
85     * @throws java.io.IOException An IOException is thrown if a temporary file could not be created.
86     */
87    public static String copyInputStreamToTmpFile(
88        final InputStream input, String prefix, String name, final String suffix) throws IOException {
89      File tmpFile = null;
90  
91      name = prefix + "." + name + ".";
92      try {
93        tmpFile = createTempFile(name, "." + suffix);
94      } catch (IOException e) {
95        System.out.printf(" Could not extract %s.%n", name);
96        System.err.println(e.getMessage());
97        System.exit(-1);
98      }
99      tmpFile.deleteOnExit();
100 
101     try (input;
102          OutputStream output = new BufferedOutputStream(new FileOutputStream(tmpFile))) {
103       byte[] buffer = new byte[8192];
104       int size;
105       while ((size = input.read(buffer)) != -1) {
106         output.write(buffer, 0, size);
107       }
108     }
109 
110     return tmpFile.toString();
111   }
112 
113   /**
114    * Constructs a relative path from the present working directory to a file.
115    *
116    * @param file Construct a relative path to file.
117    * @return Relative path to file.
118    */
119   public static Path relativePathTo(File file) {
120     File pwd = new File(".");
121     Path pwdPath = get(pwd.getAbsolutePath());
122     Path otherPath = get(file.getAbsolutePath());
123     return pwdPath.relativize(otherPath);
124   }
125 
126   /**
127    * Traverse a directory to find files matching the given regex pattern.
128    *
129    * @param directory   The directory to traverse.
130    * @param maxDepth    Maximum depth to traverse.
131    * @param filePattern Regular expression pattern to match file names.
132    * @return List of matching files.
133    */
134   public static List<File> traverseFiles(File directory, int maxDepth, String filePattern) {
135     List<File> matchingFiles = new ArrayList<>();
136     Pattern pattern = Pattern.compile(filePattern);
137 
138     try (Stream<Path> paths = Files.walk(directory.toPath(), maxDepth)) {
139       matchingFiles = paths
140           .filter(Files::isRegularFile)
141           .filter(path -> pattern.matcher(path.getFileName().toString()).matches())
142           .map(Path::toFile)
143           .collect(Collectors.toList());
144     } catch (IOException e) {
145       logger.warning(format("Error traversing directory %s: %s", directory.getAbsolutePath(), e.getMessage()));
146     }
147 
148     return matchingFiles;
149   }
150 
151   /**
152    * Append content to a file.
153    *
154    * @param file    The file to append content to.
155    * @param content The content to append.
156    */
157   public static void append(File file, String content) {
158     try (FileWriter fw = new FileWriter(file, true)) {
159       fw.write(content);
160     } catch (IOException e) {
161       logger.warning(format(" Error appending %s to file %s\n " + e.getMessage(), content, file.getAbsolutePath()));
162     }
163   }
164 }