OpenShot Library | OpenShotAudio  0.2.1
juce_File.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
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 namespace juce
24 {
25 
26 File::File (const String& fullPathName)
27  : fullPath (parseAbsolutePath (fullPathName))
28 {
29 }
30 
32 {
33  File f;
34  f.fullPath = path;
35  return f;
36 }
37 
38 File::File (const File& other)
39  : fullPath (other.fullPath)
40 {
41 }
42 
43 File& File::operator= (const String& newPath)
44 {
45  fullPath = parseAbsolutePath (newPath);
46  return *this;
47 }
48 
49 File& File::operator= (const File& other)
50 {
51  fullPath = other.fullPath;
52  return *this;
53 }
54 
55 File::File (File&& other) noexcept
56  : fullPath (std::move (other.fullPath))
57 {
58 }
59 
60 File& File::operator= (File&& other) noexcept
61 {
62  fullPath = std::move (other.fullPath);
63  return *this;
64 }
65 
66 JUCE_DECLARE_DEPRECATED_STATIC (const File File::nonexistent{};)
67 
68 //==============================================================================
69 static String removeEllipsis (const String& path)
70 {
71  // This will quickly find both /../ and /./ at the expense of a minor
72  // false-positive performance hit when path elements end in a dot.
73  #if JUCE_WINDOWS
74  if (path.contains (".\\"))
75  #else
76  if (path.contains ("./"))
77  #endif
78  {
79  StringArray toks;
80  toks.addTokens (path, File::getSeparatorString(), {});
81  bool anythingChanged = false;
82 
83  for (int i = 1; i < toks.size(); ++i)
84  {
85  auto& t = toks[i];
86 
87  if (t == ".." && toks[i - 1] != "..")
88  {
89  anythingChanged = true;
90  toks.removeRange (i - 1, 2);
91  i = jmax (0, i - 2);
92  }
93  else if (t == ".")
94  {
95  anythingChanged = true;
96  toks.remove (i--);
97  }
98  }
99 
100  if (anythingChanged)
102  }
103 
104  return path;
105 }
106 
107 static String normaliseSeparators (const String& path)
108 {
109  auto normalisedPath = path;
110 
111  String separator (File::getSeparatorString());
112  String doubleSeparator (separator + separator);
113 
114  auto uncPath = normalisedPath.startsWith (doubleSeparator)
115  && ! normalisedPath.fromFirstOccurrenceOf (doubleSeparator, false, false).startsWith (separator);
116 
117  if (uncPath)
118  normalisedPath = normalisedPath.fromFirstOccurrenceOf (doubleSeparator, false, false);
119 
120  while (normalisedPath.contains (doubleSeparator))
121  normalisedPath = normalisedPath.replace (doubleSeparator, separator);
122 
123  return uncPath ? doubleSeparator + normalisedPath
124  : normalisedPath;
125 }
126 
127 bool File::isRoot() const
128 {
129  return fullPath.isNotEmpty() && *this == getParentDirectory();
130 }
131 
132 String File::parseAbsolutePath (const String& p)
133 {
134  if (p.isEmpty())
135  return {};
136 
137  #if JUCE_WINDOWS
138  // Windows..
139  auto path = normaliseSeparators (removeEllipsis (p.replaceCharacter ('/', '\\')));
140 
141  if (path.startsWithChar (getSeparatorChar()))
142  {
143  if (path[1] != getSeparatorChar())
144  {
145  /* When you supply a raw string to the File object constructor, it must be an absolute path.
146  If you're trying to parse a string that may be either a relative path or an absolute path,
147  you MUST provide a context against which the partial path can be evaluated - you can do
148  this by simply using File::getChildFile() instead of the File constructor. E.g. saying
149  "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
150  path if that's what was supplied, or would evaluate a partial path relative to the CWD.
151  */
152  jassertfalse;
153 
155  }
156  }
157  else if (! path.containsChar (':'))
158  {
159  /* When you supply a raw string to the File object constructor, it must be an absolute path.
160  If you're trying to parse a string that may be either a relative path or an absolute path,
161  you MUST provide a context against which the partial path can be evaluated - you can do
162  this by simply using File::getChildFile() instead of the File constructor. E.g. saying
163  "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
164  path if that's what was supplied, or would evaluate a partial path relative to the CWD.
165  */
166  jassertfalse;
167 
169  }
170  #else
171  // Mac or Linux..
172 
173  // Yes, I know it's legal for a unix pathname to contain a backslash, but this assertion is here
174  // to catch anyone who's trying to run code that was written on Windows with hard-coded path names.
175  // If that's why you've ended up here, use File::getChildFile() to build your paths instead.
176  jassert ((! p.containsChar ('\\')) || (p.indexOfChar ('/') >= 0 && p.indexOfChar ('/') < p.indexOfChar ('\\')));
177 
178  auto path = normaliseSeparators (removeEllipsis (p));
179 
180  if (path.startsWithChar ('~'))
181  {
182  if (path[1] == getSeparatorChar() || path[1] == 0)
183  {
184  // expand a name of the form "~/abc"
186  + path.substring (1);
187  }
188  else
189  {
190  // expand a name of type "~dave/abc"
191  auto userName = path.substring (1).upToFirstOccurrenceOf ("/", false, false);
192 
193  if (auto* pw = getpwnam (userName.toUTF8()))
194  path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false);
195  }
196  }
197  else if (! path.startsWithChar (getSeparatorChar()))
198  {
199  #if JUCE_DEBUG || JUCE_LOG_ASSERTIONS
200  if (! (path.startsWith ("./") || path.startsWith ("../")))
201  {
202  /* When you supply a raw string to the File object constructor, it must be an absolute path.
203  If you're trying to parse a string that may be either a relative path or an absolute path,
204  you MUST provide a context against which the partial path can be evaluated - you can do
205  this by simply using File::getChildFile() instead of the File constructor. E.g. saying
206  "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
207  path if that's what was supplied, or would evaluate a partial path relative to the CWD.
208  */
209  jassertfalse;
210 
211  #if JUCE_LOG_ASSERTIONS
212  Logger::writeToLog ("Illegal absolute path: " + path);
213  #endif
214  }
215  #endif
216 
218  }
219  #endif
220 
221  while (path.endsWithChar (getSeparatorChar()) && path != getSeparatorString()) // careful not to turn a single "/" into an empty string.
222  path = path.dropLastCharacters (1);
223 
224  return path;
225 }
226 
228 {
229  return path.endsWithChar (getSeparatorChar()) ? path
230  : path + getSeparatorChar();
231 }
232 
233 //==============================================================================
234 #if JUCE_LINUX
235  #define NAMES_ARE_CASE_SENSITIVE 1
236 #endif
237 
239 {
240  #if NAMES_ARE_CASE_SENSITIVE
241  return true;
242  #else
243  return false;
244  #endif
245 }
246 
247 static int compareFilenames (const String& name1, const String& name2) noexcept
248 {
249  #if NAMES_ARE_CASE_SENSITIVE
250  return name1.compare (name2);
251  #else
252  return name1.compareIgnoreCase (name2);
253  #endif
254 }
255 
256 bool File::operator== (const File& other) const { return compareFilenames (fullPath, other.fullPath) == 0; }
257 bool File::operator!= (const File& other) const { return compareFilenames (fullPath, other.fullPath) != 0; }
258 bool File::operator< (const File& other) const { return compareFilenames (fullPath, other.fullPath) < 0; }
259 bool File::operator> (const File& other) const { return compareFilenames (fullPath, other.fullPath) > 0; }
260 
261 //==============================================================================
262 bool File::setReadOnly (const bool shouldBeReadOnly,
263  const bool applyRecursively) const
264 {
265  bool worked = true;
266 
267  if (applyRecursively && isDirectory())
268  for (auto& f : findChildFiles (File::findFilesAndDirectories, false))
269  worked = f.setReadOnly (shouldBeReadOnly, true) && worked;
270 
271  return setFileReadOnlyInternal (shouldBeReadOnly) && worked;
272 }
273 
274 bool File::setExecutePermission (bool shouldBeExecutable) const
275 {
276  return setFileExecutableInternal (shouldBeExecutable);
277 }
278 
279 bool File::deleteRecursively (bool followSymlinks) const
280 {
281  bool worked = true;
282 
283  if (isDirectory() && (followSymlinks || ! isSymbolicLink()))
284  for (auto& f : findChildFiles (File::findFilesAndDirectories, false))
285  worked = f.deleteRecursively (followSymlinks) && worked;
286 
287  return deleteFile() && worked;
288 }
289 
290 bool File::moveFileTo (const File& newFile) const
291 {
292  if (newFile.fullPath == fullPath)
293  return true;
294 
295  if (! exists())
296  return false;
297 
298  #if ! NAMES_ARE_CASE_SENSITIVE
299  if (*this != newFile)
300  #endif
301  if (! newFile.deleteFile())
302  return false;
303 
304  return moveInternal (newFile);
305 }
306 
307 bool File::copyFileTo (const File& newFile) const
308 {
309  return (*this == newFile)
310  || (exists() && newFile.deleteFile() && copyInternal (newFile));
311 }
312 
313 bool File::replaceFileIn (const File& newFile) const
314 {
315  if (newFile.fullPath == fullPath)
316  return true;
317 
318  if (! newFile.exists())
319  return moveFileTo (newFile);
320 
321  if (! replaceInternal (newFile))
322  return false;
323 
324  deleteFile();
325  return true;
326 }
327 
328 bool File::copyDirectoryTo (const File& newDirectory) const
329 {
330  if (isDirectory() && newDirectory.createDirectory())
331  {
332  for (auto& f : findChildFiles (File::findFiles, false))
333  if (! f.copyFileTo (newDirectory.getChildFile (f.getFileName())))
334  return false;
335 
336  for (auto& f : findChildFiles (File::findDirectories, false))
337  if (! f.copyDirectoryTo (newDirectory.getChildFile (f.getFileName())))
338  return false;
339 
340  return true;
341  }
342 
343  return false;
344 }
345 
346 //==============================================================================
347 String File::getPathUpToLastSlash() const
348 {
349  auto lastSlash = fullPath.lastIndexOfChar (getSeparatorChar());
350 
351  if (lastSlash > 0)
352  return fullPath.substring (0, lastSlash);
353 
354  if (lastSlash == 0)
355  return getSeparatorString();
356 
357  return fullPath;
358 }
359 
361 {
362  return createFileWithoutCheckingPath (getPathUpToLastSlash());
363 }
364 
365 //==============================================================================
367 {
368  return fullPath.substring (fullPath.lastIndexOfChar (getSeparatorChar()) + 1);
369 }
370 
372 {
373  auto lastSlash = fullPath.lastIndexOfChar (getSeparatorChar()) + 1;
374  auto lastDot = fullPath.lastIndexOfChar ('.');
375 
376  if (lastDot > lastSlash)
377  return fullPath.substring (lastSlash, lastDot);
378 
379  return fullPath.substring (lastSlash);
380 }
381 
382 bool File::isAChildOf (const File& potentialParent) const
383 {
384  if (potentialParent.fullPath.isEmpty())
385  return false;
386 
387  auto ourPath = getPathUpToLastSlash();
388 
389  if (compareFilenames (potentialParent.fullPath, ourPath) == 0)
390  return true;
391 
392  if (potentialParent.fullPath.length() >= ourPath.length())
393  return false;
394 
395  return getParentDirectory().isAChildOf (potentialParent);
396 }
397 
398 int File::hashCode() const { return fullPath.hashCode(); }
399 int64 File::hashCode64() const { return fullPath.hashCode64(); }
400 
401 //==============================================================================
403 {
404  auto firstChar = *(path.text);
405 
406  return firstChar == getSeparatorChar()
407  #if JUCE_WINDOWS
408  || (firstChar != 0 && path.text[1] == ':');
409  #else
410  || firstChar == '~';
411  #endif
412 }
413 
414 File File::getChildFile (StringRef relativePath) const
415 {
416  auto r = relativePath.text;
417 
418  if (isAbsolutePath (r))
419  return File (String (r));
420 
421  #if JUCE_WINDOWS
422  if (r.indexOf ((juce_wchar) '/') >= 0)
423  return getChildFile (String (r).replaceCharacter ('/', '\\'));
424  #endif
425 
426  auto path = fullPath;
427  auto separatorChar = getSeparatorChar();
428 
429  while (*r == '.')
430  {
431  auto lastPos = r;
432  auto secondChar = *++r;
433 
434  if (secondChar == '.') // remove "../"
435  {
436  auto thirdChar = *++r;
437 
438  if (thirdChar == separatorChar || thirdChar == 0)
439  {
440  auto lastSlash = path.lastIndexOfChar (separatorChar);
441 
442  if (lastSlash >= 0)
443  path = path.substring (0, lastSlash);
444 
445  while (*r == separatorChar) // ignore duplicate slashes
446  ++r;
447  }
448  else
449  {
450  r = lastPos;
451  break;
452  }
453  }
454  else if (secondChar == separatorChar || secondChar == 0) // remove "./"
455  {
456  while (*r == separatorChar) // ignore duplicate slashes
457  ++r;
458  }
459  else
460  {
461  r = lastPos;
462  break;
463  }
464  }
465 
466  path = addTrailingSeparator (path);
467  path.appendCharPointer (r);
468  return File (path);
469 }
470 
472 {
473  return getParentDirectory().getChildFile (fileName);
474 }
475 
476 //==============================================================================
478 {
479  const char* suffix;
480  double divisor = 0;
481 
482  if (bytes == 1) { suffix = " byte"; }
483  else if (bytes < 1024) { suffix = " bytes"; }
484  else if (bytes < 1024 * 1024) { suffix = " KB"; divisor = 1024.0; }
485  else if (bytes < 1024 * 1024 * 1024) { suffix = " MB"; divisor = 1024.0 * 1024.0; }
486  else { suffix = " GB"; divisor = 1024.0 * 1024.0 * 1024.0; }
487 
488  return (divisor > 0 ? String (bytes / divisor, 1) : String (bytes)) + suffix;
489 }
490 
491 //==============================================================================
493 {
494  if (exists())
495  return Result::ok();
496 
497  auto parentDir = getParentDirectory();
498 
499  if (parentDir == *this)
500  return Result::fail ("Cannot create parent directory");
501 
502  auto r = parentDir.createDirectory();
503 
504  if (r.wasOk())
505  {
506  FileOutputStream fo (*this, 8);
507  r = fo.getStatus();
508  }
509 
510  return r;
511 }
512 
514 {
515  if (isDirectory())
516  return Result::ok();
517 
518  auto parentDir = getParentDirectory();
519 
520  if (parentDir == *this)
521  return Result::fail ("Cannot create parent directory");
522 
523  auto r = parentDir.createDirectory();
524 
525  if (r.wasOk())
526  r = createDirectoryInternal (fullPath.trimCharactersAtEnd (getSeparatorString()));
527 
528  return r;
529 }
530 
531 //==============================================================================
532 Time File::getLastModificationTime() const { int64 m, a, c; getFileTimesInternal (m, a, c); return Time (m); }
533 Time File::getLastAccessTime() const { int64 m, a, c; getFileTimesInternal (m, a, c); return Time (a); }
534 Time File::getCreationTime() const { int64 m, a, c; getFileTimesInternal (m, a, c); return Time (c); }
535 
536 bool File::setLastModificationTime (Time t) const { return setFileTimesInternal (t.toMilliseconds(), 0, 0); }
537 bool File::setLastAccessTime (Time t) const { return setFileTimesInternal (0, t.toMilliseconds(), 0); }
538 bool File::setCreationTime (Time t) const { return setFileTimesInternal (0, 0, t.toMilliseconds()); }
539 
540 //==============================================================================
541 bool File::loadFileAsData (MemoryBlock& destBlock) const
542 {
543  if (! existsAsFile())
544  return false;
545 
546  FileInputStream in (*this);
547  return in.openedOk() && getSize() == (int64) in.readIntoMemoryBlock (destBlock);
548 }
549 
551 {
552  if (! existsAsFile())
553  return {};
554 
555  FileInputStream in (*this);
556  return in.openedOk() ? in.readEntireStreamAsString()
557  : String();
558 }
559 
560 void File::readLines (StringArray& destLines) const
561 {
562  destLines.addLines (loadFileAsString());
563 }
564 
565 //==============================================================================
566 Array<File> File::findChildFiles (int whatToLookFor, bool searchRecursively, const String& wildcard) const
567 {
568  Array<File> results;
569  findChildFiles (results, whatToLookFor, searchRecursively, wildcard);
570  return results;
571 }
572 
573 int File::findChildFiles (Array<File>& results, int whatToLookFor, bool searchRecursively, const String& wildcard) const
574 {
575  int total = 0;
576 
577  for (DirectoryIterator di (*this, searchRecursively, wildcard, whatToLookFor); di.next();)
578  {
579  results.add (di.getFile());
580  ++total;
581  }
582 
583  return total;
584 }
585 
586 int File::getNumberOfChildFiles (const int whatToLookFor, const String& wildCardPattern) const
587 {
588  int total = 0;
589 
590  for (DirectoryIterator di (*this, false, wildCardPattern, whatToLookFor); di.next();)
591  ++total;
592 
593  return total;
594 }
595 
597 {
598  if (! isDirectory())
599  return false;
600 
601  DirectoryIterator di (*this, false, "*", findDirectories);
602  return di.next();
603 }
604 
605 //==============================================================================
606 File File::getNonexistentChildFile (const String& suggestedPrefix,
607  const String& suffix,
608  bool putNumbersInBrackets) const
609 {
610  auto f = getChildFile (suggestedPrefix + suffix);
611 
612  if (f.exists())
613  {
614  int number = 1;
615  auto prefix = suggestedPrefix;
616 
617  // remove any bracketed numbers that may already be on the end..
618  if (prefix.trim().endsWithChar (')'))
619  {
620  putNumbersInBrackets = true;
621 
622  auto openBracks = prefix.lastIndexOfChar ('(');
623  auto closeBracks = prefix.lastIndexOfChar (')');
624 
625  if (openBracks > 0
626  && closeBracks > openBracks
627  && prefix.substring (openBracks + 1, closeBracks).containsOnly ("0123456789"))
628  {
629  number = prefix.substring (openBracks + 1, closeBracks).getIntValue();
630  prefix = prefix.substring (0, openBracks);
631  }
632  }
633 
634  do
635  {
636  auto newName = prefix;
637 
638  if (putNumbersInBrackets)
639  {
640  newName << '(' << ++number << ')';
641  }
642  else
643  {
644  if (CharacterFunctions::isDigit (prefix.getLastCharacter()))
645  newName << '_'; // pad with an underscore if the name already ends in a digit
646 
647  newName << ++number;
648  }
649 
650  f = getChildFile (newName + suffix);
651 
652  } while (f.exists());
653  }
654 
655  return f;
656 }
657 
658 File File::getNonexistentSibling (const bool putNumbersInBrackets) const
659 {
660  if (! exists())
661  return *this;
662 
665  putNumbersInBrackets);
666 }
667 
668 //==============================================================================
670 {
671  auto indexOfDot = fullPath.lastIndexOfChar ('.');
672 
673  if (indexOfDot > fullPath.lastIndexOfChar (getSeparatorChar()))
674  return fullPath.substring (indexOfDot);
675 
676  return {};
677 }
678 
679 bool File::hasFileExtension (StringRef possibleSuffix) const
680 {
681  if (possibleSuffix.isEmpty())
682  return fullPath.lastIndexOfChar ('.') <= fullPath.lastIndexOfChar (getSeparatorChar());
683 
684  auto semicolon = possibleSuffix.text.indexOf ((juce_wchar) ';');
685 
686  if (semicolon >= 0)
687  return hasFileExtension (String (possibleSuffix.text).substring (0, semicolon).trimEnd())
688  || hasFileExtension ((possibleSuffix.text + (semicolon + 1)).findEndOfWhitespace());
689 
690  if (fullPath.endsWithIgnoreCase (possibleSuffix))
691  {
692  if (possibleSuffix.text[0] == '.')
693  return true;
694 
695  auto dotPos = fullPath.length() - possibleSuffix.length() - 1;
696 
697  if (dotPos >= 0)
698  return fullPath[dotPos] == '.';
699  }
700 
701  return false;
702 }
703 
705 {
706  if (fullPath.isEmpty())
707  return {};
708 
709  auto filePart = getFileName();
710 
711  auto lastDot = filePart.lastIndexOfChar ('.');
712 
713  if (lastDot >= 0)
714  filePart = filePart.substring (0, lastDot);
715 
716  if (newExtension.isNotEmpty() && newExtension.text[0] != '.')
717  filePart << '.';
718 
719  return getSiblingFile (filePart + newExtension);
720 }
721 
722 //==============================================================================
723 bool File::startAsProcess (const String& parameters) const
724 {
725  return exists() && Process::openDocument (fullPath, parameters);
726 }
727 
728 //==============================================================================
730 {
731  std::unique_ptr<FileInputStream> fin (new FileInputStream (*this));
732 
733  if (fin->openedOk())
734  return fin.release();
735 
736  return nullptr;
737 }
738 
739 FileOutputStream* File::createOutputStream (size_t bufferSize) const
740 {
741  std::unique_ptr<FileOutputStream> out (new FileOutputStream (*this, bufferSize));
742 
743  return out->failedToOpen() ? nullptr
744  : out.release();
745 }
746 
747 //==============================================================================
748 bool File::appendData (const void* const dataToAppend,
749  const size_t numberOfBytes) const
750 {
751  jassert (((ssize_t) numberOfBytes) >= 0);
752 
753  if (numberOfBytes == 0)
754  return true;
755 
756  FileOutputStream out (*this, 8192);
757  return out.openedOk() && out.write (dataToAppend, numberOfBytes);
758 }
759 
760 bool File::replaceWithData (const void* const dataToWrite,
761  const size_t numberOfBytes) const
762 {
763  if (numberOfBytes == 0)
764  return deleteFile();
765 
767  tempFile.getFile().appendData (dataToWrite, numberOfBytes);
768  return tempFile.overwriteTargetFileWithTemporary();
769 }
770 
771 bool File::appendText (const String& text, bool asUnicode, bool writeHeaderBytes, const char* lineFeed) const
772 {
773  FileOutputStream out (*this);
774 
775  if (out.failedToOpen())
776  return false;
777 
778  return out.writeText (text, asUnicode, writeHeaderBytes, lineFeed);
779 }
780 
781 bool File::replaceWithText (const String& textToWrite, bool asUnicode, bool writeHeaderBytes, const char* lineFeed) const
782 {
784  tempFile.getFile().appendText (textToWrite, asUnicode, writeHeaderBytes, lineFeed);
785  return tempFile.overwriteTargetFileWithTemporary();
786 }
787 
788 bool File::hasIdenticalContentTo (const File& other) const
789 {
790  if (other == *this)
791  return true;
792 
793  if (getSize() == other.getSize() && existsAsFile() && other.existsAsFile())
794  {
795  FileInputStream in1 (*this), in2 (other);
796 
797  if (in1.openedOk() && in2.openedOk())
798  {
799  const int bufferSize = 4096;
800  HeapBlock<char> buffer1 (bufferSize), buffer2 (bufferSize);
801 
802  for (;;)
803  {
804  auto num1 = in1.read (buffer1, bufferSize);
805  auto num2 = in2.read (buffer2, bufferSize);
806 
807  if (num1 != num2)
808  break;
809 
810  if (num1 <= 0)
811  return true;
812 
813  if (memcmp (buffer1, buffer2, (size_t) num1) != 0)
814  break;
815  }
816  }
817  }
818 
819  return false;
820 }
821 
822 //==============================================================================
824 {
825  auto s = original;
826  String start;
827 
828  if (s.isNotEmpty() && s[1] == ':')
829  {
830  start = s.substring (0, 2);
831  s = s.substring (2);
832  }
833 
834  return start + s.removeCharacters ("\"#@,;:<>*^|?")
835  .substring (0, 1024);
836 }
837 
839 {
840  auto s = original.removeCharacters ("\"#@,;:<>*^|?\\/");
841 
842  const int maxLength = 128; // only the length of the filename, not the whole path
843  auto len = s.length();
844 
845  if (len > maxLength)
846  {
847  auto lastDot = s.lastIndexOfChar ('.');
848 
849  if (lastDot > jmax (0, len - 12))
850  {
851  s = s.substring (0, maxLength - (len - lastDot))
852  + s.substring (lastDot);
853  }
854  else
855  {
856  s = s.substring (0, maxLength);
857  }
858  }
859 
860  return s;
861 }
862 
863 //==============================================================================
864 static int countNumberOfSeparators (String::CharPointerType s)
865 {
866  int num = 0;
867 
868  for (;;)
869  {
870  auto c = s.getAndAdvance();
871 
872  if (c == 0)
873  break;
874 
875  if (c == File::getSeparatorChar())
876  ++num;
877  }
878 
879  return num;
880 }
881 
883 {
884  if (dir == *this)
885  return ".";
886 
887  auto thisPath = fullPath;
888 
889  while (thisPath.endsWithChar (getSeparatorChar()))
890  thisPath = thisPath.dropLastCharacters (1);
891 
893  : dir.fullPath);
894 
895  int commonBitLength = 0;
896  auto thisPathAfterCommon = thisPath.getCharPointer();
897  auto dirPathAfterCommon = dirPath.getCharPointer();
898 
899  {
900  auto thisPathIter = thisPath.getCharPointer();
901  auto dirPathIter = dirPath.getCharPointer();
902 
903  for (int i = 0;;)
904  {
905  auto c1 = thisPathIter.getAndAdvance();
906  auto c2 = dirPathIter.getAndAdvance();
907 
908  #if NAMES_ARE_CASE_SENSITIVE
909  if (c1 != c2
910  #else
912  #endif
913  || c1 == 0)
914  break;
915 
916  ++i;
917 
918  if (c1 == getSeparatorChar())
919  {
920  thisPathAfterCommon = thisPathIter;
921  dirPathAfterCommon = dirPathIter;
922  commonBitLength = i;
923  }
924  }
925  }
926 
927  // if the only common bit is the root, then just return the full path..
928  if (commonBitLength == 0 || (commonBitLength == 1 && thisPath[1] == getSeparatorChar()))
929  return fullPath;
930 
931  auto numUpDirectoriesNeeded = countNumberOfSeparators (dirPathAfterCommon);
932 
933  if (numUpDirectoriesNeeded == 0)
934  return thisPathAfterCommon;
935 
936  #if JUCE_WINDOWS
937  auto s = String::repeatedString ("..\\", numUpDirectoriesNeeded);
938  #else
939  auto s = String::repeatedString ("../", numUpDirectoriesNeeded);
940  #endif
941  s.appendCharPointer (thisPathAfterCommon);
942  return s;
943 }
944 
945 //==============================================================================
947 {
948  auto tempFile = getSpecialLocation (tempDirectory)
949  .getChildFile ("temp_" + String::toHexString (Random::getSystemRandom().nextInt()))
950  .withFileExtension (fileNameEnding);
951 
952  if (tempFile.exists())
953  return createTempFile (fileNameEnding);
954 
955  return tempFile;
956 }
957 
958 bool File::createSymbolicLink (const File& linkFileToCreate,
959  const String& nativePathOfTarget,
960  bool overwriteExisting)
961 {
962  if (linkFileToCreate.exists())
963  {
964  if (! linkFileToCreate.isSymbolicLink())
965  {
966  // user has specified an existing file / directory as the link
967  // this is bad! the user could end up unintentionally destroying data
968  jassertfalse;
969  return false;
970  }
971 
972  if (overwriteExisting)
973  linkFileToCreate.deleteFile();
974  }
975 
976  #if JUCE_MAC || JUCE_LINUX
977  // one common reason for getting an error here is that the file already exists
978  if (symlink (nativePathOfTarget.toRawUTF8(), linkFileToCreate.getFullPathName().toRawUTF8()) == -1)
979  {
980  jassertfalse;
981  return false;
982  }
983 
984  return true;
985  #elif JUCE_MSVC
986  File targetFile (linkFileToCreate.getSiblingFile (nativePathOfTarget));
987 
988  return CreateSymbolicLink (linkFileToCreate.getFullPathName().toWideCharPointer(),
989  nativePathOfTarget.toWideCharPointer(),
990  targetFile.isDirectory() ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) != FALSE;
991  #else
992  ignoreUnused (nativePathOfTarget);
993  jassertfalse; // symbolic links not supported on this platform!
994  return false;
995  #endif
996 }
997 
998 bool File::createSymbolicLink (const File& linkFileToCreate, bool overwriteExisting) const
999 {
1000  return createSymbolicLink (linkFileToCreate, getFullPathName(), overwriteExisting);
1001 }
1002 
1003 #if ! JUCE_WINDOWS
1005 {
1006  if (isSymbolicLink())
1008 
1009  return *this;
1010 }
1011 #endif
1012 
1013 //==============================================================================
1015  : range (0, file.getSize())
1016 {
1017  openInternal (file, mode, exclusive);
1018 }
1019 
1020 MemoryMappedFile::MemoryMappedFile (const File& file, const Range<int64>& fileRange, AccessMode mode, bool exclusive)
1021  : range (fileRange.getIntersectionWith (Range<int64> (0, file.getSize())))
1022 {
1023  openInternal (file, mode, exclusive);
1024 }
1025 
1026 
1027 //==============================================================================
1028 //==============================================================================
1029 #if JUCE_UNIT_TESTS
1030 
1031 class FileTests : public UnitTest
1032 {
1033 public:
1034  FileTests()
1035  : UnitTest ("Files", UnitTestCategories::files)
1036  {}
1037 
1038  void runTest() override
1039  {
1040  beginTest ("Reading");
1041 
1044 
1045  expect (! File().exists());
1046  expect (! File().existsAsFile());
1047  expect (! File().isDirectory());
1048  #if ! JUCE_WINDOWS
1049  expect (File("/").isDirectory());
1050  #endif
1051  expect (home.isDirectory());
1052  expect (home.exists());
1053  expect (! home.existsAsFile());
1058  expect (home.getVolumeTotalSize() > 1024 * 1024);
1059  expect (home.getBytesFreeOnVolume() > 0);
1060  expect (! home.isHidden());
1061  expect (home.isOnHardDisk());
1062  expect (! home.isOnCDRomDrive());
1063  expect (File::getCurrentWorkingDirectory().exists());
1064  expect (home.setAsCurrentWorkingDirectory());
1065  expect (File::getCurrentWorkingDirectory() == home);
1066 
1067  {
1068  Array<File> roots;
1069  File::findFileSystemRoots (roots);
1070  expect (roots.size() > 0);
1071 
1072  int numRootsExisting = 0;
1073  for (int i = 0; i < roots.size(); ++i)
1074  if (roots[i].exists())
1075  ++numRootsExisting;
1076 
1077  // (on windows, some of the drives may not contain media, so as long as at least one is ok..)
1078  expect (numRootsExisting > 0);
1079  }
1080 
1081  beginTest ("Writing");
1082 
1083  File demoFolder (temp.getChildFile ("JUCE UnitTests Temp Folder.folder"));
1084  expect (demoFolder.deleteRecursively());
1085  expect (demoFolder.createDirectory());
1086  expect (demoFolder.isDirectory());
1087  expect (demoFolder.getParentDirectory() == temp);
1088  expect (temp.isDirectory());
1089  expect (temp.findChildFiles (File::findFilesAndDirectories, false, "*").contains (demoFolder));
1090  expect (temp.findChildFiles (File::findDirectories, true, "*.folder").contains (demoFolder));
1091 
1092  File tempFile (demoFolder.getNonexistentChildFile ("test", ".txt", false));
1093 
1094  expect (tempFile.getFileExtension() == ".txt");
1095  expect (tempFile.hasFileExtension (".txt"));
1096  expect (tempFile.hasFileExtension ("txt"));
1097  expect (tempFile.withFileExtension ("xyz").hasFileExtension (".xyz"));
1098  expect (tempFile.withFileExtension ("xyz").hasFileExtension ("abc;xyz;foo"));
1099  expect (tempFile.withFileExtension ("xyz").hasFileExtension ("xyz;foo"));
1100  expect (! tempFile.withFileExtension ("h").hasFileExtension ("bar;foo;xx"));
1101  expect (tempFile.getSiblingFile ("foo").isAChildOf (temp));
1102  expect (tempFile.hasWriteAccess());
1103 
1104  expect (home.getChildFile (".") == home);
1105  expect (home.getChildFile ("..") == home.getParentDirectory());
1106  expect (home.getChildFile (".xyz").getFileName() == ".xyz");
1107  expect (home.getChildFile ("..xyz").getFileName() == "..xyz");
1108  expect (home.getChildFile ("...xyz").getFileName() == "...xyz");
1109  expect (home.getChildFile ("./xyz") == home.getChildFile ("xyz"));
1110  expect (home.getChildFile ("././xyz") == home.getChildFile ("xyz"));
1111  expect (home.getChildFile ("../xyz") == home.getParentDirectory().getChildFile ("xyz"));
1112  expect (home.getChildFile (".././xyz") == home.getParentDirectory().getChildFile ("xyz"));
1113  expect (home.getChildFile (".././xyz/./abc") == home.getParentDirectory().getChildFile ("xyz/abc"));
1114  expect (home.getChildFile ("./../xyz") == home.getParentDirectory().getChildFile ("xyz"));
1115  expect (home.getChildFile ("a1/a2/a3/./../../a4") == home.getChildFile ("a1/a4"));
1116 
1117  {
1118  FileOutputStream fo (tempFile);
1119  fo.write ("0123456789", 10);
1120  }
1121 
1122  expect (tempFile.exists());
1123  expect (tempFile.getSize() == 10);
1124  expect (std::abs ((int) (tempFile.getLastModificationTime().toMilliseconds() - Time::getCurrentTime().toMilliseconds())) < 3000);
1125  expectEquals (tempFile.loadFileAsString(), String ("0123456789"));
1126  expect (! demoFolder.containsSubDirectories());
1127 
1128  expectEquals (tempFile.getRelativePathFrom (demoFolder.getParentDirectory()), demoFolder.getFileName() + File::getSeparatorString() + tempFile.getFileName());
1129  expectEquals (demoFolder.getParentDirectory().getRelativePathFrom (tempFile), ".." + File::getSeparatorString() + ".." + File::getSeparatorString() + demoFolder.getParentDirectory().getFileName());
1130 
1131  expect (demoFolder.getNumberOfChildFiles (File::findFiles) == 1);
1132  expect (demoFolder.getNumberOfChildFiles (File::findFilesAndDirectories) == 1);
1133  expect (demoFolder.getNumberOfChildFiles (File::findDirectories) == 0);
1134  demoFolder.getNonexistentChildFile ("tempFolder", "", false).createDirectory();
1135  expect (demoFolder.getNumberOfChildFiles (File::findDirectories) == 1);
1136  expect (demoFolder.getNumberOfChildFiles (File::findFilesAndDirectories) == 2);
1137  expect (demoFolder.containsSubDirectories());
1138 
1139  expect (tempFile.hasWriteAccess());
1140  tempFile.setReadOnly (true);
1141  expect (! tempFile.hasWriteAccess());
1142  tempFile.setReadOnly (false);
1143  expect (tempFile.hasWriteAccess());
1144 
1145  Time t (Time::getCurrentTime());
1146  tempFile.setLastModificationTime (t);
1147  Time t2 = tempFile.getLastModificationTime();
1148  expect (std::abs ((int) (t2.toMilliseconds() - t.toMilliseconds())) <= 1000);
1149 
1150  {
1151  MemoryBlock mb;
1152  tempFile.loadFileAsData (mb);
1153  expect (mb.getSize() == 10);
1154  expect (mb[0] == '0');
1155  }
1156 
1157  {
1158  expect (tempFile.getSize() == 10);
1159  FileOutputStream fo (tempFile);
1160  expect (fo.openedOk());
1161 
1162  expect (fo.setPosition (7));
1163  expect (fo.truncate().wasOk());
1164  expect (tempFile.getSize() == 7);
1165  fo.write ("789", 3);
1166  fo.flush();
1167  expect (tempFile.getSize() == 10);
1168  }
1169 
1170  beginTest ("Memory-mapped files");
1171 
1172  {
1174  expect (mmf.getSize() == 10);
1175  expect (mmf.getData() != nullptr);
1176  expect (memcmp (mmf.getData(), "0123456789", 10) == 0);
1177  }
1178 
1179  {
1180  const File tempFile2 (tempFile.getNonexistentSibling (false));
1181  expect (tempFile2.create());
1182  expect (tempFile2.appendData ("xxxxxxxxxx", 10));
1183 
1184  {
1186  expect (mmf.getSize() == 10);
1187  expect (mmf.getData() != nullptr);
1188  memcpy (mmf.getData(), "abcdefghij", 10);
1189  }
1190 
1191  {
1193  expect (mmf.getSize() == 10);
1194  expect (mmf.getData() != nullptr);
1195  expect (memcmp (mmf.getData(), "abcdefghij", 10) == 0);
1196  }
1197 
1198  expect (tempFile2.deleteFile());
1199  }
1200 
1201  beginTest ("More writing");
1202 
1203  expect (tempFile.appendData ("abcdefghij", 10));
1204  expect (tempFile.getSize() == 20);
1205  expect (tempFile.replaceWithData ("abcdefghij", 10));
1206  expect (tempFile.getSize() == 10);
1207 
1208  File tempFile2 (tempFile.getNonexistentSibling (false));
1209  expect (tempFile.copyFileTo (tempFile2));
1210  expect (tempFile2.exists());
1211  expect (tempFile2.hasIdenticalContentTo (tempFile));
1212  expect (tempFile.deleteFile());
1213  expect (! tempFile.exists());
1214  expect (tempFile2.moveFileTo (tempFile));
1215  expect (tempFile.exists());
1216  expect (! tempFile2.exists());
1217 
1218  expect (demoFolder.deleteRecursively());
1219  expect (! demoFolder.exists());
1220 
1221  {
1222  URL url ("https://audio.dev/foo/bar/");
1223  expectEquals (url.toString (false), String ("https://audio.dev/foo/bar/"));
1224  expectEquals (url.getChildURL ("x").toString (false), String ("https://audio.dev/foo/bar/x"));
1225  expectEquals (url.getParentURL().toString (false), String ("https://audio.dev/foo"));
1226  expectEquals (url.getParentURL().getParentURL().toString (false), String ("https://audio.dev/"));
1227  expectEquals (url.getParentURL().getParentURL().getParentURL().toString (false), String ("https://audio.dev/"));
1228  expectEquals (url.getParentURL().getChildURL ("x").toString (false), String ("https://audio.dev/foo/x"));
1229  expectEquals (url.getParentURL().getParentURL().getParentURL().getChildURL ("x").toString (false), String ("https://audio.dev/x"));
1230  }
1231 
1232  {
1233  URL url ("https://audio.dev/foo/bar");
1234  expectEquals (url.toString (false), String ("https://audio.dev/foo/bar"));
1235  expectEquals (url.getChildURL ("x").toString (false), String ("https://audio.dev/foo/bar/x"));
1236  expectEquals (url.getParentURL().toString (false), String ("https://audio.dev/foo"));
1237  expectEquals (url.getParentURL().getParentURL().toString (false), String ("https://audio.dev/"));
1238  expectEquals (url.getParentURL().getParentURL().getParentURL().toString (false), String ("https://audio.dev/"));
1239  expectEquals (url.getParentURL().getChildURL ("x").toString (false), String ("https://audio.dev/foo/x"));
1240  expectEquals (url.getParentURL().getParentURL().getParentURL().getChildURL ("x").toString (false), String ("https://audio.dev/x"));
1241  }
1242  }
1243 };
1244 
1245 static FileTests fileUnitTests;
1246 
1247 #endif
1248 
1249 } // namespace juce
size_t getSize() const noexcept
Returns the block&#39;s current allocated size, in bytes.
bool copyFileTo(const File &targetLocation) const
Copies a file.
Definition: juce_File.cpp:307
String getFileName() const
Returns the last section of the pathname.
Definition: juce_File.cpp:366
Manages a temporary file, which will be deleted when this object is deleted.
bool setReadOnly(bool shouldBeReadOnly, bool applyRecursively=false) const
Changes the write-permission of a file or directory.
Definition: juce_File.cpp:262
Result create() const
Creates an empty file if it doesn&#39;t already exist.
Definition: juce_File.cpp:492
bool operator!=(const File &) const
Compares the pathnames for two files.
Definition: juce_File.cpp:257
static Random & getSystemRandom() noexcept
The overhead of creating a new Random object is fairly small, but if you want to avoid it...
Definition: juce_Random.cpp:71
bool appendText(const String &textToAppend, bool asUnicode=false, bool writeUnicodeHeaderBytes=false, const char *lineEndings="\") const
Appends a string to the end of the file.
Definition: juce_File.cpp:771
int64 hashCode64() const noexcept
Generates a probably-unique 64-bit hashcode from this string.
bool hasIdenticalContentTo(const File &other) const
Attempts to scan the contents of this file and compare it to another file, returning true if this is ...
Definition: juce_File.cpp:788
Indicates that the memory can only be read.
bool setCreationTime(Time newTime) const
Changes the creation date for this file.
Definition: juce_File.cpp:538
File getSiblingFile(StringRef siblingFileName) const
Returns a file which is in the same directory as this one.
Definition: juce_File.cpp:471
String fromFirstOccurrenceOf(StringRef substringToStartFrom, bool includeSubStringInResult, bool ignoreCase) const
Returns a section of the string starting from a given substring.
static Result ok() noexcept
Creates and returns a &#39;successful&#39; result.
Definition: juce_Result.h:65
static bool isAbsolutePath(StringRef path)
Returns true if the string seems to be a fully-specified absolute path.
Definition: juce_File.cpp:402
const char * toRawUTF8() const
Returns a pointer to a UTF-8 version of this string.
bool copyDirectoryTo(const File &newDirectory) const
Copies a directory.
Definition: juce_File.cpp:328
bool createSymbolicLink(const File &linkFileToCreate, bool overwriteExisting) const
Tries to create a symbolic link and returns a boolean to indicate success.
Definition: juce_File.cpp:998
bool appendData(const void *dataToAppend, size_t numberOfBytes) const
Appends a block of binary data to the end of the file.
Definition: juce_File.cpp:748
bool operator<(const File &) const
Compares the pathnames for two files.
Definition: juce_File.cpp:258
static String createLegalPathName(const String &pathNameToFix)
Returns a version of a path with any illegal characters removed.
Definition: juce_File.cpp:823
bool overwriteTargetFileWithTemporary() const
Tries to move the temporary file to overwrite the target file that was specified in the constructor...
bool endsWithChar(juce_wchar character) const noexcept
Tests whether the string ends with a particular character.
bool isNotEmpty() const noexcept
Returns true if the string contains at least one character.
Definition: juce_String.h:306
Searches through the files in a directory, returning each file that is found.
const File & getFile() const noexcept
Returns the temporary file.
URL getChildURL(const String &subPath) const
Returns a new URL that refers to a sub-path relative to this one.
Definition: juce_URL.cpp:440
const Result & getStatus() const noexcept
Returns the status of the file stream.
A simple class for holding temporary references to a string literal or String.
bool isAChildOf(const File &potentialParentDirectory) const
Checks whether a file is somewhere inside a directory.
Definition: juce_File.cpp:382
bool setLastAccessTime(Time newTime) const
Changes the last-access time for this file.
Definition: juce_File.cpp:537
int length() const noexcept
Returns the number of characters in the string.
File getParentDirectory() const
Returns the directory that contains this file or directory.
Definition: juce_File.cpp:360
static File createFileWithoutCheckingPath(const String &absolutePath) noexcept
Creates a file that simply contains this string, without doing the sanity-checking that the normal co...
Definition: juce_File.cpp:31
void add(const ElementType &newElement)
Appends a new element at the end of the array.
Definition: juce_Array.h:422
Time getLastModificationTime() const
Returns the last modification time of this file.
Definition: juce_File.cpp:532
Result createDirectory() const
Creates a new directory for this filename.
Definition: juce_File.cpp:513
bool deleteFile() const
Deletes a file.
bool isNotEmpty() const noexcept
Returns true if the string is not empty.
String trimCharactersAtEnd(StringRef charactersToTrim) const
Returns a copy of this string, having removed a specified set of characters from its end...
Indicates that the temporary file should be hidden - i.e.
void remove(int index)
Removes a string from the array.
bool containsChar(juce_wchar character) const noexcept
Tests whether the string contains a particular character.
bool endsWithIgnoreCase(StringRef text) const noexcept
Tests whether the string ends with another string.
Indicates that the memory can be read and written to - changes that are made will be flushed back to ...
The user&#39;s home folder.
Definition: juce_File.h:836
bool replaceWithText(const String &textToWrite, bool asUnicode=false, bool writeUnicodeHeaderBytes=false, const char *lineEndings="\") const
Replaces this file&#39;s contents with a given text string.
Definition: juce_File.cpp:781
String toString(bool includeGetParameters) const
Returns a string version of the URL.
Definition: juce_URL.cpp:311
void * getData() const noexcept
Returns the address at which this file has been mapped, or a null pointer if the file couldn&#39;t be suc...
static bool isDigit(char character) noexcept
Checks whether a character is a digit.
CharPointerType getCharPointer() const noexcept
Returns the character pointer currently being used to store this string.
Definition: juce_String.h:1202
String dropLastCharacters(int numberToDrop) const
Returns a version of this string with a number of characters removed from the end.
int addLines(StringRef stringToBreakUp)
Breaks up a string into lines and adds them to this array.
bool operator==(const File &) const
Compares the pathnames for two files.
Definition: juce_File.cpp:256
bool isRoot() const
Checks whether the path of this file represents the root of a file system, irrespective of its existe...
Definition: juce_File.cpp:127
bool containsSubDirectories() const
Returns true if this file is a directory that contains one or more subdirectories.
Definition: juce_File.cpp:596
int64 toMilliseconds() const noexcept
Returns the time as a number of milliseconds.
Definition: juce_Time.h:102
bool isSymbolicLink() const
Returns true if this file is a link or alias that can be followed using getLinkedTarget().
A special array for holding a list of strings.
File getChildFile(StringRef relativeOrAbsolutePath) const
Returns a file that represents a relative (or absolute) sub-path of the current one.
Definition: juce_File.cpp:414
The JUCE String class!
Definition: juce_String.h:42
FileInputStream * createInputStream() const
Creates a stream to read from this file.
Definition: juce_File.cpp:729
Use this flag to indicate that you want to find both files and directories.
Definition: juce_File.h:555
bool write(const void *, size_t) override
Writes a block of data to the stream.
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Returns a Time object that is set to the current system time.
Definition: juce_Time.cpp:218
File & operator=(const String &newAbsolutePath)
Sets the file based on an absolute pathname.
Definition: juce_File.cpp:43
static bool JUCE_CALLTYPE openDocument(const String &documentURL, const String &parameters)
Tries to launch the OS&#39;s default reader application for a given file or URL.
bool exists() const
Checks whether the file actually exists.
const wchar_t * toWideCharPointer() const
Returns a pointer to a wchar_t version of this string.
bool setLastModificationTime(Time newTime) const
Changes the modification time for this file.
Definition: juce_File.cpp:536
Time getLastAccessTime() const
Returns the last time this file was accessed.
Definition: juce_File.cpp:533
bool replaceFileIn(const File &targetLocation) const
Replaces a file.
Definition: juce_File.cpp:313
static void findFileSystemRoots(Array< File > &results)
Creates a set of files to represent each file root.
static String createLegalFileName(const String &fileNameToFix)
Returns a version of a filename with any illegal characters removed.
Definition: juce_File.cpp:838
void readLines(StringArray &destLines) const
Reads the contents of this file as text and splits it into lines, which are appended to the given Str...
Definition: juce_File.cpp:560
This is a base class for classes that perform a unit test.
Definition: juce_UnitTest.h:73
static Result fail(const String &errorMessage) noexcept
Creates a &#39;failure&#39; result.
Definition: juce_Result.cpp:65
Maps a file into virtual memory for easy reading and/or writing.
virtual bool writeText(const String &text, bool asUTF16, bool writeUTF16ByteOrderMark, const char *lineEndings)
Writes a string of text to the stream.
String removeCharacters(StringRef charactersToRemove) const
Returns a version of this string with a set of characters removed.
int addTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Breaks up a string into tokens and adds them to this array.
String trimEnd() const
Returns a copy of this string with any whitespace characters removed from the end.
static String repeatedString(StringRef stringToRepeat, int numberOfTimesToRepeat)
Creates a string which is a version of a string repeated and joined together.
Returns this application&#39;s executable file.
Definition: juce_File.h:899
String substring(int startIndex, int endIndex) const
Returns a subsection of the string.
int read(void *, int) override
Reads some data from the stream into a memory buffer.
Use this flag to indicate that you want to find files.
Definition: juce_File.h:554
static String descriptionOfSizeInBytes(int64 bytes)
Utility function to convert a file size in bytes to a neat string description.
Definition: juce_File.cpp:477
File withFileExtension(StringRef newExtension) const
Returns a version of this file with a different file extension.
Definition: juce_File.cpp:704
int indexOf(const CharPointer stringToFind) const noexcept
Returns the character index of a substring, or -1 if it isn&#39;t found.
bool openedOk() const noexcept
Returns true if the stream opened without problems.
String loadFileAsString() const
Reads a file into memory as a string.
Definition: juce_File.cpp:550
bool contains(StringRef text) const noexcept
Tests whether the string contains another substring.
int64 getSize() const
Returns the size of the file in bytes.
int64 hashCode64() const
Returns a 64-bit hash-code that identifies this file.
Definition: juce_File.cpp:399
int compareIgnoreCase(const String &other) const noexcept
Case-insensitive comparison with another string.
bool isHidden() const
Returns true if this file is a hidden or system file.
bool isEmpty() const noexcept
Returns true if the string is empty.
juce_wchar getAndAdvance() noexcept
Returns the character that this pointer is currently pointing to, and then advances the pointer to po...
static String toHexString(IntegerType number)
Returns a string representing this numeric value in hexadecimal.
Definition: juce_String.h:1057
bool loadFileAsData(MemoryBlock &result) const
Loads a file&#39;s contents into memory as a block of binary data.
Definition: juce_File.cpp:541
Represents the &#39;success&#39; or &#39;failure&#39; of an operation, and holds an associated error message to descr...
Definition: juce_Result.h:60
bool replaceWithData(const void *dataToWrite, size_t numberOfBytes) const
Replaces this file&#39;s contents with a given block of data.
Definition: juce_File.cpp:760
Array< File > findChildFiles(int whatToLookFor, bool searchRecursively, const String &wildCardPattern="*") const
Searches this directory for files matching a wildcard pattern.
Definition: juce_File.cpp:566
void removeRange(int startIndex, int numberToRemove)
Removes a range of elements from the array.
bool existsAsFile() const
Checks whether the file exists and is a file rather than a directory.
String getRelativePathFrom(const File &directoryToBeRelativeTo) const
Creates a relative path that refers to a file relatively to a given directory.
Definition: juce_File.cpp:882
String replaceCharacter(juce_wchar characterToReplace, juce_wchar characterToInsertInstead) const
Returns a string with all occurrences of a character replaced with a different one.
Use this flag to indicate that you want to find directories.
Definition: juce_File.h:553
Represents a local file or directory.
Definition: juce_File.h:44
bool moveFileTo(const File &targetLocation) const
Moves or renames a file.
Definition: juce_File.cpp:290
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:59
bool hasFileExtension(StringRef extensionToTest) const
Checks whether the file has a given extension.
Definition: juce_File.cpp:679
String getFileExtension() const
Returns the file&#39;s extension.
Definition: juce_File.cpp:669
int size() const noexcept
Returns the current number of elements in the array.
Definition: juce_Array.h:219
FileOutputStream * createOutputStream(size_t bufferSize=0x8000) const
Creates a stream to write to this file.
Definition: juce_File.cpp:739
static juce_wchar toLowerCase(juce_wchar character) noexcept
Converts a character to lower-case.
bool isEmpty() const noexcept
Returns true if the string contains no characters.
Definition: juce_String.h:300
String::CharPointerType text
The text that is referenced.
virtual size_t readIntoMemoryBlock(MemoryBlock &destBlock, ssize_t maxNumBytesToRead=-1)
Reads from the stream and appends the data to a MemoryBlock.
An input stream that reads from a local file.
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
Joins the strings in the array together into one string.
String upToFirstOccurrenceOf(StringRef substringToEndWith, bool includeSubStringInResult, bool ignoreCase) const
Returns the start of this string, up to the first occurrence of a substring.
bool setExecutePermission(bool shouldBeExecutable) const
Changes the execute-permissions of a file.
Definition: juce_File.cpp:274
File getNonexistentChildFile(const String &prefix, const String &suffix, bool putNumbersInBrackets=true) const
Chooses a filename relative to this one that doesn&#39;t already exist.
Definition: juce_File.cpp:606
static String addTrailingSeparator(const String &path)
Adds a separator character to the end of a path if it doesn&#39;t already have one.
Definition: juce_File.cpp:227
static void JUCE_CALLTYPE writeToLog(const String &message)
Writes a string to the current logger.
Definition: juce_Logger.cpp:40
int64 getVolumeTotalSize() const
Returns the total size of the drive that contains this file.
bool startsWithChar(juce_wchar character) const noexcept
Tests whether the string begins with a particular character.
Time getCreationTime() const
Returns the time that this file was created.
Definition: juce_File.cpp:534
URL getParentURL() const
Attempts to return a URL which is the parent folder containing this URL.
Definition: juce_URL.cpp:433
int64 getBytesFreeOnVolume() const
Returns the number of bytes free on the drive that this file lives on.
An output stream that writes into a local file.
String getFileNameWithoutExtension() const
Returns the last part of the filename, without its file extension.
Definition: juce_File.cpp:371
The folder in which applications store their persistent user-specific settings.
Definition: juce_File.h:862
bool openedOk() const noexcept
Returns true if the stream opened without problems.
static StringRef getSeparatorString()
The system-specific file separator character, as a string.
int hashCode() const noexcept
Generates a probably-unique 32-bit hashcode from this string.
bool isOnCDRomDrive() const
Returns true if this file is on a CD or DVD drive.
static File createTempFile(StringRef fileNameEnding)
Returns a temporary file in the system&#39;s temp directory.
Definition: juce_File.cpp:946
static bool areFileNamesCaseSensitive()
Indicates whether filenames are case-sensitive on the current operating system.
Definition: juce_File.cpp:238
int lastIndexOfChar(juce_wchar character) const noexcept
Searches for a character inside this string (working backwards from the end of the string)...
int size() const noexcept
Returns the number of strings in the array.
AccessMode
The read/write flags used when opening a memory mapped file.
int hashCode() const
Returns a 32-bit hash-code that identifies this file.
Definition: juce_File.cpp:398
bool startAsProcess(const String &parameters=String()) const
Launches the file as a process.
Definition: juce_File.cpp:723
bool operator>(const File &) const
Compares the pathnames for two files.
Definition: juce_File.cpp:259
bool isDirectory() const
Checks whether the file is a directory that exists.
String getNativeLinkedTarget() const
This returns the native path that the symbolic link points to.
int indexOfChar(juce_wchar characterToLookFor) const noexcept
Searches for a character inside this string.
int compare(const String &other) const noexcept
Case-sensitive comparison with another string.
static File getCurrentWorkingDirectory()
Returns the current working directory.
File()=default
Creates an (invalid) file object.
int length() const noexcept
Returns the number of characters in the string.
bool failedToOpen() const noexcept
Returns true if the stream couldn&#39;t be opened for some reason.
A class to hold a resizable block of raw data.
Holds an absolute date and time.
Definition: juce_Time.h:40
size_t getSize() const noexcept
Returns the number of bytes of data that are available for reading or writing.
static File JUCE_CALLTYPE getSpecialLocation(const SpecialLocationType type)
Finds the location of a special type of file or directory, such as a home folder or documents folder...
MemoryMappedFile(const File &file, AccessMode mode, bool exclusive=false)
Opens a file and maps it to an area of virtual memory.
Definition: juce_File.cpp:1014
File getNonexistentSibling(bool putNumbersInBrackets=true) const
Chooses a filename for a sibling file to this one that doesn&#39;t already exist.
Definition: juce_File.cpp:658
File getLinkedTarget() const
If this file is a link or alias, this returns the file that it points to.
Definition: juce_File.cpp:1004
bool next()
Moves the iterator along to the next file.
bool isOnHardDisk() const
Returns true if this file is on a hard disk.
const String & getFullPathName() const noexcept
Returns the complete, absolute path of this file.
Definition: juce_File.h:153
int getNumberOfChildFiles(int whatToLookFor, const String &wildCardPattern="*") const
Searches inside a directory and counts how many files match a wildcard pattern.
Definition: juce_File.cpp:586
void appendCharPointer(CharPointerType startOfTextToAppend, CharPointerType endOfTextToAppend)
Appends a string to the end of this one.
bool setAsCurrentWorkingDirectory() const
Sets the current working directory to be this file.
bool deleteRecursively(bool followSymlinks=false) const
Deletes a file or directory and all its subdirectories.
Definition: juce_File.cpp:279
bool startsWith(StringRef text) const noexcept
Tests whether the string begins with another string.
Returns the file that was invoked to launch this executable.
Definition: juce_File.h:916
Returns this application&#39;s location.
Definition: juce_File.h:909
virtual String readEntireStreamAsString()
Tries to read the whole stream and turn it into a string.
Represents a URL and has a bunch of useful functions to manipulate it.
Definition: juce_URL.h:41
static juce_wchar getSeparatorChar()
The system-specific file separator character.
Wraps a pointer to a null-terminated UTF-8 character string, and provides various methods to operate ...
The folder that should be used for temporary files.
Definition: juce_File.h:886