39 : fullPath (other.fullPath)
45 fullPath = parseAbsolutePath (
newPath);
51 fullPath = other.fullPath;
56 : fullPath (std::move (other.fullPath))
62 fullPath = std::move (other.fullPath);
79 bool anythingChanged =
false;
81 for (
int i = 1; i < toks.
size(); ++i)
85 if (t ==
".." && toks[i - 1] !=
"..")
87 anythingChanged =
true;
93 anythingChanged =
true;
105static String normaliseSeparators (
const String& path)
107 auto normalisedPath = path;
110 String doubleSeparator (separator + separator);
112 auto uncPath = normalisedPath.startsWith (doubleSeparator)
113 && ! normalisedPath.fromFirstOccurrenceOf (doubleSeparator,
false,
false).startsWith (separator);
116 normalisedPath = normalisedPath.fromFirstOccurrenceOf (doubleSeparator,
false,
false);
118 while (normalisedPath.contains (doubleSeparator))
119 normalisedPath = normalisedPath.replace (doubleSeparator, separator);
121 return uncPath ? doubleSeparator + normalisedPath
137 auto path = normaliseSeparators (removeEllipsis (p.
replaceCharacter (
'/',
'\\')));
155 else if (! path.containsChar (
':'))
176 auto path = normaliseSeparators (removeEllipsis (p));
178 if (path.startsWithChar (
'~'))
184 + path.substring (1);
189 auto userName = path.substring (1).upToFirstOccurrenceOf (
"/",
false,
false);
191 if (
auto* pw = getpwnam (userName.toUTF8()))
197 #if JUCE_DEBUG || JUCE_LOG_ASSERTIONS
198 if (! (path.startsWith (
"./") || path.startsWith (
"../")))
209 #if JUCE_LOG_ASSERTIONS
220 path = path.dropLastCharacters (1);
232#if JUCE_LINUX || JUCE_BSD
233 #define NAMES_ARE_CASE_SENSITIVE 1
238 #if NAMES_ARE_CASE_SENSITIVE
247 #if NAMES_ARE_CASE_SENSITIVE
283 worked = f.deleteRecursively (followSymlinks) &&
worked;
290 if (
newFile.fullPath == fullPath)
296 #if ! NAMES_ARE_CASE_SENSITIVE
313 if (
newFile.fullPath == fullPath)
319 if (! replaceInternal (
newFile))
331 if (! f.copyFileTo (
newDirectory.getChildFile (f.getFileName())))
335 if (! f.copyDirectoryTo (
newDirectory.getChildFile (f.getFileName())))
345String File::getPathUpToLastSlash()
const
363bool File::isNonEmptyDirectory()
const
393 auto ourPath = getPathUpToLastSlash();
432 auto path = fullPath;
473 path.appendCharPointer (r);
488 if (bytes == 1) {
suffix =
" byte"; }
489 else if (bytes < 1024) {
suffix =
" bytes"; }
490 else if (bytes < 1024 * 1024) {
suffix =
" KB";
divisor = 1024.0; }
491 else if (bytes < 1024 * 1024 * 1024) {
suffix =
" MB";
divisor = 1024.0 * 1024.0; }
562 return in.openedOk() ?
in.readEntireStreamAsString()
585 results.add (
di.getFile());
611 bool putNumbersInBrackets)
const
621 if (
prefix.trim().endsWithChar (
')'))
623 putNumbersInBrackets =
true;
641 if (putNumbersInBrackets)
643 newName <<
'(' << ++
number <<
')';
655 }
while (f.exists());
668 putNumbersInBrackets);
701 return fullPath[
dotPos] ==
'.';
734 auto fin = std::make_unique<FileInputStream> (*
this);
744 auto fout = std::make_unique<FileOutputStream> (*
this, bufferSize);
746 if (
fout->openedOk())
773 return tempFile.overwriteTargetFileWithTemporary();
780 if (
fout.failedToOpen())
790 return tempFile.overwriteTargetFileWithTemporary();
802 if (
in1.openedOk() &&
in2.openedOk())
804 const int bufferSize = 4096;
833 if (s.isNotEmpty() && s[1] ==
':')
845 auto s =
original.removeCharacters (
"\"#@,;:<>*^|?\\/");
848 auto len = s.length();
852 auto lastDot = s.lastIndexOfChar (
'.');
869static int countNumberOfSeparators (String::CharPointerType s)
875 auto c = s.getAndAdvance();
913 #if NAMES_ARE_CASE_SENSITIVE
981 #if JUCE_MAC || JUCE_LINUX || JUCE_BSD
1018#if JUCE_ALLOW_STATIC_NULL_VARIABLES
1020JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wdeprecated-declarations")
1021JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
1025JUCE_END_IGNORE_WARNINGS_GCC_LIKE
1026JUCE_END_IGNORE_WARNINGS_MSVC
1032 : range (0, file.getSize())
1034 openInternal (file, mode, exclusive);
1038 : range (
fileRange.getIntersectionWith (
Range<int64> (0, file.getSize())))
1040 openInternal (file, mode, exclusive);
1052 :
UnitTest (
"Files", UnitTestCategories::files)
1055 void runTest()
override
1057 beginTest (
"Reading");
1062 expect (! File().exists());
1063 expect (! File().existsAsFile());
1064 expect (! File().isDirectory());
1066 expect (File (
"/").isDirectory());
1068 expect (home.isDirectory());
1069 expect (home.exists());
1070 expect (! home.existsAsFile());
1075 expect (home.getVolumeTotalSize() > 1024 * 1024);
1076 expect (home.getBytesFreeOnVolume() > 0);
1077 expect (! home.isHidden());
1078 expect (home.isOnHardDisk());
1079 expect (! home.isOnCDRomDrive());
1081 expect (home.setAsCurrentWorkingDirectory());
1084 auto homeParent = home;
1085 bool noSymlinks =
true;
1087 while (! homeParent.isRoot())
1089 if (homeParent.isSymbolicLink())
1095 homeParent = homeParent.getParentDirectory();
1105 expect (roots.size() > 0);
1107 int numRootsExisting = 0;
1108 for (
int i = 0; i < roots.size(); ++i)
1109 if (roots[i].exists())
1113 expect (numRootsExisting > 0);
1116 beginTest (
"Writing");
1118 auto random = getRandom();
1119 const auto tempFolderName =
"JUCE UnitTests Temp Folder "
1122 File demoFolder (temp.getChildFile (tempFolderName));
1123 expect (demoFolder.deleteRecursively());
1124 expect (demoFolder.createDirectory());
1125 expect (demoFolder.isDirectory());
1126 expect (demoFolder.getParentDirectory() == temp);
1127 expect (temp.isDirectory());
1131 File tempFile (demoFolder.getNonexistentChildFile (
"test",
".txt",
false));
1133 expect (tempFile.getFileExtension() ==
".txt");
1134 expect (tempFile.hasFileExtension (
".txt"));
1135 expect (tempFile.hasFileExtension (
"txt"));
1136 expect (tempFile.withFileExtension (
"xyz").hasFileExtension (
".xyz"));
1137 expect (tempFile.withFileExtension (
"xyz").hasFileExtension (
"abc;xyz;foo"));
1138 expect (tempFile.withFileExtension (
"xyz").hasFileExtension (
"xyz;foo"));
1139 expect (! tempFile.withFileExtension (
"h").hasFileExtension (
"bar;foo;xx"));
1140 expect (tempFile.getSiblingFile (
"foo").isAChildOf (temp));
1141 expect (tempFile.hasWriteAccess());
1143 expect (home.getChildFile (
".") == home);
1144 expect (home.getChildFile (
"..") == home.getParentDirectory());
1145 expect (home.getChildFile (
".xyz").getFileName() ==
".xyz");
1146 expect (home.getChildFile (
"..xyz").getFileName() ==
"..xyz");
1147 expect (home.getChildFile (
"...xyz").getFileName() ==
"...xyz");
1148 expect (home.getChildFile (
"./xyz") == home.getChildFile (
"xyz"));
1149 expect (home.getChildFile (
"././xyz") == home.getChildFile (
"xyz"));
1150 expect (home.getChildFile (
"../xyz") == home.getParentDirectory().getChildFile (
"xyz"));
1151 expect (home.getChildFile (
".././xyz") == home.getParentDirectory().getChildFile (
"xyz"));
1152 expect (home.getChildFile (
".././xyz/./abc") == home.getParentDirectory().getChildFile (
"xyz/abc"));
1153 expect (home.getChildFile (
"./../xyz") == home.getParentDirectory().getChildFile (
"xyz"));
1154 expect (home.getChildFile (
"a1/a2/a3/./../../a4") == home.getChildFile (
"a1/a4"));
1156 expect (! File().hasReadAccess());
1157 expect (! File().hasWriteAccess());
1159 expect (! tempFile.hasReadAccess());
1162 FileOutputStream fo (tempFile);
1163 fo.write (
"0123456789", 10);
1166 expect (tempFile.hasReadAccess());
1168 expect (tempFile.exists());
1169 expect (tempFile.getSize() == 10);
1170 expect (std::abs ((
int) (tempFile.getLastModificationTime().toMilliseconds() -
Time::getCurrentTime().toMilliseconds())) < 3000);
1171 expectEquals (tempFile.loadFileAsString(), String (
"0123456789"));
1172 expect (! demoFolder.containsSubDirectories());
1174 expectEquals (tempFile.getRelativePathFrom (demoFolder.getParentDirectory()), demoFolder.getFileName() +
File::getSeparatorString() + tempFile.getFileName());
1180 demoFolder.getNonexistentChildFile (
"tempFolder",
"",
false).createDirectory();
1183 expect (demoFolder.containsSubDirectories());
1185 expect (tempFile.hasWriteAccess());
1186 tempFile.setReadOnly (
true);
1187 expect (! tempFile.hasWriteAccess());
1188 tempFile.setReadOnly (
false);
1189 expect (tempFile.hasWriteAccess());
1192 tempFile.setLastModificationTime (t);
1193 Time t2 = tempFile.getLastModificationTime();
1194 expect (std::abs ((
int) (t2.toMilliseconds() - t.toMilliseconds())) <= 1000);
1198 tempFile.loadFileAsData (mb);
1199 expect (mb.getSize() == 10);
1200 expect (mb[0] ==
'0');
1204 expect (tempFile.getSize() == 10);
1205 FileOutputStream fo (tempFile);
1206 expect (fo.openedOk());
1208 expect (fo.setPosition (7));
1209 expect (fo.truncate().wasOk());
1210 expect (tempFile.getSize() == 7);
1211 fo.write (
"789", 3);
1213 expect (tempFile.getSize() == 10);
1216 beginTest (
"Memory-mapped files");
1220 expect (mmf.getSize() == 10);
1221 expect (mmf.getData() !=
nullptr);
1222 expect (memcmp (mmf.getData(),
"0123456789", 10) == 0);
1226 const File tempFile2 (tempFile.getNonexistentSibling (
false));
1227 expect (tempFile2.create());
1228 expect (tempFile2.appendData (
"xxxxxxxxxx", 10));
1232 expect (mmf.getSize() == 10);
1233 expect (mmf.getData() !=
nullptr);
1234 memcpy (mmf.getData(),
"abcdefghij", 10);
1239 expect (mmf.getSize() == 10);
1240 expect (mmf.getData() !=
nullptr);
1241 expect (memcmp (mmf.getData(),
"abcdefghij", 10) == 0);
1244 expect (tempFile2.deleteFile());
1247 beginTest (
"More writing");
1249 expect (tempFile.appendData (
"abcdefghij", 10));
1250 expect (tempFile.getSize() == 20);
1251 expect (tempFile.replaceWithData (
"abcdefghij", 10));
1252 expect (tempFile.getSize() == 10);
1254 File tempFile2 (tempFile.getNonexistentSibling (
false));
1255 expect (tempFile.copyFileTo (tempFile2));
1256 expect (tempFile2.exists());
1257 expect (tempFile2.hasIdenticalContentTo (tempFile));
1258 expect (tempFile.deleteFile());
1259 expect (! tempFile.exists());
1260 expect (tempFile2.moveFileTo (tempFile));
1261 expect (tempFile.exists());
1262 expect (! tempFile2.exists());
1264 expect (demoFolder.deleteRecursively());
1265 expect (! demoFolder.exists());
1268 URL url (
"https://audio.dev/foo/bar/");
1269 expectEquals (url.toString (
false), String (
"https://audio.dev/foo/bar/"));
1270 expectEquals (url.getChildURL (
"x").toString (
false), String (
"https://audio.dev/foo/bar/x"));
1271 expectEquals (url.getParentURL().toString (
false), String (
"https://audio.dev/foo"));
1272 expectEquals (url.getParentURL().getParentURL().toString (
false), String (
"https://audio.dev/"));
1273 expectEquals (url.getParentURL().getParentURL().getParentURL().toString (
false), String (
"https://audio.dev/"));
1274 expectEquals (url.getParentURL().getChildURL (
"x").toString (
false), String (
"https://audio.dev/foo/x"));
1275 expectEquals (url.getParentURL().getParentURL().getParentURL().getChildURL (
"x").toString (
false), String (
"https://audio.dev/x"));
1279 URL url (
"https://audio.dev/foo/bar");
1280 expectEquals (url.toString (
false), String (
"https://audio.dev/foo/bar"));
1281 expectEquals (url.getChildURL (
"x").toString (
false), String (
"https://audio.dev/foo/bar/x"));
1282 expectEquals (url.getParentURL().toString (
false), String (
"https://audio.dev/foo"));
1283 expectEquals (url.getParentURL().getParentURL().toString (
false), String (
"https://audio.dev/"));
1284 expectEquals (url.getParentURL().getParentURL().getParentURL().toString (
false), String (
"https://audio.dev/"));
1285 expectEquals (url.getParentURL().getChildURL (
"x").toString (
false), String (
"https://audio.dev/foo/x"));
1286 expectEquals (url.getParentURL().getParentURL().getParentURL().getChildURL (
"x").toString (
false), String (
"https://audio.dev/x"));
1291static FileTests fileUnitTests;
static juce_wchar toLowerCase(juce_wchar character) noexcept
static bool isDigit(char character) noexcept
std::unique_ptr< FileOutputStream > createOutputStream(size_t bufferSize=0x8000) const
bool replaceWithText(const String &textToWrite, bool asUnicode=false, bool writeUnicodeHeaderBytes=false, const char *lineEndings="\r\n") const
bool isSymbolicLink() const
int getNumberOfChildFiles(int whatToLookFor, const String &wildCardPattern="*") const
bool moveFileTo(const File &targetLocation) const
bool operator==(const File &) const
bool containsSubDirectories() const
Array< File > findChildFiles(int whatToLookFor, bool searchRecursively, const String &wildCardPattern="*", FollowSymlinks followSymlinks=FollowSymlinks::yes) const
static void findFileSystemRoots(Array< File > &results)
bool hasIdenticalContentTo(const File &other) const
static String createLegalPathName(const String &pathNameToFix)
static String addTrailingSeparator(const String &path)
String getFileExtension() const
Time getLastModificationTime() const
bool existsAsFile() const
bool copyFileTo(const File &targetLocation) const
bool deleteRecursively(bool followSymlinks=false) const
static File JUCE_CALLTYPE getSpecialLocation(const SpecialLocationType type)
const String & getFullPathName() const noexcept
String getFileName() const
bool replaceWithData(const void *dataToWrite, size_t numberOfBytes) const
bool setLastAccessTime(Time newTime) const
File getChildFile(StringRef relativeOrAbsolutePath) const
void readLines(StringArray &destLines) const
static bool isAbsolutePath(StringRef path)
File getSiblingFile(StringRef siblingFileName) const
bool createSymbolicLink(const File &linkFileToCreate, bool overwriteExisting) const
String getFileNameWithoutExtension() const
File getNonexistentSibling(bool putNumbersInBrackets=true) const
@ userApplicationDataDirectory
String getRelativePathFrom(const File &directoryToBeRelativeTo) const
bool appendText(const String &textToAppend, bool asUnicode=false, bool writeUnicodeHeaderBytes=false, const char *lineEndings="\r\n") const
@ findFilesAndDirectories
File getNonexistentChildFile(const String &prefix, const String &suffix, bool putNumbersInBrackets=true) const
bool operator!=(const File &) const
bool setCreationTime(Time newTime) const
static String descriptionOfSizeInBytes(int64 bytes)
bool setReadOnly(bool shouldBeReadOnly, bool applyRecursively=false) const
static File createTempFile(StringRef fileNameEnding)
static juce_wchar getSeparatorChar()
static bool areFileNamesCaseSensitive()
String loadFileAsString() const
bool operator>(const File &) const
File getLinkedTarget() const
File getParentDirectory() const
bool appendData(const void *dataToAppend, size_t numberOfBytes) const
std::unique_ptr< FileInputStream > createInputStream() const
bool operator<(const File &) const
Time getCreationTime() const
bool setExecutePermission(bool shouldBeExecutable) const
File withFileExtension(StringRef newExtension) const
static String createLegalFileName(const String &fileNameToFix)
bool replaceFileIn(const File &targetLocation) const
bool isAChildOf(const File &potentialParentDirectory) const
static File createFileWithoutCheckingPath(const String &absolutePath) noexcept
bool startAsProcess(const String ¶meters=String()) const
String getNativeLinkedTarget() const
bool hasFileExtension(StringRef extensionToTest) const
bool copyDirectoryTo(const File &newDirectory) const
bool loadFileAsData(MemoryBlock &result) const
bool setLastModificationTime(Time newTime) const
Time getLastAccessTime() const
Result createDirectory() const
static File getCurrentWorkingDirectory()
static StringRef getSeparatorString()
File & operator=(const String &newAbsolutePath)
static void JUCE_CALLTYPE writeToLog(const String &message)
MemoryMappedFile(const File &file, AccessMode mode, bool exclusive=false)
static bool JUCE_CALLTYPE openDocument(const String &documentURL, const String ¶meters)
static Random & getSystemRandom() noexcept
static Result fail(const String &errorMessage) noexcept
static Result ok() noexcept
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
int size() const noexcept
void removeRange(int startIndex, int numberToRemove)
String::CharPointerType text
static String repeatedString(StringRef stringToRepeat, int numberOfTimesToRepeat)
int indexOfChar(juce_wchar characterToLookFor) const noexcept
int length() const noexcept
bool endsWithChar(juce_wchar character) const noexcept
bool isEmpty() const noexcept
int64 hashCode64() const noexcept
bool containsChar(juce_wchar character) const noexcept
String removeCharacters(StringRef charactersToRemove) const
bool endsWithIgnoreCase(StringRef text) const noexcept
bool contains(StringRef text) const noexcept
static String toHexString(IntegerType number)
int lastIndexOfChar(juce_wchar character) const noexcept
String trimCharactersAtEnd(StringRef charactersToTrim) const
String replaceCharacter(juce_wchar characterToReplace, juce_wchar characterToInsertInstead) const
String substring(int startIndex, int endIndex) const
int hashCode() const noexcept
bool isNotEmpty() const noexcept
static Time JUCE_CALLTYPE getCurrentTime() noexcept