我需要在UWP应用程序中创建一个简单的日志类(只是"保存到文件"方法)以进行调试,但AppendTextAsync与ofstream有很大不同,我不知道如何使用。 这是我的班级
#pragma once
ref class winRTLog sealed
{
public:
winRTLog();
void save(Platform::String^ log);
private:
Platform::String^ myFilename = L"myLog.txt";
Windows::Storage::StorageFolder^ myFolder;
Windows::Storage::StorageFile^ myFile;
Windows::Foundation::IAsyncOperation<Windows::Storage::StorageFile^>^ createMyFile;
concurrency::task<Windows::Storage::StorageFile^> myFileTask;
};
这是我到目前为止试图理解文档的混乱
#include "pch.h"
#include <ppltasks.h>
#include "winRTLog.h"
winRTLog::winRTLog()
{
myFolder = Windows::Storage::ApplicationData::Current->LocalFolder;
createMyFile = myFolder->CreateFileAsync(myFilename, Windows::Storage::CreationCollisionOption::OpenIfExists);
myFileTask = concurrency::create_task(myFolder->GetFileAsync(myFilename));
//how to make myFile point the file I've created?
}
void winRTLog::save(Platform::String^ log)
{
//??
myFileTask.then([&]()
{
//how to use Windows::Storage::FileIO::AppendTextAsync
//with myFile and log?
});
}
答案 0 :(得分:2)
不要使用StorageFile API将数据保存到本地文件夹中。只有在需要时才使用它:对于需要将它们传递到存储文件中的API,或者访问没有真实路径的图片库这样的地方。与传统API相比,StorageFile API非常慢。最糟糕的是,所有文件操作都是异步的,这意味着它们很难处理,甚至更难以调试。
对于您的方案,如果您熟悉它,我只使用std :: wofstream:
#include <fstream>
class winRTLog
{
public:
winRTLog(Platform::String^ fileName);
void save(Platform::String^ log);
private:
std::wofstream m_OutStream;
};
winRTLog::winRTLog(Platform::String^ fileName) :
m_OutStream(std::wstring(Windows::Storage::ApplicationData::Current->LocalFolder->Path->Data()) + L"\\" + fileName->Data(), std::ios::app)
{
if (!m_OutStream.is_open())
throw std::runtime_error("Failed to open the log file.");
}
void winRTLog::save(Platform::String^ log)
{
m_OutStream << log->Data();
if (m_OutStream.fail())
throw std::runtime_error("Failed to write to the log file.");
}
或者,您可以使用Win32文件API:
#include <memory>
#include <string>
#include <windows.h>
class winRTLog
{
public:
winRTLog(Platform::String^ fileName);
~winRTLog();
void save(Platform::String^ log);
private:
HANDLE m_LogHandle;
};
winRTLog::winRTLog(Platform::String^ fileName)
{
auto filePath = std::wstring(Windows::Storage::ApplicationData::Current->LocalFolder->Path->Data()) + L"\\" + fileName->Data();
m_LogHandle = CreateFile2(filePath.c_str(), GENERIC_WRITE, 0, OPEN_ALWAYS, nullptr);
if (m_LogHandle == INVALID_HANDLE_VALUE)
throw std::runtime_error("Failed to open the log file: error code " + std::to_string(GetLastError()));
if (SetFilePointer(m_LogHandle, 0, nullptr, FILE_END) == INVALID_SET_FILE_POINTER)
throw std::runtime_error("Failed to set file pointer to the end of file: error code " + std::to_string(GetLastError()));
}
winRTLog::~winRTLog()
{
if (m_LogHandle != INVALID_HANDLE_VALUE)
CloseHandle(m_LogHandle);
}
void winRTLog::save(Platform::String^ log)
{
// Convert to UTF8
std::string utf8;
utf8.resize(4 * log->Length());
auto utf8Length = WideCharToMultiByte(CP_UTF8, 0, log->Data(), static_cast<int>(log->Length()), &utf8[0], static_cast<int>(4 * log->Length()), nullptr, nullptr);
if (utf8Length == 0)
throw std::runtime_error("Failed to convert log message to UTF8: error code " + std::to_string(GetLastError()));
utf8.resize(utf8Length);
// Write to actual log
DWORD bytesWritten;
auto writeResult = WriteFile(m_LogHandle, utf8.data(), static_cast<DWORD>(utf8.length()), &bytesWritten, nullptr);
if (writeResult == FALSE || bytesWritten != utf8.length())
throw std::runtime_error("Failed to write log message to the log file: error code " + std::to_string(GetLastError()));
}
注意,出于示例目的,我使用throw std :: runtime_error进行错误处理:您可能希望以不同方式执行此操作。
答案 1 :(得分:0)
基于@Sunius 的回答,但对于 UWP 应用程序中的 C++/WinRT,请注意日志文件将位于 %appdata%\..\Local\Packages\<YOUR_UWP_APP PACKAGE>\LocalState
文件夹中:
// WinRtLog.cpp
#include "WinRtLog.h"
#include "winrt/Windows.Storage.h"
using namespace winrt::Windows;
winRTLog::winRTLog(std::wstring fileName) :
m_OutStream(std::wstring(Storage::ApplicationData::Current().LocalFolder().Path().data()) + L"\\" + fileName, std::ios::app)
{
if (!m_OutStream.is_open())
throw std::runtime_error("Failed to open the log file.");
}
void winRTLog::save(std::string log)
{
m_OutStream << log.data();
if (m_OutStream.fail())
throw std::runtime_error("Failed to write to the log file.");
}
和标题:
// WinRtLog.h
#pragma once
#include <fstream>
#include "winrt/Windows.ApplicationModel.Core.h"
class winRTLog
{
public:
winRTLog(std::wstring fileName);
void save(std::string log);
private:
std::wofstream m_OutStream;
};
请注意,如果要将日志文件存储在任意文件夹中,则 UWP broadFileSystemAccess
中需要 Package.appxmanifest
功能——必须在代码中设置此功能(Appx GUI 不会显示它)如图所示in this SO post。