DotNetDupe 4.0.6
C++17/20 Implementation of the .NET Base Class Library (BCL)
Loading...
Searching...
No Matches
File.cpp
Go to the documentation of this file.
1#include "pch.h"
2#include "System/IO/File.h"
3#include <fstream>
4#include <sstream>
5#include <filesystem>
6#include <vector>
9
10#if defined(_WIN32)
11#include "Win32Internal.h"
12using namespace DotNetDupe::System::Internal;
13#endif
14
15namespace fs = std::filesystem;
16
17namespace {
18 fs::path ToFsPath(const DotNetDupe::System::String& sPath) {
20#if defined(_WIN32)
22#else
23 return fs::path(sPath.GetRawString());
24#endif
25 }
26}
27
28namespace DotNetDupe {
29 namespace System {
30 namespace IO {
31 bool File::Exists(const String& sPath) {
33 return fs::exists(ToFsPath(sPath));
34 }
35
38 std::ifstream fileStream(ToFsPath(sPath), std::ios::binary);
39 if (!fileStream.is_open()) {
40 throw IO::IOException("Failed to open file for reading.");
41 }
42
44 std::stringstream buffer;
45 buffer << fileStream.rdbuf();
46 std::string charContent = buffer.str();
47
48 Array<char> bytes((int)charContent.size());
49 for (int iIdx = 0; iIdx < (int)charContent.size(); iIdx++) bytes[iIdx] = charContent[iIdx];
50 return Text::TextEncoding::UTF8()->GetString(bytes);
51 }
52
53 void File::WriteAllText(const String& sPath, const String& sContents) {
54 Array<char> contentBytes = Text::TextEncoding::UTF8()->GetBytes(sContents);
55
56 std::ofstream fileStream(ToFsPath(sPath), std::ios::binary);
57 if (!fileStream.is_open()) {
58 throw IO::IOException("Failed to open file for writing.");
59 }
60 fileStream.write(contentBytes.GetData(), contentBytes.GetLength());
61 }
62
63 void File::Copy(const String& sSourceFileName, const String& sDestFileName, bool bOverwrite) {
64 fs::copy_options options = fs::copy_options::none;
65 if (bOverwrite) options |= fs::copy_options::overwrite_existing;
66
67 try {
68 fs::copy(ToFsPath(sSourceFileName), ToFsPath(sDestFileName), options);
69 } catch (const std::exception& ex) {
70 throw IO::IOException(ex.what());
71 }
72 }
73
74 void File::Move(const String& sSourceFileName, const String& sDestFileName) {
75 try {
76 fs::rename(ToFsPath(sSourceFileName), ToFsPath(sDestFileName));
77 } catch (const std::exception& ex) {
78 throw IO::IOException(ex.what());
79 }
80 }
81
82 void File::Delete(const String& sPath) {
83 try {
84 fs::remove(ToFsPath(sPath));
85 } catch (const std::exception& ex) {
86 throw IO::IOException(ex.what());
87 }
88 }
89
90 void File::AppendAllText(const String& sPath, const String& sContents) {
91 Array<char> contentBytes = Text::TextEncoding::UTF8()->GetBytes(sContents);
92 std::ofstream fileStream(ToFsPath(sPath), std::ios::binary | std::ios_base::app);
93 if (!fileStream.is_open()) {
94 throw IO::IOException("Failed to open file for writing.");
95 }
96 fileStream.write(contentBytes.GetData(), contentBytes.GetLength());
97 }
98
99 void File::AppendAllLines(const String& sPath, const Array<String>& sContents) {
100 std::ofstream fileStream(ToFsPath(sPath), std::ios::binary | std::ios_base::app);
101 if (!fileStream.is_open()) {
102 throw IO::IOException("Failed to open file for writing.");
103 }
104 for (int iIdx = 0; iIdx < sContents.GetLength(); iIdx++) {
105 const auto& line = sContents[iIdx];
106 Array<char> lineBytes = Text::TextEncoding::UTF8()->GetBytes(line);
107 fileStream.write(lineBytes.GetData(), lineBytes.GetLength());
108 fileStream << "\n";
109 }
110 }
111
113 std::vector<String> tempLines;
114 std::ifstream fileStream(ToFsPath(sPath), std::ios::binary);
115 if (!fileStream.is_open()) {
116 throw IO::IOException("Failed to open file for reading.");
117 }
118 std::string line;
119 while (std::getline(fileStream, line)) {
120 Array<char> lineBytes((int)line.size());
121 for (int iIdx = 0; iIdx < (int)line.size(); iIdx++) lineBytes[iIdx] = line[iIdx];
122 tempLines.push_back(Text::TextEncoding::UTF8()->GetString(lineBytes));
123 }
124
125 Array<String> lines((int)tempLines.size());
126 for (int iIdx = 0; iIdx < (int)tempLines.size(); iIdx++) lines[iIdx] = tempLines[iIdx];
127 return lines;
128 }
129
130 void File::WriteAllLines(const String& sPath, const Array<String>& sContents) {
131 std::ofstream fileStream(ToFsPath(sPath), std::ios::binary);
132 if (!fileStream.is_open()) {
133 throw IO::IOException("Failed to open file for writing.");
134 }
135 for (int iIdx = 0; iIdx < sContents.GetLength(); iIdx++) {
136 const auto& line = sContents[iIdx];
137 Array<char> lineBytes = Text::TextEncoding::UTF8()->GetBytes(line);
138 fileStream.write(lineBytes.GetData(), lineBytes.GetLength());
139 fileStream << "\n";
140 }
141 }
142
143 void File::Create(const String& sPath) {
144 std::ofstream fileStream(ToFsPath(sPath));
145 if (!fileStream.is_open()) {
146 throw IO::IOException("Failed to open file for writing.");
147 }
148 }
149
150#if !defined(_WIN32)
151 static int ComputeLinuxFileAttributes(const fs::path& pPath, const fs::file_status& statusInfo) {
152 int iAttrs = static_cast<int>(FileAttributes::Normal);
153 if ((statusInfo.permissions() & fs::perms::owner_write) == fs::perms::none) iAttrs |= static_cast<int>(FileAttributes::ReadOnly);
154 if (fs::is_directory(statusInfo)) iAttrs |= static_cast<int>(FileAttributes::Directory);
155 if (!pPath.filename().empty() && pPath.filename().string()[0] == '.') iAttrs |= static_cast<int>(FileAttributes::Hidden);
156 return iAttrs;
157 }
158
159 static fs::perms ComputeLinuxFilePermissions(FileAttributes eAttributes, fs::perms permsCurrent) {
160 if ((static_cast<int>(eAttributes) & static_cast<int>(FileAttributes::ReadOnly)) != 0) {
161 return permsCurrent & ~(fs::perms::owner_write | fs::perms::group_write | fs::perms::others_write);
162 }
163 return permsCurrent | fs::perms::owner_write;
164 }
165#endif
166
167 bool File::GetAttributes(const String& sPath, FileAttributes& eAttributes) {
168 #if defined(_WIN32)
169 std::wstring sWPath = Utf8ToWChar(sPath.GetRawString());
170 DWORD iAttrs = GetFileAttributesW(sWPath.c_str());
171 if (iAttrs == INVALID_FILE_ATTRIBUTES) return false;
172 eAttributes = static_cast<FileAttributes>(iAttrs);
173 return true;
174 #else
175 fs::path pPath = ToFsPath(sPath);
176 std::error_code ec;
177 auto statusInfo = fs::status(pPath, ec);
178 if (ec) return false;
179 eAttributes = static_cast<FileAttributes>(ComputeLinuxFileAttributes(pPath, statusInfo));
180 return true;
181 #endif
182 }
183
184 bool File::SetAttributes(const String& sPath, FileAttributes eAttributes) {
185 #if defined(_WIN32)
186 std::wstring sWPath = Utf8ToWChar(sPath.GetRawString());
187 return ::SetFileAttributesW(sWPath.c_str(), static_cast<DWORD>(eAttributes)) != FALSE;
188 #else
189 fs::path pPath = ToFsPath(sPath);
190 std::error_code ec;
191 auto statusInfo = fs::status(pPath, ec);
192 if (ec) return false;
193 fs::permissions(pPath, ComputeLinuxFilePermissions(eAttributes, statusInfo.permissions()), fs::perm_options::replace, ec);
194 return !ec;
195 #endif
196 }
197 }
198 }
199}
Provides static methods for the creation, copying, deletion, moving, and opening of a single file.
The exception that is thrown when an I/O error occurs.
Represents character encodings and code page conversions.
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Definition Array.h:29
int GetLength() const
Gets the total number of elements in all dimensions of the Array.
Definition Array.h:142
T * GetData()
Gets a pointer to the contiguous internal element buffer.
Definition Array.h:146
static bool GetAttributes(const String &sPath, FileAttributes &attrAttributes)
Definition File.cpp:167
static void Copy(const String &sSourceFileName, const String &sDestFileName, bool bOverwrite)
Copies an existing file to a new file, allowing overwriting of an existing file.
Definition File.cpp:63
static bool SetAttributes(const String &sPath, FileAttributes attrAttributes)
Definition File.cpp:184
static void WriteAllText(const String &sPath, const String &sContents)
Creates a new file, writes the specified string to the file, and then closes the file.
Definition File.cpp:53
static bool Exists(const String &sPath)
Determines whether the specified file exists.
Definition File.cpp:31
static void AppendAllText(const String &sPath, const String &sContents)
Definition File.cpp:90
static String ReadAllText(const String &sPath)
Opens a text file, reads all the text in the file, and then closes the file.
Definition File.cpp:36
static void AppendAllLines(const String &sPath, const Array< String > &sContents)
Definition File.cpp:99
static void WriteAllLines(const String &sPath, const Array< String > &sContents)
Definition File.cpp:130
static void Delete(const String &sPath)
Deletes the specified file.
Definition File.cpp:82
static void Create(const String &sPath)
Definition File.cpp:143
static void Move(const String &sSourceFileName, const String &sDestFileName)
Moves a specified file to a new location.
Definition File.cpp:74
static Array< String > ReadAllLines(const String &sPath)
Definition File.cpp:112
The exception that is thrown when an I/O error occurs.
Definition IOException.h:17
static std::wstring Utf8ToWChar(const char *pUtf8Str)
Represents text as a sequence of UTF-8 code units with culture-invariant operations.
Definition String.h:74
const char * GetRawString() const
Definition String.cpp:230
static EncodingPtr UTF8()
Gets an encoding for the UTF-8 format.
FileAttributes
Provides attributes for files and directories.
Definition File.h:16
std::wstring Utf8ToWChar(const char *pUtf8Str)