2016-09-09 1 views
0

Мне нужно создать простой класс журнала (только метод «сохранить в файл») в приложении UWP для цели отладки, но AppendTextAsync сильно отличается от потока, и я не знаете, как использовать. Это мой классКак добавить текст в файл в приложении UWP

#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

Тег C++ - cli не так, больше, C++ - cx – Gorice

ответ

1

Не используйте StorageFile API, для сохранения данных в локальную папку. Используйте его только в том случае, если вам нужно: для API-интерфейсов, которым требуется передать их в файл хранилища или для доступа к библиотеке изображений, которая не имеет реального пути. API-интерфейсы StorageFile очень медленны по сравнению с традиционными API-интерфейсами. Хуже всего, все операции с файлами являются асинхронными, что означает, что они больно работать и даже болью больно отлаживать.

Для вашего сценария, я бы просто использовать зЬй :: 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."); 
} 

В качестве альтернативы, вы можете использовать API для файлов Win32:

#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())); 
} 

Примечание, Я использовал бросок std :: runtime_error для обработки ошибок, например: вы можете сделать это по-другому.

+0

Благодарим вас за подробный ответ. Я попробовал первое решение, файл был создан, но на нем ничего не написано (без ошибок бросания). Любая идея почему? – Gorice

+0

Я пробовал оба метода локально, и они работают для меня. Сколько текста вы пишете в файл? Возможно, содержимое буферизовано - вы пытались добавить строку, заканчивающуюся в конце вашего сообщения? Вы также можете вызвать .flush() на m_OutStream, если вы не хотите буферизации. Обычно, несмотря на это, он загорается при регистрации строки, заканчивающейся или уничтожающей объект потока. – Sunius

+0

Очень мало строк текста, в основном числа. Добавление окончания строки решает проблему. Большое спасибо. – Gorice

Смежные вопросы