mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
add: add FileUtils
Moved file operations to `utils`.
This commit is contained in:
parent
49f41b8bce
commit
da284c1387
|
|
@ -101,6 +101,7 @@ list(APPEND MINECRAFT_SERVER_SOURCES
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/CliCommandList.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/CliCommandTp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/CliCommandGamemode.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Common/FileUtils.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Common/StringUtils.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/vendor/linenoise/linenoise.c"
|
||||
)
|
||||
|
|
|
|||
146
Minecraft.Server/Common/FileUtils.cpp
Normal file
146
Minecraft.Server/Common/FileUtils.cpp
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
#include "stdafx.h"
|
||||
|
||||
#include "FileUtils.h"
|
||||
|
||||
#include "StringUtils.h"
|
||||
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace ServerRuntime
|
||||
{
|
||||
namespace FileUtils
|
||||
{
|
||||
namespace
|
||||
{
|
||||
static std::wstring ToWidePath(const std::string &filePath)
|
||||
{
|
||||
return StringUtils::Utf8ToWide(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long long GetCurrentUtcFileTime()
|
||||
{
|
||||
FILETIME now = {};
|
||||
GetSystemTimeAsFileTime(&now);
|
||||
|
||||
ULARGE_INTEGER value = {};
|
||||
value.LowPart = now.dwLowDateTime;
|
||||
value.HighPart = now.dwHighDateTime;
|
||||
return value.QuadPart;
|
||||
}
|
||||
|
||||
bool ReadTextFile(const std::string &filePath, std::string *outText)
|
||||
{
|
||||
if (outText == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
outText->clear();
|
||||
|
||||
const std::wstring widePath = ToWidePath(filePath);
|
||||
if (widePath.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE *inFile = nullptr;
|
||||
if (_wfopen_s(&inFile, widePath.c_str(), L"rb") != 0 || inFile == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fseek(inFile, 0, SEEK_END) != 0)
|
||||
{
|
||||
fclose(inFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
long fileSize = ftell(inFile);
|
||||
if (fileSize < 0)
|
||||
{
|
||||
fclose(inFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fseek(inFile, 0, SEEK_SET) != 0)
|
||||
{
|
||||
fclose(inFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileSize == 0)
|
||||
{
|
||||
fclose(inFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
outText->resize((size_t)fileSize);
|
||||
size_t bytesRead = fread(&(*outText)[0], 1, (size_t)fileSize, inFile);
|
||||
fclose(inFile);
|
||||
|
||||
if (bytesRead != (size_t)fileSize)
|
||||
{
|
||||
outText->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteTextFileAtomic(const std::string &filePath, const std::string &text)
|
||||
{
|
||||
const std::wstring widePath = ToWidePath(filePath);
|
||||
if (widePath.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::wstring tmpPath = widePath + L".tmp";
|
||||
|
||||
FILE *outFile = nullptr;
|
||||
if (_wfopen_s(&outFile, tmpPath.c_str(), L"wb") != 0 || outFile == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!text.empty())
|
||||
{
|
||||
size_t bytesWritten = fwrite(text.data(), 1, text.size(), outFile);
|
||||
if (bytesWritten != text.size())
|
||||
{
|
||||
fclose(outFile);
|
||||
DeleteFileW(tmpPath.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fflush(outFile) != 0 || _commit(_fileno(outFile)) != 0)
|
||||
{
|
||||
fclose(outFile);
|
||||
DeleteFileW(tmpPath.c_str());
|
||||
return false;
|
||||
}
|
||||
fclose(outFile);
|
||||
|
||||
DWORD attrs = GetFileAttributesW(widePath.c_str());
|
||||
if (attrs != INVALID_FILE_ATTRIBUTES && ((attrs & FILE_ATTRIBUTE_DIRECTORY) == 0))
|
||||
{
|
||||
// Replace the destination without deleting the last known-good file first.
|
||||
if (ReplaceFileW(widePath.c_str(), tmpPath.c_str(), nullptr, REPLACEFILE_IGNORE_MERGE_ERRORS, nullptr, nullptr))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (MoveFileExW(tmpPath.c_str(), widePath.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Keep the temp file on failure so the original file remains recoverable and the caller can inspect the write result.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Minecraft.Server/Common/FileUtils.h
Normal file
25
Minecraft.Server/Common/FileUtils.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ServerRuntime
|
||||
{
|
||||
namespace FileUtils
|
||||
{
|
||||
/**
|
||||
* Reads the full UTF-8 path target into memory without interpreting JSON or line endings
|
||||
* UTF-8パスのテキストファイル全体をそのまま読み込む
|
||||
*/
|
||||
bool ReadTextFile(const std::string &filePath, std::string *outText);
|
||||
/**
|
||||
* Writes text through a same-directory temporary file and publishes it with a single replacement step
|
||||
* 同一ディレクトリの一時ファイル経由で安全に書き換える
|
||||
*/
|
||||
bool WriteTextFileAtomic(const std::string &filePath, const std::string &text);
|
||||
/**
|
||||
* Returns the current UTC timestamp encoded in Windows FILETIME units for expiry comparisons
|
||||
* 期限判定用に現在UTC時刻をWindows FILETIME単位で返す
|
||||
*/
|
||||
unsigned long long GetCurrentUtcFileTime();
|
||||
}
|
||||
}
|
||||
|
|
@ -37,6 +37,7 @@ namespace ServerRuntime
|
|||
int wideCount = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0);
|
||||
if (wideCount <= 0)
|
||||
{
|
||||
// Fall back to the current ANSI code page so legacy non-UTF-8 inputs remain readable.
|
||||
wideCount = MultiByteToWideChar(CP_ACP, 0, value, -1, NULL, 0);
|
||||
if (wideCount <= 0)
|
||||
{
|
||||
|
|
@ -60,6 +61,19 @@ namespace ServerRuntime
|
|||
return Utf8ToWide(value.c_str());
|
||||
}
|
||||
|
||||
std::string StripUtf8Bom(const std::string &value)
|
||||
{
|
||||
if (value.size() >= 3 &&
|
||||
(unsigned char)value[0] == 0xEF &&
|
||||
(unsigned char)value[1] == 0xBB &&
|
||||
(unsigned char)value[2] == 0xBF)
|
||||
{
|
||||
return value.substr(3);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string TrimAscii(const std::string &value)
|
||||
{
|
||||
size_t start = 0;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ namespace ServerRuntime
|
|||
std::string WideToUtf8(const std::wstring &value);
|
||||
std::wstring Utf8ToWide(const char *value);
|
||||
std::wstring Utf8ToWide(const std::string &value);
|
||||
std::string StripUtf8Bom(const std::string &value);
|
||||
|
||||
std::string TrimAscii(const std::string &value);
|
||||
std::string ToLowerAscii(const std::string &value);
|
||||
|
|
|
|||
|
|
@ -657,6 +657,7 @@
|
|||
<ClCompile Include="Console\ServerCliEngine.cpp" />
|
||||
<ClCompile Include="Console\ServerCliParser.cpp" />
|
||||
<ClCompile Include="Console\ServerCliRegistry.cpp" />
|
||||
<ClCompile Include="Common\FileUtils.cpp" />
|
||||
<ClCompile Include="Common\StringUtils.cpp" />
|
||||
<ClCompile Include="..\Minecraft.Client\glWrapper.cpp" />
|
||||
<ClCompile Include="ServerLogger.cpp" />
|
||||
|
|
@ -684,6 +685,7 @@
|
|||
<ClInclude Include="Console\ServerCliEngine.h" />
|
||||
<ClInclude Include="Console\ServerCliParser.h" />
|
||||
<ClInclude Include="Console\ServerCliRegistry.h" />
|
||||
<ClInclude Include="Common\FileUtils.h" />
|
||||
<ClInclude Include="Common\StringUtils.h" />
|
||||
<ClInclude Include="ServerLogger.h" />
|
||||
<ClInclude Include="ServerProperties.h" />
|
||||
|
|
|
|||
|
|
@ -48,6 +48,9 @@
|
|||
<ClCompile Include="Windows64\ServerMain.cpp">
|
||||
<Filter>Server</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\FileUtils.cpp">
|
||||
<Filter>Server\Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Minecraft.Client\AbstractTexturePack.cpp" />
|
||||
<ClCompile Include="..\Minecraft.Client\AchievementPopup.cpp" />
|
||||
<ClCompile Include="..\Minecraft.Client\AchievementScreen.cpp" />
|
||||
|
|
@ -572,6 +575,9 @@
|
|||
<ClInclude Include="Console\ServerCliRegistry.h">
|
||||
<Filter>Server\Console</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\FileUtils.h">
|
||||
<Filter>Server\Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\StringUtils.h">
|
||||
<Filter>Server\Common</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
Loading…
Reference in a new issue