2016-09-09 18 views
0

UWPアプリケーションで単純なログクラス(単に「ファイルに保存」メソッド)を作成してデバッグする必要がありますが、AppendTextAsyncはofstreamとは大きく異なります。使用方法を知っている。 これは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の場合にのみ使用してください。 StorageFile APIは、従来の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())); 
} 

注意、私は、目的のためのエラー処理のためにstd :: runtime_errorを投げていました。あなたはそれをやりたいと思うかもしれません。

+0

詳細な回答ありがとうございます。私は最初の解決策を試してみましたが、ファイルは作成されましたが、何も書き込まれません(エラーを投げずに)。どんな考え? – Gorice

+0

私は両方の方法をローカルで試してみました。どのくらいテキストをファイルに書きますか?おそらく内容がバッファされているのでしょうか?あなたのメッセージの最後に行末を追加しようとしましたか?バッファリングをしたくない場合は、m_OutStreamの.flush()を呼び出すこともできます。通常は、ストリームオブジェクトを終了または破棄する行をログに記録すると、フラッシュされます。 – Sunius

+0

テキストの行はほとんどなく、主に数字です。行末を付けることで問題は解決しました。どうもありがとうございました。 – Gorice

関連する問題