Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_FileIOHelper.c
Go to the documentation of this file.
2{
3 protected static const string PATH_DELIMITER = SCR_StringHelper.SLASH; // accepted under Windows too
4 protected static const string FORBIDDEN_FILENAME_CHARS_WINDOWS = "*/\\<>:|?\t\r\n\"";
5 protected static const string FORBIDDEN_FILENAME_CHARS_LINUX = SCR_StringHelper.SLASH;
6
7 protected static const ref array<ref SCR_FileInfo> FOUND_FILEINFOS = {};
8
9 //------------------------------------------------------------------------------------------------
14 [Obsolete("Use FileIO.MakeDirectory instead")]
15 static bool CreateDirectory(string absoluteDirectory)
16 {
17 if (SCR_StringHelper.IsEmptyOrWhiteSpace(absoluteDirectory))
18 return false;
19
20 if (FileIO.FileExists(absoluteDirectory))
21 return true;
22
23 absoluteDirectory.Replace("\\", PATH_DELIMITER);
24 absoluteDirectory = SCR_StringHelper.ReplaceRecursive(absoluteDirectory, PATH_DELIMITER + PATH_DELIMITER, PATH_DELIMITER);
25
26 if (FileIO.FileExists(absoluteDirectory))
27 return true;
28
29 array<string> pieces = {};
30 absoluteDirectory.Split(PATH_DELIMITER, pieces, true);
31
32 if (pieces.Count() < 2)
33 {
34 Print("Cannot create directory " + absoluteDirectory + "; not enough directories", LogLevel.DEBUG);
35 return false;
36 }
37
38 string path = pieces[0]; // C: part on Windows
39 for (int i = 1, count = pieces.Count(); i < count; i++)
40 {
41 path += PATH_DELIMITER + pieces[i];
42
43 if (FileIO.FileExists(path))
44 continue;
45
46 if (!FileIO.MakeDirectory(path))
47 {
48 Print("Cannot create directory " + absoluteDirectory + "; blocked at " + path, LogLevel.DEBUG);
49 return false;
50 }
51 }
52
53 return true;
54 }
55
56 //------------------------------------------------------------------------------------------------
61 static array<string> FindFiles(string directoryPath, string extension)
62 {
63 array<string> result = {};
64 FileIO.FindFiles(result.Insert, directoryPath, extension);
65 return result;
66 }
67
68 //------------------------------------------------------------------------------------------------
74 [Obsolete("Use CopyFile instead")] // 2025-05-14
75 static bool Copy(string source, string destination, bool overwrite = true)
76 {
77 array<string> content = ReadFileContent(source);
78 if (!content)
79 {
80 Print("Cannot get file content - " + source, LogLevel.ERROR);
81 return false;
82 }
83
84#ifdef WORKBENCH
85 string absolutePath;
86 if (!FilePath.IsAbsolutePath(destination) && !Workbench.GetAbsolutePath(destination, absolutePath, false))
87 {
88 Print("Cannot get destination's absolute file path - " + destination, LogLevel.WARNING);
89 return false;
90 }
91#endif // WORKBENCH
92
93 if (!overwrite && FileIO.FileExists(destination))
94 {
95 Print("Not allowed to overwrite file - " + destination, LogLevel.WARNING);
96 return false;
97 }
98
99 if (!WriteFileContent(destination, content))
100 {
101 Print("Cannot write file - " + destination, LogLevel.ERROR);
102 return false;
103 }
104
105 return true;
106 }
107
108 //------------------------------------------------------------------------------------------------
113 static bool CopyFile(string sourceFile, string destinationFile)
114 {
115 if (!FileIO.FileExists(sourceFile))
116 return false;
117
118 if (FileIO.CopyFile(sourceFile, destinationFile))
119 return true;
120
121 if (!FileIO.MakeDirectory(FilePath.StripFileName(destinationFile)))
122 return false;
123
124 return FileIO.CopyFile(sourceFile, destinationFile);
125 }
126
127 //------------------------------------------------------------------------------------------------
132 static bool CopyDirectory(string sourceDirectory, string destinationDirectory)
133 {
134#ifdef WORKBENCH
135 if (!Workbench.GetAbsolutePath(sourceDirectory, sourceDirectory, true))
136 {
137 Print("Wrong sourceDirectory provided", LogLevel.WARNING);
138 return false;
139 }
140
141 if (!Workbench.GetAbsolutePath(destinationDirectory, destinationDirectory, false))
142 {
143 Print("Wrong destinationDirectory provided", LogLevel.WARNING);
144 return false;
145 }
146#else // WORKBENCH
147 if (!FileIO.FileExists(sourceDirectory))
148 {
149 Print("Wrong sourceDirectory provided", LogLevel.WARNING);
150 return false;
151 }
152
153 if (!FileIO.FileExists(destinationDirectory))
154 {
155 Print("Wrong destinationDirectory provided", LogLevel.WARNING);
156 return false;
157 }
158#endif // WORKBENCH
159
160 array<ref SCR_FileInfo> directoryContent = GetDirectoryContent(sourceDirectory);
161 if (!directoryContent)
162 {
163 Print("Cannot get files from directory " + sourceDirectory, LogLevel.WARNING);
164 return false;
165 }
166
167 if (directoryContent.IsEmpty())
168 {
169 if (FileIO.FileExists(destinationDirectory))
170 return true;
171
172 return FileIO.MakeDirectory(destinationDirectory);
173 }
174
175 if (!FileIO.MakeDirectory(destinationDirectory))
176 {
177 Print("Cannot create " + destinationDirectory, LogLevel.ERROR);
178 return false;
179 }
180
181 bool result = true;
182
183 int sourceDirectoryLength = sourceDirectory.Length();
184 array<string> isDirCheck = {};
185 foreach (SCR_FileInfo fileInfo : directoryContent)
186 {
187 string newAbsPath = destinationDirectory + fileInfo.m_sFilePath.Substring(sourceDirectoryLength, fileInfo.m_sFilePath.Length() - sourceDirectoryLength);
188
189 if ((fileInfo.m_eAttributes | FileAttribute.DIRECTORY) == fileInfo.m_eAttributes)
190 {
191 if (!FileIO.MakeDirectory(fileInfo.m_sFilePath)) // returns true if the directory exists
192 {
193 PrintFormat("Cannot create directory %1", fileInfo.m_sFilePath, level: LogLevel.ERROR);
194 result = false;
195 }
196
197 continue;
198 }
199
200 // it is a file
201
202 string newAbsFileDir = FilePath.StripFileName(newAbsPath);
203 if (!FileIO.MakeDirectory(newAbsFileDir)) // returns true if the directory exists
204 {
205 PrintFormat("Cannot create directory %1", newAbsFileDir, level: LogLevel.ERROR);
206 result = false;
207 }
208
209 if (!FileIO.CopyFile(fileInfo.m_sFilePath, newAbsPath)) // CopyFile requires the directory to exist
210 {
211 PrintFormat("Cannot copy '%1' to '%2'", fileInfo.m_sFilePath, newAbsPath, level: LogLevel.ERROR);
212 result = false;
213 }
214 }
215
216 return result;
217 }
218
219 //------------------------------------------------------------------------------------------------
224 static bool RenameFile(string sourceFile, string destinationFile)
225 {
226 return FileIO.CopyFile(sourceFile, destinationFile) && FileIO.DeleteFile(sourceFile);
227 }
228
229 //------------------------------------------------------------------------------------------------
234 static string GetFileStringContent(string filePath, bool printWarning = true)
235 {
236 FileHandle fileHandle = FileIO.OpenFile(filePath, FileMode.READ);
237 if (!fileHandle)
238 {
239 if (printWarning)
240 Print("Cannot open/read " + filePath, LogLevel.WARNING);
241
242 return string.Empty;
243 }
244
245 string result;
246 fileHandle.Read(result, -1);
247 fileHandle.Close();
248
249 return result;
250 }
251
252 //------------------------------------------------------------------------------------------------
256 static array<ref SCR_FileInfo> GetDirectoryContent(string directory, string extension = "")
257 {
258 if (!FileIO.FindFiles(FindFilesCallbackMethod, directory, extension))
259 return null;
260
261 array<ref SCR_FileInfo> result = SCR_ArrayHelperRefT<SCR_FileInfo>.GetCopy(FOUND_FILEINFOS);
262 FOUND_FILEINFOS.Clear();
263
264 return result;
265 }
266
267 //------------------------------------------------------------------------------------------------
272 static array<string> ReadFileContent(string filePath, bool printWarning = true)
273 {
274 FileHandle fileHandle = FileIO.OpenFile(filePath, FileMode.READ);
275 if (!fileHandle)
276 {
277 if (printWarning)
278 Print("Cannot open/read " + filePath, LogLevel.WARNING);
279
280 return null;
281 }
282
283 string lineContent;
284 array<string> result = {};
285 while (fileHandle.ReadLine(lineContent) > -1)
286 {
287 result.Insert(lineContent);
288 }
289
290 fileHandle.Close();
291
292 return result;
293 }
294
295 //------------------------------------------------------------------------------------------------
301 static bool WriteFileContent(string filePath, notnull array<string> lines)
302 {
303 FileHandle fileHandle = FileIO.OpenFile(filePath, FileMode.WRITE);
304 if (!fileHandle)
305 {
306 Print("Cannot open/write " + filePath, LogLevel.WARNING);
307 return false;
308 }
309
310 int linesCountMinusOne = lines.Count() - 1;
311 if (linesCountMinusOne == -1)
312 {
313 fileHandle.Write(string.Empty); // needed?
314 }
315 else
316 {
317 foreach (int lineNumber, string line : lines)
318 {
319 if (lineNumber < linesCountMinusOne)
320 fileHandle.WriteLine(line);
321 }
322
323 // avoid final line return due to WriteLine
324 fileHandle.Write(lines[linesCountMinusOne]);
325 }
326
327 fileHandle.Close();
328
329 return true;
330 }
331
332 //------------------------------------------------------------------------------------------------
338 static bool AppendFileContent(string filePath, notnull array<string> lines)
339 {
340 if (!FileIO.FileExists(filePath))
341 return WriteFileContent(filePath, lines);
342
343 FileHandle fileHandle = FileIO.OpenFile(filePath, FileMode.APPEND);
344 if (!fileHandle)
345 {
346 Print("Cannot open/append " + filePath, LogLevel.WARNING);
347 return false;
348 }
349
350 int linesCountMinusOne = lines.Count() - 1;
351 if (linesCountMinusOne == -1)
352 {
353 fileHandle.Write(string.Empty); // needed?
354 }
355 else
356 {
357 // add a line return before appending the provided lines
358 fileHandle.Write("\n");
359
360 foreach (int lineNumber, string line : lines)
361 {
362 if (lineNumber < linesCountMinusOne)
363 fileHandle.WriteLine(line);
364 }
365
366 // avoid final line return due to WriteLine
367 fileHandle.Write(lines[linesCountMinusOne]);
368 }
369
370 fileHandle.Close();
371
372 return true;
373 }
374
375 //------------------------------------------------------------------------------------------------
379 static bool IsValidFileName(string fileName)
380 {
381 bool isWindowsBased = IsWindowsBased();
382 if (isWindowsBased)
383 {
384 if (fileName.EndsWith("."))
385 return false;
386
387 if (fileName.EndsWith(" "))
388 return false;
389 }
390
391 string forbiddenCharacters;
392 if (isWindowsBased)
393 forbiddenCharacters = FORBIDDEN_FILENAME_CHARS_WINDOWS;
394 else
395 forbiddenCharacters = FORBIDDEN_FILENAME_CHARS_LINUX;
396
397 for (int i, len = forbiddenCharacters.Length(); i < len; i++)
398 {
399 if (fileName.Contains(forbiddenCharacters[i]))
400 return false;
401 }
402
403 return true;
404 }
405
406 //------------------------------------------------------------------------------------------------
410 static string SanitiseFileName(string fileName)
411 {
412 string forbiddenCharacters;
413 bool isWindowsBased = IsWindowsBased();
414 if (isWindowsBased)
415 forbiddenCharacters = FORBIDDEN_FILENAME_CHARS_WINDOWS;
416 else
417 forbiddenCharacters = FORBIDDEN_FILENAME_CHARS_LINUX;
418
419 fileName = FilePath.StripPath(fileName);
420 fileName = SCR_StringHelper.Filter(fileName, forbiddenCharacters, true);
421
422 fileName.TrimInPlace();
423 if (fileName.IsEmpty())
424 return string.Empty;
425
426 if (isWindowsBased)
427 {
428 int originalLength = fileName.Length();
429 int properLength = originalLength;
430 string lastChar = fileName[properLength - 1];
431
432 while (lastChar == "." || lastChar == " " || lastChar == "\t")
433 {
434 --properLength;
435 if (properLength < 1)
436 break;
437
438 lastChar = fileName[properLength - 1];
439 }
440
441 if (properLength < 1)
442 return string.Empty;
443
444 if (properLength != originalLength)
445 fileName = fileName.Substring(0, properLength);
446 }
447
448 fileName.TrimInPlace();
449
450 return fileName;
451 }
452
453 //------------------------------------------------------------------------------------------------
455 protected static bool IsWindowsBased()
456 {
457 EPlatform platform = System.GetPlatform();
458
459 return platform == EPlatform.WINDOWS
460 || platform == EPlatform.XBOX_ONE
461 || platform == EPlatform.XBOX_ONE_S
462 || platform == EPlatform.XBOX_ONE_X
463 || platform == EPlatform.XBOX_SERIES_S
464 || platform == EPlatform.XBOX_SERIES_X;
465 }
466
467 //------------------------------------------------------------------------------------------------
468 // FindFilesCallback
469 protected static void FindFilesCallbackMethod(string fileName, FileAttribute attributes = 0, string filesystem = string.Empty)
470 {
471 SCR_FileInfo fileInfo = new SCR_FileInfo();
472 fileInfo.m_sFilePath = fileName;
473 fileInfo.m_eAttributes = attributes;
474 fileInfo.m_sFileSystem = filesystem;
475 FOUND_FILEINFOS.Insert(fileInfo);
476 }
477
478 //------------------------------------------------------------------------------------------------
483 {
484 return rn.Substring(0, rn.IndexOf("}") + 1) + FilePath.StripPath(rn.GetPath());
485 }
486
487 //------------------------------------------------------------------------------------------------
488 // constructor
489 protected void SCR_FileIOHelper();
490}
491
492class SCR_FileInfo
493{
497}
string path
class RestAPIHelper< JsonApiStruct T > content
string m_sFileSystem
FileAttribute m_eAttributes
class SCR_FileIOHelper m_sFilePath
static bool CopyDirectory(string sourceDirectory, string destinationDirectory)
static bool AppendFileContent(string filePath, notnull array< string > lines)
static bool CreateDirectory(string absoluteDirectory)
static bool CopyFile(string sourceFile, string destinationFile)
static string GetFileStringContent(string filePath, bool printWarning=true)
static const string FORBIDDEN_FILENAME_CHARS_LINUX
static array< string > FindFiles(string directoryPath, string extension)
static bool RenameFile(string sourceFile, string destinationFile)
static string GetShortResourceName(ResourceName rn)
static const string PATH_DELIMITER
static string SanitiseFileName(string fileName)
static const ref array< ref SCR_FileInfo > FOUND_FILEINFOS
static bool WriteFileContent(string filePath, notnull array< string > lines)
static array< ref SCR_FileInfo > GetDirectoryContent(string directory, string extension="")
static bool IsValidFileName(string fileName)
static array< string > ReadFileContent(string filePath, bool printWarning=true)
static const string FORBIDDEN_FILENAME_CHARS_WINDOWS
static bool Copy(string source, string destination, bool overwrite=true)
static void FindFilesCallbackMethod(string fileName, FileAttribute attributes=0, string filesystem=string.Empty)
void SCR_FileIOHelper()
static bool IsWindowsBased()
static string Filter(string input, string characters, bool useCharactersAsBlacklist=false)
static string ReplaceRecursive(string input, string sample, string replacement)
static bool IsEmptyOrWhiteSpace(string input)
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
proto void PrintFormat(string fmt, void param1=NULL, void param2=NULL, void param3=NULL, void param4=NULL, void param5=NULL, void param6=NULL, void param7=NULL, void param8=NULL, void param9=NULL, LogLevel level=LogLevel.NORMAL)
FileMode
Mode for opening file. See FileSystem::Open.
Definition FileMode.c:14
EPlatform
Definition EPlatform.c:13
FileAttribute
File attributes. See FileDescription.