$darkmode
DENOPTIM
FileUtils.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2022 Marco Foscato <marco.foscato@uib.no>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package denoptim.files;
20
21import java.io.BufferedInputStream;
22import java.io.BufferedReader;
23import java.io.File;
24import java.io.FileFilter;
25import java.io.FileInputStream;
26import java.io.FileOutputStream;
27import java.io.FileReader;
28import java.io.IOException;
29import java.io.OutputStream;
30import java.io.RandomAccessFile;
31import java.nio.channels.FileChannel;
32import java.nio.channels.FileLock;
33import java.nio.file.Files;
34import java.nio.file.Paths;
35import java.nio.file.StandardOpenOption;
36import java.util.ArrayList;
37import java.util.HashMap;
38import java.util.List;
39import java.util.Map;
40import java.util.Map.Entry;
41import java.util.logging.Level;
42import java.util.zip.CRC32;
43import java.util.zip.ZipEntry;
44import java.util.zip.ZipOutputStream;
45
46import org.apache.commons.io.FilenameUtils;
47import org.apache.commons.io.filefilter.WildcardFileFilter;
48
49import com.google.gson.Gson;
50
51import denoptim.constants.DENOPTIMConstants;
52import denoptim.exception.DENOPTIMException;
53import denoptim.io.DenoptimIO;
54import denoptim.json.DENOPTIMgson;
55import denoptim.logging.StaticLogger;
56
57public class FileUtils
58{
59
60//------------------------------------------------------------------------------
61
67 public static void addToRecentFiles(String fileName, FileFormat ff)
68 {
69 FileUtils.addToRecentFiles(new File(fileName), ff);
70 }
71
72//------------------------------------------------------------------------------
73
81 public static void addToRecentFiles(File file, FileFormat ff)
82 {
83 String text = "";
84 Map<File, FileFormat> existingEntries = DenoptimIO.readRecentFilesMap();
85 int maxSize = 20;
86 int toIgnore = existingEntries.size() + 1 - maxSize;
87 int ignored = 0;
88 for (Entry<File, FileFormat> e : existingEntries.entrySet())
89 {
90 if (ignored < toIgnore)
91 {
92 ignored++;
93 continue;
94 }
95 text = text + e.getValue() + " " + e.getKey()
97 }
98 text = text + ff + " " + file.getAbsolutePath();
99 try
100 {
102 DENOPTIMConstants.RECENTFILESLIST.getAbsolutePath(), text,
103 false);
104 } catch (DENOPTIMException e)
105 {
106 StaticLogger.appLogger.log(Level.WARNING, "WARNING: unable to "
107 + "write list of recent files.", e);
108 }
109 }
110
111//------------------------------------------------------------------------------
112
132 public static boolean isLineInTxtFile(String query, File file, boolean add)
133 throws IOException
134 {
135 boolean found = false;
136
137 RandomAccessFile rafile = null; // The file we'll lock
138 FileChannel channel = null; // The channel to the file
139 FileLock lock = null; // The lock object we hold
140
141 try
142 {
143 rafile = new RandomAccessFile(file, "rw");
144 channel = rafile.getChannel();
145 lock = channel.lock();
146
147 for (String line; (line = rafile.readLine()) != null; )
148 {
149 if (line.trim().length() == 0)
150 continue;
151 if (line.trim().equalsIgnoreCase(query.trim()))
152 {
153 found = true;
154 break;
155 }
156 }
157
158 if (!found && add)
159 {
160 rafile.seek(channel.position());
161 rafile.writeBytes(query.trim() + DenoptimIO.NL);
162 channel.force(true);
163 }
164 }
165 finally
166 {
167 if (channel != null)
168 channel.close();
169 if (rafile!= null)
170 rafile.close();
171 if (lock != null && lock.isValid())
172 lock.release();
173 }
174 return found;
175 }
176
177//------------------------------------------------------------------------------
178
185 public static boolean canWriteAndReadTo(String pathName) {
186 boolean res = true;
187 try {
188 DenoptimIO.writeData(pathName, "TEST", false);
189 DenoptimIO.readList(pathName);
190 } catch (DENOPTIMException e) {
191 res = false;
192 }
193 return res;
194 }
195
196//------------------------------------------------------------------------------
197
204 public static String getTempFolder() {
205
206 ArrayList<String> tmpFolders = new ArrayList<String>();
207 tmpFolders.add(System.getProperty("file.separator") + "tmp");
208 tmpFolders.add(System.getProperty("file.separator") + "scratch");
209 tmpFolders.add(System.getProperty("java.io.tmpdir"));
210
211 String tmpPathName = "";
212 String tmpFolder = "";
213 for (String t : tmpFolders) {
214 tmpFolder = t;
215 tmpPathName = tmpFolder + System.getProperty("file.separator")
216 + "Denoptim_tmpFile";
217 if (canWriteAndReadTo(tmpPathName)) {
218 break;
219 }
220 }
221 return tmpFolder;
222 }
223
224//------------------------------------------------------------------------------
225
231 public static boolean createDirectory(String fileName) {
232 return (new File(fileName)).mkdir();
233 }
234
235//------------------------------------------------------------------------------
236
241 public static boolean checkExists(String fileName) {
242 if (fileName.length() > 0) {
243 return (new File(fileName)).exists();
244 }
245 return false;
246 }
247
248//------------------------------------------------------------------------------
249
256 public static void deleteFile(String fileName) throws DENOPTIMException {
257 File f = new File(fileName);
258 // Make sure the file or directory exists and isn't write protected
259 if (!f.exists()) {
260 return;
261 }
262
263 if (!f.canWrite()) {
264 return;
265 }
266
267 // If it is a directory, make sure it is empty
268 if (f.isDirectory()) {
269 return;
270 }
271
272 // Attempt to delete it
273 boolean success = f.delete();
274
275 if (!success) {
276 throw new DENOPTIMException("Deletion of " + fileName + " failed.");
277 }
278 }
279
280//------------------------------------------------------------------------------
281
289 public static void deleteFilesContaining(String path, String pattern)
290 throws DENOPTIMException {
291 File folder = new File(path);
292 File[] listOfFiles = folder.listFiles();
293 for (int i = 0; i < listOfFiles.length; i++) {
294 if (listOfFiles[i].isFile()) {
295 String name = listOfFiles[i].getName();
296 if (name.contains(pattern)) {
297 deleteFile(listOfFiles[i].getAbsolutePath());
298 }
299 }
300 }
301 }
302
303//------------------------------------------------------------------------------
304
312 public static int countLinesInFile(String fileName) throws DENOPTIMException {
313 BufferedInputStream bis = null;
314 try {
315 bis = new BufferedInputStream(new FileInputStream(fileName));
316 byte[] c = new byte[1024];
317 int count = 0;
318 int readChars = 0;
319 while ((readChars = bis.read(c)) != -1) {
320 for (int i = 0; i < readChars; ++i) {
321 if (c[i] == '\n') {
322 ++count;
323 }
324 }
325 }
326 return count;
327 } catch (IOException ioe) {
328 throw new DENOPTIMException(ioe);
329 } finally {
330 try {
331 if (bis != null) {
332 bis.close();
333 }
334 } catch (IOException ioe) {
335 throw new DENOPTIMException(ioe);
336 }
337 }
338 }
339
340//------------------------------------------------------------------------------
341
349 public static void createZipFile(String zipOutputFileName,
350 String[] filesToZip) throws Exception {
351 FileOutputStream fos = new FileOutputStream(zipOutputFileName);
352 ZipOutputStream zos = new ZipOutputStream(fos);
353 int bytesRead;
354 byte[] buffer = new byte[1024];
355 CRC32 crc = new CRC32();
356 for (int i = 0, n = filesToZip.length; i < n; i++) {
357 String fname = filesToZip[i];
358 File cFile = new File(fname);
359 if (!cFile.exists()) {
360 continue;
361 }
362
363 BufferedInputStream bis = new BufferedInputStream(
364 new FileInputStream(cFile));
365 crc.reset();
366 while ((bytesRead = bis.read(buffer)) != -1) {
367 crc.update(buffer, 0, bytesRead);
368 }
369 bis.close();
370 // Reset to beginning of input stream
371 bis = new BufferedInputStream(new FileInputStream(cFile));
372 ZipEntry ze = new ZipEntry(fname);
373 // DEFLATED setting for a compressed version
374 ze.setMethod(ZipEntry.DEFLATED);
375 ze.setCompressedSize(cFile.length());
376 ze.setSize(cFile.length());
377 ze.setCrc(crc.getValue());
378 zos.putNextEntry(ze);
379 while ((bytesRead = bis.read(buffer)) != -1) {
380 zos.write(buffer, 0, bytesRead);
381 }
382 bis.close();
383 }
384 zos.close();
385 }
386
387//------------------------------------------------------------------------------
388
399 public static FileFormat detectFileFormat(File inFile)
400 throws UndetectedFileFormatException, IOException
401 {
402 FileFormat ff = null;
403 String ext = FilenameUtils.getExtension(inFile.getAbsolutePath());
404 // Folders are presumed to contain output kind of data
405 if (inFile.isDirectory())
406 {
407
408 // This is to distinguish GA from FSE runs
409 for(File folder : inFile.listFiles(new FileFilter() {
410
411 @Override
412 public boolean accept(File pathname) {
413 if (pathname.isDirectory())
414 {
415 return true;
416 }
417 return false;
418 }
419 }))
420 {
421 if (folder.getName().startsWith(
423 {
424 ff = FileFormat.FSE_RUN;
425 return ff;
426 }
427 else if (folder.getName().startsWith(
429 {
430 ff = FileFormat.GA_RUN;
431 return ff;
432 }
433 }
434
435 throw new UndetectedFileFormatException(inFile);
436 }
437
438 // Files are first distinguished first by extension
439 switch (ext.toUpperCase())
440 {
441 case "SDF":
442 //Either graphs or fragment
443 ff = FileUtils.detectKindOfSDFFile(inFile.getAbsolutePath());
444 break;
445
446 case "JSON":
447 ff = FileUtils.detectKindOfJSONFile(inFile.getAbsolutePath());
448 break;
449
450 case "PAR":
451 //Parameters for any DENOPTIM module
452 ff = FileUtils.detectKindOfParameterFile(inFile.getAbsolutePath());
453 break;
454
455 case "PARAMS":
456 //Parameters for any DENOPTIM module
457 ff = FileUtils.detectKindOfParameterFile(inFile.getAbsolutePath());
458 break;
459
460 case "TXT":
461 ff = FileUtils.detectKindOfTXTFile(inFile.getAbsolutePath());
462 break;
463
464 case "":
465 //Parameters for any DENOPTIM module
466 ff = FileUtils.detectKindOfParameterFile(inFile.getAbsolutePath());
467 break;
468
469 default:
470 throw new UndetectedFileFormatException(inFile);
471 }
472 if (ff == null)
473 {
474 throw new UndetectedFileFormatException(inFile);
475 }
476 return ff;
477 }
478
479//------------------------------------------------------------------------------
480
487 @SuppressWarnings("rawtypes")
488 public static FileFormat detectKindOfJSONFile(String fileName)
489 throws IOException
490 {
491 Gson reader = DENOPTIMgson.getReader();
492
493 FileFormat ff = null;
494
495 BufferedReader br = null;
496 try
497 {
498 br = new BufferedReader(new FileReader(fileName));
499 Object o = reader.fromJson(br,Object.class);
500 Object oneObj = null;
501 if (o instanceof ArrayList)
502 {
503 oneObj = ((ArrayList) o).get(0);
504 } else {
505 oneObj = o;
506 }
507 if (oneObj instanceof Map)
508 {
509 if (((Map)oneObj).keySet().contains("gVertices"))
510 {
511 br.close();
512 return FileFormat.GRAPHJSON;
513 } else {
514 return FileFormat.VRTXJSON;
515 }
516 }
517 }
518 catch (IOException ioe)
519 {
520 throw new IOException("Unable to read file '"+fileName + "'", ioe);
521 }
522 finally
523 {
524 try
525 {
526 if (br != null)
527 {
528 br.close();
529 br = null;
530 }
531 }
532 catch (IOException ioe)
533 {
534
535 throw new IOException("Unable to close file '" + fileName + "'",
536 ioe);
537 }
538 }
539
540 return ff;
541 }
542
543//------------------------------------------------------------------------------
544
554 public static FileFormat detectKindOfSDFFile(String fileName)
555 throws IOException
556 {
558 }
559
560//------------------------------------------------------------------------------
561
570 public static FileFormat detectKindOfParameterFile(String fileName)
571 throws IOException
572 {
574 }
575
576//------------------------------------------------------------------------------
577
588 public static FileFormat detectKindOfTXTFile(String fileName)
589 throws IOException
590 {
592 }
593
594//------------------------------------------------------------------------------
595
605 public static FileFormat detectKindFile(String fileName, FileFormat[] ffs)
606 throws IOException
607 {
608 Map<String,FileFormat> regexToMatch = new HashMap<String,FileFormat>();
609 Map<String,List<FileFormat>> regexToNotMatch =
610 new HashMap<String,List<FileFormat>>();
611 String endOfSample = null;
612 for (FileFormat ff : ffs)
613 {
614 for (String regex : ff.getDefiningRegex())
615 {
616 regexToMatch.put(regex,ff);
617 if (ff.getSampleEndRegex() != null)
618 {
619 endOfSample = ff.getSampleEndRegex();
620 }
621 }
622 for (String regex : ff.getNegatingRegex())
623 {
624 if (regexToNotMatch.containsKey(regex))
625 {
626 regexToNotMatch.get(regex).add(ff);
627 } else {
628 List<FileFormat> lst = new ArrayList<FileFormat>();
629 lst.add(ff);
630 regexToNotMatch.put(regex, lst);
631 }
632 }
633 }
634
635 Map<FileFormat,Boolean> foundDefiningRegex = new HashMap<FileFormat,Boolean>();
636 for (FileFormat f : ffs)
637 foundDefiningRegex.put(f, false);
638
639 Map<FileFormat,Boolean> foundNegatingRegex = new HashMap<FileFormat,Boolean>();
640 for (FileFormat f : ffs)
641 foundNegatingRegex.put(f, false);
642
643 String line;
644 BufferedReader br = null;
645 try
646 {
647 br = new BufferedReader(new FileReader(fileName));
648 lineReadingLoop:
649 while ((line = br.readLine()) != null)
650 {
651 if (endOfSample != null && line.matches(endOfSample))
652 {
653 break lineReadingLoop;
654 }
655
656 if ((line.trim()).length() == 0)
657 {
658 continue;
659 }
660
661 for (String key : regexToNotMatch.keySet())
662 {
663 if (line.toUpperCase().matches(key.toUpperCase()))
664 {
665 for (FileFormat ff : regexToNotMatch.get(key))
666 {
667 foundNegatingRegex.put(ff,true);
668 }
669 }
670 }
671
672 for (String keyRoot : regexToMatch.keySet())
673 {
674 if (line.toUpperCase().matches(keyRoot.toUpperCase()))
675 {
676 foundDefiningRegex.put(regexToMatch.get(keyRoot), true);
677 }
678 }
679 }
680 }
681 catch (IOException ioe)
682 {
683 throw new IOException("Unable to read file '"+fileName + "'", ioe);
684 }
685 finally
686 {
687 try
688 {
689 if (br != null)
690 {
691 br.close();
692 br = null;
693 }
694 }
695 catch (IOException ioe)
696 {
697
698 throw new IOException("Unable to close file '" + fileName + "'",
699 ioe);
700 }
701 }
702
703 FileFormat result = null;
704 for (FileFormat ff : ffs)
705 {
706 if (foundDefiningRegex.get(ff) && !foundNegatingRegex.get(ff))
707 {
708 result = ff;
709 break;
710 }
711 }
712 return result;
713 }
714
715//------------------------------------------------------------------------------
716
729 public static File getAvailableFileName(File parent, String baseName)
730 throws DENOPTIMException
731 {
732 File newName = null;
733 if (!parent.exists())
734 {
735 if (!createDirectory(parent.getAbsolutePath()))
736 {
737 throw new DENOPTIMException("Cannot make folder '"+parent+"'");
738 }
739 }
740 FileFilter fileFilter = new WildcardFileFilter(baseName+"*");
741 File[] cands = parent.listFiles(fileFilter);
742 int i=0;
743 boolean goon = true;
744 while (goon)
745 {
746 i++;
747 int idx = i + cands.length;
748 newName = new File(parent + DenoptimIO.FS + baseName + "_" + idx);
749 if (!newName.exists())
750 {
751 goon = false;
752 break;
753 }
754 }
755 return newName;
756 }
757
758//------------------------------------------------------------------------------
759
768 public static void mergeIntoOneFile(String destinationPathname,
769 List<String> sourcePathnames) throws IOException
770 {
771 try(OutputStream out = Files.newOutputStream(
772 Paths.get(destinationPathname),
773 StandardOpenOption.CREATE,
774 StandardOpenOption.WRITE))
775 {
776 for (String sourcePathname : sourcePathnames) {
777 Files.copy(Paths.get(sourcePathname), out);
778 }
779 }
780 }
781
782//------------------------------------------------------------------------------
783
784}
General set of constants used in DENOPTIM.
static final File RECENTFILESLIST
List of recent files.
static final String EOL
new line character
static final String GAGENDIRNAMEROOT
Prefix for generation folders.
static final String FSEIDXNAMEROOT
Prefix for graph indexing files.
static void deleteFilesContaining(String path, String pattern)
Delete all files with pathname containing a given string.
Definition: FileUtils.java:289
static boolean checkExists(String fileName)
Definition: FileUtils.java:241
static File getAvailableFileName(File parent, String baseName)
Define a filename that can be used, i.e., is still available, because no other file with the same pat...
Definition: FileUtils.java:729
static FileFormat detectKindOfTXTFile(String fileName)
Looks into a text file and tries to understand if the file is a known text file.
Definition: FileUtils.java:588
static int countLinesInFile(String fileName)
Count the number of lines in the file.
Definition: FileUtils.java:312
static void mergeIntoOneFile(String destinationPathname, List< String > sourcePathnames)
Copies the content of all the files specified in the list of sources and places it into the destinati...
Definition: FileUtils.java:768
static boolean createDirectory(String fileName)
Creates a directory.
Definition: FileUtils.java:231
static boolean isLineInTxtFile(String query, File file, boolean add)
Search in a file for a line matching the given string query.
Definition: FileUtils.java:132
static FileFormat detectKindOfJSONFile(String fileName)
Detect the content of a json file.
Definition: FileUtils.java:488
static FileFormat detectKindOfSDFFile(String fileName)
Looks into a text file and tries to understand if the file is a collection of parameters for any spec...
Definition: FileUtils.java:554
static boolean canWriteAndReadTo(String pathName)
Check whether we can write and read to a given pathname.
Definition: FileUtils.java:185
static void createZipFile(String zipOutputFileName, String[] filesToZip)
Creates a zip file.
Definition: FileUtils.java:349
static FileFormat detectKindFile(String fileName, FileFormat[] ffs)
Looks into a text file and tries to understand what format it is among the given formats.
Definition: FileUtils.java:605
static FileFormat detectFileFormat(File inFile)
Inspects a file/folder and tries to detect if there is one of the data sources that is recognized by ...
Definition: FileUtils.java:399
static void deleteFile(String fileName)
Delete the file.
Definition: FileUtils.java:256
static String getTempFolder()
Looks for a writable location where to put temporary files and returns an absolute pathname to the fo...
Definition: FileUtils.java:204
static FileFormat detectKindOfParameterFile(String fileName)
Looks into a text file and tries to understand if the file is a collection of parameters for any spec...
Definition: FileUtils.java:570
static void addToRecentFiles(File file, FileFormat ff)
Appends an entry to the list of recent files.
Definition: FileUtils.java:81
static void addToRecentFiles(String fileName, FileFormat ff)
Appends an entry to the list of recent files.
Definition: FileUtils.java:67
Exception thrown when the format of a file is not recognized.
Utility methods for input/output.
static Map< File, FileFormat > readRecentFilesMap()
Reads the file defined in DENOPTIMConstants#RECENTFILESLIST and makes a map that contains the pathnam...
static final String NL
Newline character from system.
static ArrayList< String > readList(String fileName)
Read list of data as text.
static void writeData(String fileName, String data, boolean append)
Write text-like data file.
static final String FS
File separator from system.
Class for de/serializing DENOPTIM graphs from/to JSON format.
Logger class for DENOPTIM.
static final Logger appLogger
File formats identified by DENOPTIM.
Definition: FileFormat.java:32
static FileFormat[] getParameterFormats()
Returns the collection of file formats with input parameters.
static FileFormat[] getSDFFormats()
Returns the collection of file formats using SDF syntax.
static FileFormat[] getTXTFormats()
Returns the collection of file formats restricted to TXT files (excluded parameter files)