1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - Raw Material Software Limited
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
10    The code included in this file is provided under the terms of the ISC license
11    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12    To use, copy, modify, and/or distribute this software for any purpose with or
13    without fee is hereby granted provided that the above copyright notice and
14    this permission notice appear in all copies.
15 
16    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18    DISCLAIMED.
19 
20   ==============================================================================
21 */
22 
23 #if ! DOXYGEN && (JUCE_MAC || JUCE_IOS)
24  #if __LP64__
25   using OSType = unsigned int;
26  #else
27   using OSType = unsigned long;
28  #endif
29 #endif
30 
31 namespace juce
32 {
33 
34 //==============================================================================
35 /**
36     Represents a local file or directory.
37 
38     This class encapsulates the absolute pathname of a file or directory, and
39     has methods for finding out about the file and changing its properties.
40 
41     To read or write to the file, there are methods for returning an input or
42     output stream.
43 
44     @see FileInputStream, FileOutputStream
45 
46     @tags{Core}
47 */
48 class JUCE_API  File final
49 {
50 public:
51     //==============================================================================
52     /** Creates an (invalid) file object.
53 
54         The file is initially set to an empty path, so getFullPathName() will return
55         an empty string.
56 
57         You can use its operator= method to point it at a proper file.
58     */
59     File() = default;
60 
61     /** Creates a file from an absolute path.
62 
63         If the path supplied is a relative path, it is taken to be relative
64         to the current working directory (see File::getCurrentWorkingDirectory()),
65         but this isn't a recommended way of creating a file, because you
66         never know what the CWD is going to be.
67 
68         On the Mac/Linux, the path can include "~" notation for referring to
69         user home directories.
70     */
71     File (const String& absolutePath);
72 
73     /** Creates a copy of another file object. */
74     File (const File&);
75 
76     /** Destructor. */
77     ~File() = default;
78 
79     /** Sets the file based on an absolute pathname.
80 
81         If the path supplied is a relative path, it is taken to be relative
82         to the current working directory (see File::getCurrentWorkingDirectory()),
83         but this isn't a recommended way of creating a file, because you
84         never know what the CWD is going to be.
85 
86         On the Mac/Linux, the path can include "~" notation for referring to
87         user home directories.
88     */
89     File& operator= (const String& newAbsolutePath);
90 
91     /** Copies from another file object. */
92     File& operator= (const File& otherFile);
93 
94     /** Move constructor */
95     File (File&&) noexcept;
96 
97     /** Move assignment operator */
98     File& operator= (File&&) noexcept;
99 
100     //==============================================================================
101     /** Checks whether the file actually exists.
102 
103         @returns    true if the file exists, either as a file or a directory.
104         @see existsAsFile, isDirectory
105     */
106     bool exists() const;
107 
108     /** Checks whether the file exists and is a file rather than a directory.
109 
110         @returns    true only if this is a real file, false if it's a directory
111                     or doesn't exist
112         @see exists, isDirectory
113     */
114     bool existsAsFile() const;
115 
116     /** Checks whether the file is a directory that exists.
117 
118         @returns    true only if the file is a directory which actually exists, so
119                     false if it's a file or doesn't exist at all
120         @see exists, existsAsFile
121     */
122     bool isDirectory() const;
123 
124     /** Checks whether the path of this file represents the root of a file system,
125         irrespective of its existence.
126 
127         This will return true for "C:", "D:", etc on Windows and "/" on other
128         platforms.
129     */
130     bool isRoot() const;
131 
132     /** Returns the size of the file in bytes.
133 
134         @returns    the number of bytes in the file, or 0 if it doesn't exist.
135     */
136     int64 getSize() const;
137 
138     /** Utility function to convert a file size in bytes to a neat string description.
139 
140         So for example 100 would return "100 bytes", 2000 would return "2 KB",
141         2000000 would produce "2 MB", etc.
142     */
143     static String descriptionOfSizeInBytes (int64 bytes);
144 
145     //==============================================================================
146     /** Returns the complete, absolute path of this file.
147 
148         This includes the filename and all its parent folders. On Windows it'll
149         also include the drive letter prefix; on Mac or Linux it'll be a complete
150         path starting from the root folder.
151 
152         If you just want the file's name, you should use getFileName() or
153         getFileNameWithoutExtension().
154 
155         @see getFileName, getRelativePathFrom
156     */
getFullPathName()157     const String& getFullPathName() const noexcept          { return fullPath; }
158 
159     /** Returns the last section of the pathname.
160 
161         Returns just the final part of the path - e.g. if the whole path
162         is "/moose/fish/foo.txt" this will return "foo.txt".
163 
164         For a directory, it returns the final part of the path - e.g. for the
165         directory "/moose/fish" it'll return "fish".
166 
167         If the filename begins with a dot, it'll return the whole filename, e.g. for
168         "/moose/.fish", it'll return ".fish"
169 
170         @see getFullPathName, getFileNameWithoutExtension
171     */
172     String getFileName() const;
173 
174     /** Creates a relative path that refers to a file relatively to a given directory.
175 
176         e.g. File ("/moose/foo.txt").getRelativePathFrom (File ("/moose/fish/haddock"))
177              would return "../../foo.txt".
178 
179         If it's not possible to navigate from one file to the other, an absolute
180         path is returned. If the paths are invalid, an empty string may also be
181         returned.
182 
183         @param directoryToBeRelativeTo  the directory which the resultant string will
184                                         be relative to. If this is actually a file rather than
185                                         a directory, its parent directory will be used instead.
186                                         If it doesn't exist, it's assumed to be a directory.
187         @see getChildFile, isAbsolutePath
188     */
189     String getRelativePathFrom (const File& directoryToBeRelativeTo) const;
190 
191     //==============================================================================
192     /** Returns the file's extension.
193 
194         Returns the file extension of this file, also including the dot.
195 
196         e.g. "/moose/fish/foo.txt" would return ".txt"
197 
198         @see hasFileExtension, withFileExtension, getFileNameWithoutExtension
199     */
200     String getFileExtension() const;
201 
202     /** Checks whether the file has a given extension.
203 
204         @param extensionToTest  the extension to look for - it doesn't matter whether or
205                                 not this string has a dot at the start, so ".wav" and "wav"
206                                 will have the same effect. To compare with multiple extensions, this
207                                 parameter can contain multiple strings, separated by semi-colons -
208                                 so, for example: hasFileExtension (".jpeg;png;gif") would return
209                                 true if the file has any of those three extensions.
210 
211         @see getFileExtension, withFileExtension, getFileNameWithoutExtension
212     */
213     bool hasFileExtension (StringRef extensionToTest) const;
214 
215     /** Returns a version of this file with a different file extension.
216 
217         e.g. File ("/moose/fish/foo.txt").withFileExtension ("html") returns "/moose/fish/foo.html"
218 
219         @param newExtension     the new extension, either with or without a dot at the start (this
220                                 doesn't make any difference). To get remove a file's extension altogether,
221                                 pass an empty string into this function.
222 
223         @see getFileName, getFileExtension, hasFileExtension, getFileNameWithoutExtension
224     */
225     File withFileExtension (StringRef newExtension) const;
226 
227     /** Returns the last part of the filename, without its file extension.
228 
229         e.g. for "/moose/fish/foo.txt" this will return "foo".
230 
231         @see getFileName, getFileExtension, hasFileExtension, withFileExtension
232     */
233     String getFileNameWithoutExtension() const;
234 
235     //==============================================================================
236     /** Returns a 32-bit hash-code that identifies this file.
237 
238         This is based on the filename. Obviously it's possible, although unlikely, that
239         two files will have the same hash-code.
240     */
241     int hashCode() const;
242 
243     /** Returns a 64-bit hash-code that identifies this file.
244 
245         This is based on the filename. Obviously it's possible, although unlikely, that
246         two files will have the same hash-code.
247     */
248     int64 hashCode64() const;
249 
250     //==============================================================================
251     /** Returns a file that represents a relative (or absolute) sub-path of the current one.
252 
253         This will find a child file or directory of the current object.
254 
255         e.g.
256             File ("/moose/fish").getChildFile ("foo.txt") will produce "/moose/fish/foo.txt".
257             File ("/moose/fish").getChildFile ("haddock/foo.txt") will produce "/moose/fish/haddock/foo.txt".
258             File ("/moose/fish").getChildFile ("../foo.txt") will produce "/moose/foo.txt".
259 
260         If the string is actually an absolute path, it will be treated as such, e.g.
261             File ("/moose/fish").getChildFile ("/foo.txt") will produce "/foo.txt"
262 
263         @see getSiblingFile, getParentDirectory, getRelativePathFrom, isAChildOf
264     */
265     File getChildFile (StringRef relativeOrAbsolutePath) const;
266 
267     /** Returns a file which is in the same directory as this one.
268 
269         This is equivalent to getParentDirectory().getChildFile (name).
270 
271         @see getChildFile, getParentDirectory
272     */
273     File getSiblingFile (StringRef siblingFileName) const;
274 
275     //==============================================================================
276     /** Returns the directory that contains this file or directory.
277 
278         e.g. for "/moose/fish/foo.txt" this will return "/moose/fish".
279 
280         If you are already at the root directory ("/" or "C:") then this method will
281         return the root directory.
282     */
283     File getParentDirectory() const;
284 
285     /** Checks whether a file is somewhere inside a directory.
286 
287         Returns true if this file is somewhere inside a subdirectory of the directory
288         that is passed in. Neither file actually has to exist, because the function
289         just checks the paths for similarities.
290 
291         e.g. File ("/moose/fish/foo.txt").isAChildOf ("/moose") is true.
292              File ("/moose/fish/foo.txt").isAChildOf ("/moose/fish") is also true.
293     */
294     bool isAChildOf (const File& potentialParentDirectory) const;
295 
296     //==============================================================================
297     /** Chooses a filename relative to this one that doesn't already exist.
298 
299         If this file is a directory, this will return a child file of this
300         directory that doesn't exist, by adding numbers to a prefix and suffix until
301         it finds one that isn't already there.
302 
303         If the prefix + the suffix doesn't exist, it won't bother adding a number.
304 
305         e.g. File ("/moose/fish").getNonexistentChildFile ("foo", ".txt", true) might
306              return "/moose/fish/foo(2).txt" if there's already a file called "foo.txt".
307 
308         @param prefix                   the string to use for the filename before the number
309         @param suffix                   the string to add to the filename after the number
310         @param putNumbersInBrackets     if true, this will create filenames in the
311                                         format "prefix(number)suffix", if false, it will leave the
312                                         brackets out.
313     */
314     File getNonexistentChildFile (const String& prefix,
315                                   const String& suffix,
316                                   bool putNumbersInBrackets = true) const;
317 
318     /** Chooses a filename for a sibling file to this one that doesn't already exist.
319 
320         If this file doesn't exist, this will just return itself, otherwise it
321         will return an appropriate sibling that doesn't exist, e.g. if a file
322         "/moose/fish/foo.txt" exists, this might return "/moose/fish/foo(2).txt".
323 
324         @param putNumbersInBrackets     whether to add brackets around the numbers that
325                                         get appended to the new filename.
326     */
327     File getNonexistentSibling (bool putNumbersInBrackets = true) const;
328 
329     //==============================================================================
330     /** Compares the pathnames for two files. */
331     bool operator== (const File&) const;
332     /** Compares the pathnames for two files. */
333     bool operator!= (const File&) const;
334     /** Compares the pathnames for two files. */
335     bool operator< (const File&) const;
336     /** Compares the pathnames for two files. */
337     bool operator> (const File&) const;
338 
339     //==============================================================================
340     /** Checks whether a file can be created or written to.
341 
342         @returns    true if it's possible to create and write to this file. If the file
343                     doesn't already exist, this will check its parent directory to
344                     see if writing is allowed.
345         @see setReadOnly
346     */
347     bool hasWriteAccess() const;
348 
349     /** Changes the write-permission of a file or directory.
350 
351         @param shouldBeReadOnly     whether to add or remove write-permission
352         @param applyRecursively     if the file is a directory and this is true, it will
353                                     recurse through all the subfolders changing the permissions
354                                     of all files
355         @returns    true if it manages to change the file's permissions.
356         @see hasWriteAccess
357     */
358     bool setReadOnly (bool shouldBeReadOnly,
359                       bool applyRecursively = false) const;
360 
361     /** Changes the execute-permissions of a file.
362 
363         @param shouldBeExecutable   whether to add or remove execute-permission
364         @returns    true if it manages to change the file's permissions.
365     */
366     bool setExecutePermission (bool shouldBeExecutable) const;
367 
368     /** Returns true if this file is a hidden or system file.
369         The criteria for deciding whether a file is hidden are platform-dependent.
370     */
371     bool isHidden() const;
372 
373     /** Returns a unique identifier for the file, if one is available.
374 
375         Depending on the OS and file-system, this may be a unix inode number or
376         a win32 file identifier, or 0 if it fails to find one. The number will
377         be unique on the filesystem, but not globally.
378     */
379     uint64 getFileIdentifier() const;
380 
381     //==============================================================================
382     /** Returns the last modification time of this file.
383 
384         @returns    the time, or an invalid time if the file doesn't exist.
385         @see setLastModificationTime, getLastAccessTime, getCreationTime
386     */
387     Time getLastModificationTime() const;
388 
389     /** Returns the last time this file was accessed.
390 
391         @returns    the time, or an invalid time if the file doesn't exist.
392         @see setLastAccessTime, getLastModificationTime, getCreationTime
393     */
394     Time getLastAccessTime() const;
395 
396     /** Returns the time that this file was created.
397 
398         @returns    the time, or an invalid time if the file doesn't exist.
399         @see getLastModificationTime, getLastAccessTime
400     */
401     Time getCreationTime() const;
402 
403     /** Changes the modification time for this file.
404 
405         @param newTime  the time to apply to the file
406         @returns true if it manages to change the file's time.
407         @see getLastModificationTime, setLastAccessTime, setCreationTime
408     */
409     bool setLastModificationTime (Time newTime) const;
410 
411     /** Changes the last-access time for this file.
412 
413         @param newTime  the time to apply to the file
414         @returns true if it manages to change the file's time.
415         @see getLastAccessTime, setLastModificationTime, setCreationTime
416     */
417     bool setLastAccessTime (Time newTime) const;
418 
419     /** Changes the creation date for this file.
420 
421         @param newTime  the time to apply to the file
422         @returns true if it manages to change the file's time.
423         @see getCreationTime, setLastModificationTime, setLastAccessTime
424     */
425     bool setCreationTime (Time newTime) const;
426 
427     /** If possible, this will try to create a version string for the given file.
428 
429         The OS may be able to look at the file and give a version for it - e.g. with
430         executables, bundles, dlls, etc. If no version is available, this will
431         return an empty string.
432     */
433     String getVersion() const;
434 
435     //==============================================================================
436     /** Creates an empty file if it doesn't already exist.
437 
438         If the file that this object refers to doesn't exist, this will create a file
439         of zero size.
440 
441         If it already exists or is a directory, this method will do nothing.
442 
443         If the parent directories of the File do not exist then this method will
444         recursively create the parent directories.
445 
446         @returns    a result to indicate whether the file was created successfully,
447                     or an error message if it failed.
448         @see createDirectory
449     */
450     Result create() const;
451 
452     /** Creates a new directory for this filename.
453 
454         This will try to create the file as a directory, and will also create
455         any parent directories it needs in order to complete the operation.
456 
457         @returns    a result to indicate whether the directory was created successfully, or
458                     an error message if it failed.
459         @see create
460     */
461     Result createDirectory() const;
462 
463     /** Deletes a file.
464 
465         If this file is actually a directory, it may not be deleted correctly if it
466         contains files. See deleteRecursively() as a better way of deleting directories.
467 
468         If this file is a symlink, then the symlink will be deleted and not the target
469         of the symlink.
470 
471         @returns    true if the file has been successfully deleted (or if it didn't exist to
472                     begin with).
473         @see deleteRecursively
474     */
475     bool deleteFile() const;
476 
477     /** Deletes a file or directory and all its subdirectories.
478 
479         If this file is a directory, this will try to delete it and all its subfolders. If
480         it's just a file, it will just try to delete the file.
481 
482 
483         @param followSymlinks If true, then any symlink pointing to a directory will also
484                               recursively delete the contents of that directory
485         @returns              true if the file and all its subfolders have been successfully
486                               deleted (or if it didn't exist to begin with).
487         @see deleteFile
488     */
489     bool deleteRecursively (bool followSymlinks = false) const;
490 
491     /** Moves this file or folder to the trash.
492 
493         @returns true if the operation succeeded. It could fail if the trash is full, or
494                  if the file is write-protected, so you should check the return value
495                  and act appropriately.
496     */
497     bool moveToTrash() const;
498 
499     /** Moves or renames a file.
500 
501         Tries to move a file to a different location.
502         If the target file already exists, this will attempt to delete it first, and
503         will fail if this can't be done.
504 
505         Note that the destination file isn't the directory to put it in, it's the actual
506         filename that you want the new file to have.
507 
508         Also note that on some OSes (e.g. Windows), moving files between different
509         volumes may not be possible.
510 
511         @returns    true if the operation succeeds
512     */
513     bool moveFileTo (const File& targetLocation) const;
514 
515     /** Copies a file.
516 
517         Tries to copy a file to a different location.
518         If the target file already exists, this will attempt to delete it first, and
519         will fail if this can't be done.
520 
521         @returns    true if the operation succeeds
522     */
523     bool copyFileTo (const File& targetLocation) const;
524 
525     /** Replaces a file.
526 
527         Replace the file in the given location, assuming the replaced files identity.
528         Depending on the file system this will preserve file attributes such as
529         creation date, short file name, etc.
530 
531         If replacement succeeds the original file is deleted.
532 
533         @returns    true if the operation succeeds
534     */
535     bool replaceFileIn (const File& targetLocation) const;
536 
537     /** Copies a directory.
538 
539         Tries to copy an entire directory, recursively.
540 
541         If this file isn't a directory or if any target files can't be created, this
542         will return false.
543 
544         @param newDirectory    the directory that this one should be copied to. Note that this
545                                is the name of the actual directory to create, not the directory
546                                into which the new one should be placed, so there must be enough
547                                write privileges to create it if it doesn't exist. Any files inside
548                                it will be overwritten by similarly named ones that are copied.
549     */
550     bool copyDirectoryTo (const File& newDirectory) const;
551 
552     //==============================================================================
553     /** Used in file searching, to specify whether to return files, directories, or both.
554     */
555     enum TypesOfFileToFind
556     {
557         findDirectories             = 1,    /**< Use this flag to indicate that you want to find directories. */
558         findFiles                   = 2,    /**< Use this flag to indicate that you want to find files. */
559         findFilesAndDirectories     = 3,    /**< Use this flag to indicate that you want to find both files and directories. */
560         ignoreHiddenFiles           = 4     /**< Add this flag to avoid returning any hidden files in the results. */
561     };
562 
563     /** Searches this directory for files matching a wildcard pattern.
564 
565         Assuming that this file is a directory, this method will search it
566         for either files or subdirectories whose names match a filename pattern.
567         Note that the order in which files are returned is completely undefined!
568 
569         @param whatToLookFor            a value from the TypesOfFileToFind enum, specifying whether to
570                                         return files, directories, or both. If the ignoreHiddenFiles flag
571                                         is also added to this value, hidden files won't be returned
572         @param searchRecursively        if true, all subdirectories will be recursed into to do
573                                         an exhaustive search
574         @param wildCardPattern          the filename pattern to search for, e.g. "*.txt"
575         @returns                        the set of files that were found
576 
577         @see getNumberOfChildFiles, RangedDirectoryIterator
578     */
579     Array<File> findChildFiles (int whatToLookFor,
580                                 bool searchRecursively,
581                                 const String& wildCardPattern = "*") const;
582 
583     /** Searches inside a directory for files matching a wildcard pattern.
584         Note that there's a newer, better version of this method which returns the results
585         array, and in almost all cases, you should use that one instead! This one is kept around
586         mainly for legacy code to use.
587     */
588     int findChildFiles (Array<File>& results, int whatToLookFor,
589                         bool searchRecursively, const String& wildCardPattern = "*") const;
590 
591     /** Searches inside a directory and counts how many files match a wildcard pattern.
592 
593         Assuming that this file is a directory, this method will search it
594         for either files or subdirectories whose names match a filename pattern,
595         and will return the number of matches found.
596 
597         This isn't a recursive call, and will only search this directory, not
598         its children.
599 
600         @param whatToLookFor    a value from the TypesOfFileToFind enum, specifying whether to
601                                 count files, directories, or both. If the ignoreHiddenFiles flag
602                                 is also added to this value, hidden files won't be counted
603         @param wildCardPattern  the filename pattern to search for, e.g. "*.txt"
604         @returns                the number of matches found
605 
606         @see findChildFiles, RangedDirectoryIterator
607     */
608     int getNumberOfChildFiles (int whatToLookFor,
609                                const String& wildCardPattern = "*") const;
610 
611     /** Returns true if this file is a directory that contains one or more subdirectories.
612         @see isDirectory, findChildFiles
613     */
614     bool containsSubDirectories() const;
615 
616     //==============================================================================
617     /** Creates a stream to read from this file.
618 
619         Note that this is an old method, and actually it's usually best to avoid it and
620         instead use an RAII pattern with an FileInputStream directly, e.g.
621         @code
622         FileInputStream input (fileToOpen);
623 
624         if (input.openedOk())
625         {
626             input.read (etc...
627         }
628         @endcode
629 
630         @returns    a stream that will read from this file (initially positioned at the
631                     start of the file), or nullptr if the file can't be opened for some reason
632         @see createOutputStream, loadFileAsData
633     */
634     std::unique_ptr<FileInputStream> createInputStream() const;
635 
636     /** Creates a stream to write to this file.
637 
638         Note that this is an old method, and actually it's usually best to avoid it and
639         instead use an RAII pattern with an FileOutputStream directly, e.g.
640         @code
641         FileOutputStream output (fileToOpen);
642 
643         if (output.openedOk())
644         {
645             output.read etc...
646         }
647         @endcode
648 
649         If the file exists, the stream that is returned will be positioned ready for
650         writing at the end of the file. If you want to write to the start of the file,
651         replacing the existing content, then you can do the following:
652         @code
653         FileOutputStream output (fileToOverwrite);
654 
655         if (output.openedOk())
656         {
657             output.setPosition (0);
658             output.truncate();
659             ...
660         }
661         @endcode
662 
663         @returns    a stream that will write to this file (initially positioned at the
664                     end of the file), or nullptr if the file can't be opened for some reason
665         @see createInputStream, appendData, appendText
666     */
667     std::unique_ptr<FileOutputStream> createOutputStream (size_t bufferSize = 0x8000) const;
668 
669     //==============================================================================
670     /** Loads a file's contents into memory as a block of binary data.
671 
672         Of course, trying to load a very large file into memory will blow up, so
673         it's better to check first.
674 
675         @param result   the data block to which the file's contents should be appended - note
676                         that if the memory block might already contain some data, you
677                         might want to clear it first
678         @returns        true if the file could all be read into memory
679     */
680     bool loadFileAsData (MemoryBlock& result) const;
681 
682     /** Reads a file into memory as a string.
683 
684         Attempts to load the entire file as a zero-terminated string.
685 
686         This makes use of InputStream::readEntireStreamAsString, which can
687         read either UTF-16 or UTF-8 file formats.
688     */
689     String loadFileAsString() const;
690 
691     /** Reads the contents of this file as text and splits it into lines, which are
692         appended to the given StringArray.
693     */
694     void readLines (StringArray& destLines) const;
695 
696     //==============================================================================
697     /** Appends a block of binary data to the end of the file.
698 
699         This will try to write the given buffer to the end of the file.
700 
701         @returns false if it can't write to the file for some reason
702     */
703     bool appendData (const void* dataToAppend,
704                      size_t numberOfBytes) const;
705 
706     /** Replaces this file's contents with a given block of data.
707 
708         This will delete the file and replace it with the given data.
709 
710         A nice feature of this method is that it's safe - instead of deleting
711         the file first and then re-writing it, it creates a new temporary file,
712         writes the data to that, and then moves the new file to replace the existing
713         file. This means that if the power gets pulled out or something crashes,
714         you're a lot less likely to end up with a corrupted or unfinished file..
715 
716         Returns true if the operation succeeds, or false if it fails.
717 
718         @see appendText
719     */
720     bool replaceWithData (const void* dataToWrite,
721                           size_t numberOfBytes) const;
722 
723     /** Appends a string to the end of the file.
724 
725         This will try to append a text string to the file, as either 16-bit unicode
726         or 8-bit characters in the default system encoding.
727 
728         It can also write the 'ff fe' unicode header bytes before the text to indicate
729         the endianness of the file.
730 
731         If lineEndings is nullptr, then line endings in the text won't be modified. If you
732         pass "\\n" or "\\r\\n" then this function will replace any existing line feeds.
733 
734         @see replaceWithText
735     */
736     bool appendText (const String& textToAppend,
737                      bool asUnicode = false,
738                      bool writeUnicodeHeaderBytes = false,
739                      const char* lineEndings = "\r\n") const;
740 
741     /** Replaces this file's contents with a given text string.
742 
743         This will delete the file and replace it with the given text.
744 
745         A nice feature of this method is that it's safe - instead of deleting
746         the file first and then re-writing it, it creates a new temporary file,
747         writes the text to that, and then moves the new file to replace the existing
748         file. This means that if the power gets pulled out or something crashes,
749         you're a lot less likely to end up with an empty file..
750 
751         For an explanation of the parameters here, see the appendText() method.
752 
753         Returns true if the operation succeeds, or false if it fails.
754 
755         @see appendText
756     */
757     bool replaceWithText (const String& textToWrite,
758                           bool asUnicode = false,
759                           bool writeUnicodeHeaderBytes = false,
760                           const char* lineEndings = "\r\n") const;
761 
762     /** Attempts to scan the contents of this file and compare it to another file, returning
763         true if this is possible and they match byte-for-byte.
764     */
765     bool hasIdenticalContentTo (const File& other) const;
766 
767     //==============================================================================
768     /** Creates a set of files to represent each file root.
769 
770         e.g. on Windows this will create files for "c:\", "d:\" etc according
771         to which ones are available. On the Mac/Linux, this will probably
772         just add a single entry for "/".
773     */
774     static void findFileSystemRoots (Array<File>& results);
775 
776     /** Finds the name of the drive on which this file lives.
777         @returns the volume label of the drive, or an empty string if this isn't possible
778     */
779     String getVolumeLabel() const;
780 
781     /** Returns the serial number of the volume on which this file lives.
782         @returns the serial number, or zero if there's a problem doing this
783     */
784     int getVolumeSerialNumber() const;
785 
786     /** Returns the number of bytes free on the drive that this file lives on.
787 
788         @returns the number of bytes free, or 0 if there's a problem finding this out
789         @see getVolumeTotalSize
790     */
791     int64 getBytesFreeOnVolume() const;
792 
793     /** Returns the total size of the drive that contains this file.
794 
795         @returns the total number of bytes that the volume can hold
796         @see getBytesFreeOnVolume
797     */
798     int64 getVolumeTotalSize() const;
799 
800     /** Returns true if this file is on a CD or DVD drive. */
801     bool isOnCDRomDrive() const;
802 
803     /** Returns true if this file is on a hard disk.
804 
805         This will fail if it's a network drive, but will still be true for
806         removable hard-disks.
807     */
808     bool isOnHardDisk() const;
809 
810     /** Returns true if this file is on a removable disk drive.
811 
812         This might be a usb-drive, a CD-rom, or maybe a network drive.
813     */
814     bool isOnRemovableDrive() const;
815 
816     //==============================================================================
817     /** Launches the file as a process.
818 
819         - if the file is executable, this will run it.
820 
821         - if it's a document of some kind, it will launch the document with its
822         default viewer application.
823 
824         - if it's a folder, it will be opened in Explorer, Finder, or equivalent.
825 
826         @see revealToUser
827     */
828     bool startAsProcess (const String& parameters = String()) const;
829 
830     /** Opens Finder, Explorer, or whatever the OS uses, to show the user this file's location.
831         @see startAsProcess
832     */
833     void revealToUser() const;
834 
835     //==============================================================================
836     /** A set of types of location that can be passed to the getSpecialLocation() method.
837     */
838     enum SpecialLocationType
839     {
840         /** The user's home folder. This is the same as using File ("~"). */
841         userHomeDirectory,
842 
843         /** The user's default documents folder. On Windows, this might be the user's
844             "My Documents" folder. On the Mac it'll be their "Documents" folder. Linux
845             doesn't tend to have one of these, so it might just return their home folder.
846         */
847         userDocumentsDirectory,
848 
849         /** The folder that contains the user's desktop objects. */
850         userDesktopDirectory,
851 
852         /** The most likely place where a user might store their music files. */
853         userMusicDirectory,
854 
855         /** The most likely place where a user might store their movie files. */
856         userMoviesDirectory,
857 
858         /** The most likely place where a user might store their picture files. */
859         userPicturesDirectory,
860 
861         /** The folder in which applications store their persistent user-specific settings.
862             On Windows, this might be "\Documents and Settings\username\Application Data".
863             On the Mac, it might be "~/Library". If you're going to store your settings in here,
864             always create your own sub-folder to put them in, to avoid making a mess.
865             On GNU/Linux it is "~/.config".
866         */
867         userApplicationDataDirectory,
868 
869         /** An equivalent of the userApplicationDataDirectory folder that is shared by all users
870             of the computer, rather than just the current user.
871 
872             On the Mac it'll be "/Library", on Windows, it could be something like
873             "\Documents and Settings\All Users\Application Data".
874 
875             On GNU/Linux it is "/opt".
876 
877             Depending on the setup, this folder may be read-only.
878         */
879         commonApplicationDataDirectory,
880 
881         /** A place to put documents which are shared by all users of the machine.
882             On Windows this may be somewhere like "C:\Users\Public\Documents", on OSX it
883             will be something like "/Users/Shared". Other OSes may have no such concept
884             though, so be careful.
885         */
886         commonDocumentsDirectory,
887 
888         /** The folder that should be used for temporary files.
889             Always delete them when you're finished, to keep the user's computer tidy!
890         */
891         tempDirectory,
892 
893         /** Returns this application's executable file.
894 
895             If running as a plug-in or DLL, this will (where possible) be the DLL rather than the
896             host app.
897 
898             On the mac this will return the unix binary, not the package folder - see
899             currentApplicationFile for that.
900 
901             See also invokedExecutableFile, which is similar, but if the exe was launched from a
902             file link, invokedExecutableFile will return the name of the link.
903         */
904         currentExecutableFile,
905 
906         /** Returns this application's location.
907 
908             If running as a plug-in or DLL, this will (where possible) be the DLL rather than the
909             host app.
910 
911             On the mac this will return the package folder (if it's in one), not the unix binary
912             that's inside it - compare with currentExecutableFile.
913         */
914         currentApplicationFile,
915 
916         /** Returns the file that was invoked to launch this executable.
917             This may differ from currentExecutableFile if the app was started from e.g. a link - this
918             will return the name of the link that was used, whereas currentExecutableFile will return
919             the actual location of the target executable.
920         */
921         invokedExecutableFile,
922 
923         /** In a plugin, this will return the path of the host executable. */
924         hostApplicationPath,
925 
926        #if JUCE_WINDOWS || DOXYGEN
927         /** On a Windows machine, returns the location of the Windows/System32 folder. */
928         windowsSystemDirectory,
929        #endif
930 
931         /** The directory in which applications normally get installed.
932             So on windows, this would be something like "C:\Program Files", on the
933             Mac "/Applications", or "/usr" on linux.
934         */
935         globalApplicationsDirectory,
936 
937        #if JUCE_WINDOWS || DOXYGEN
938         /** On a Windows machine, returns the directory in which 32 bit applications
939             normally get installed. On a 64 bit machine this would be something like
940             "C:\Program Files (x86)", whereas for 32 bit machines this would match
941             globalApplicationsDirectory and be something like "C:\Program Files".
942 
943             @see globalApplicationsDirectory
944         */
945         globalApplicationsDirectoryX86
946        #endif
947     };
948 
949     /** Finds the location of a special type of file or directory, such as a home folder or
950         documents folder.
951 
952         @see SpecialLocationType
953     */
954     static File JUCE_CALLTYPE getSpecialLocation (const SpecialLocationType type);
955 
956     //==============================================================================
957     /** Returns a temporary file in the system's temp directory.
958         This will try to return the name of a non-existent temp file.
959         To get the temp folder, you can use getSpecialLocation (File::tempDirectory).
960     */
961     static File createTempFile (StringRef fileNameEnding);
962 
963     //==============================================================================
964     /** Returns the current working directory.
965         @see setAsCurrentWorkingDirectory
966     */
967     static File getCurrentWorkingDirectory();
968 
969     /** Sets the current working directory to be this file.
970 
971         For this to work the file must point to a valid directory.
972 
973         @returns true if the current directory has been changed.
974         @see getCurrentWorkingDirectory
975     */
976     bool setAsCurrentWorkingDirectory() const;
977 
978     //==============================================================================
979     /** The system-specific file separator character.
980         On Windows, this will be '\', on Mac/Linux, it'll be '/'
981     */
982     static juce_wchar getSeparatorChar();
983 
984     /** The system-specific file separator character, as a string.
985         On Windows, this will be '\', on Mac/Linux, it'll be '/'
986     */
987     static StringRef getSeparatorString();
988 
989     //==============================================================================
990     /** Returns a version of a filename with any illegal characters removed.
991 
992         This will return a copy of the given string after removing characters
993         that are not allowed in a legal filename, and possibly shortening the
994         string if it's too long.
995 
996         Because this will remove slashes, don't use it on an absolute pathname - use
997         createLegalPathName() for that.
998 
999         @see createLegalPathName
1000     */
1001     static String createLegalFileName (const String& fileNameToFix);
1002 
1003     /** Returns a version of a path with any illegal characters removed.
1004 
1005         Similar to createLegalFileName(), but this won't remove slashes, so can
1006         be used on a complete pathname.
1007 
1008         @see createLegalFileName
1009     */
1010     static String createLegalPathName (const String& pathNameToFix);
1011 
1012     /** Indicates whether filenames are case-sensitive on the current operating system. */
1013     static bool areFileNamesCaseSensitive();
1014 
1015     /** Returns true if the string seems to be a fully-specified absolute path. */
1016     static bool isAbsolutePath (StringRef path);
1017 
1018     /** Creates a file that simply contains this string, without doing the sanity-checking
1019         that the normal constructors do.
1020 
1021         Best to avoid this unless you really know what you're doing.
1022     */
1023     static File createFileWithoutCheckingPath (const String& absolutePath) noexcept;
1024 
1025     /** Adds a separator character to the end of a path if it doesn't already have one. */
1026     static String addTrailingSeparator (const String& path);
1027 
1028     //==============================================================================
1029     /** Tries to create a symbolic link and returns a boolean to indicate success */
1030     bool createSymbolicLink (const File& linkFileToCreate, bool overwriteExisting) const;
1031 
1032     /** Returns true if this file is a link or alias that can be followed using getLinkedTarget(). */
1033     bool isSymbolicLink() const;
1034 
1035     /** If this file is a link or alias, this returns the file that it points to.
1036         If the file isn't actually link, it'll just return itself.
1037     */
1038     File getLinkedTarget() const;
1039 
1040     /** Create a symbolic link to a native path and return a boolean to indicate success.
1041 
1042         Use this method if you want to create a link to a relative path or a special native
1043         file path (such as a device file on Windows).
1044     */
1045     static bool createSymbolicLink (const File& linkFileToCreate,
1046                                     const String& nativePathOfTarget,
1047                                     bool overwriteExisting);
1048 
1049     /** This returns the native path that the symbolic link points to. The returned path
1050         is a native path of the current OS and can be a relative, absolute or special path. */
1051     String getNativeLinkedTarget() const;
1052 
1053    #if JUCE_WINDOWS || DOXYGEN
1054     /** Windows ONLY - Creates a win32 .LNK shortcut file that links to this file. */
1055     bool createShortcut (const String& description, const File& linkFileToCreate) const;
1056 
1057     /** Windows ONLY - Returns true if this is a win32 .LNK file. */
1058     bool isShortcut() const;
1059    #else
1060 
1061    #endif
1062 
1063     //==============================================================================
1064    #if JUCE_MAC || JUCE_IOS || DOXYGEN
1065     /** OSX ONLY - Finds the OSType of a file from the its resources. */
1066     OSType getMacOSType() const;
1067 
1068     /** OSX ONLY - Returns true if this file is actually a bundle. */
1069     bool isBundle() const;
1070    #endif
1071 
1072    #if JUCE_MAC || DOXYGEN
1073     /** OSX ONLY - Adds this file to the OSX dock */
1074     void addToDock() const;
1075    #endif
1076 
1077     //==============================================================================
1078     /** Comparator for files */
1079     struct NaturalFileComparator
1080     {
NaturalFileComparatorNaturalFileComparator1081         NaturalFileComparator (bool shouldPutFoldersFirst) noexcept : foldersFirst (shouldPutFoldersFirst) {}
1082 
compareElementsNaturalFileComparator1083         int compareElements (const File& firstFile, const File& secondFile) const
1084         {
1085             if (foldersFirst && (firstFile.isDirectory() != secondFile.isDirectory()))
1086                 return firstFile.isDirectory() ? -1 : 1;
1087 
1088            #if NAMES_ARE_CASE_SENSITIVE
1089             return firstFile.getFullPathName().compareNatural (secondFile.getFullPathName(), true);
1090            #else
1091             return firstFile.getFullPathName().compareNatural (secondFile.getFullPathName(), false);
1092            #endif
1093         }
1094 
1095         bool foldersFirst;
1096     };
1097 
1098     /* These static objects are deprecated because it's too easy to accidentally use them indirectly
1099        during a static constructor, which leads to very obscure order-of-initialisation bugs.
1100        Use File::getSeparatorChar() and File::getSeparatorString(), and instead of File::nonexistent,
1101        just use File() or {}.
1102     */
1103     JUCE_DEPRECATED_STATIC (static const juce_wchar separator;)
1104     JUCE_DEPRECATED_STATIC (static const StringRef separatorString;)
1105     JUCE_DEPRECATED_STATIC (static const File nonexistent;)
1106 
1107 private:
1108     //==============================================================================
1109     String fullPath;
1110 
1111     static String parseAbsolutePath (const String&);
1112     String getPathUpToLastSlash() const;
1113 
1114     Result createDirectoryInternal (const String&) const;
1115     bool copyInternal (const File&) const;
1116     bool moveInternal (const File&) const;
1117     bool replaceInternal (const File&) const;
1118     bool setFileTimesInternal (int64 m, int64 a, int64 c) const;
1119     void getFileTimesInternal (int64& m, int64& a, int64& c) const;
1120     bool setFileReadOnlyInternal (bool) const;
1121     bool setFileExecutableInternal (bool) const;
1122 };
1123 
1124 } // namespace juce
1125