The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1165 lines
48KB

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