2016-04-11 2 views
0

Я использую streamwriter для сохранения моих данных игры во время игры в CSV-файле. Чтобы сделать это, я инициализировал свой потоковый блок в начальной функции и написал первую строку для заголовков для моих данных. Затем в функции обновления я пишу переменные игровые переменные в этом файле. Проблема у меня следующая:Как закрыть streamwriter правильно после того, как утверждение более верно?

Это прекрасно работает, и я могу видеть свой файл csv с данными, когда я нажимаю кнопку «остановить» вручную в игре. Однако, когда я жду, пока myTimer (продолжительность игры < = 0), и графический интерфейс перезагружается, я просто получаю пустой CSV-файл. Я думаю, что проблема связана с тем, что я не закрыть мой StreamWriter правильно ... Вот мой код:

// Use this for initialization 
public void Start() 
{ 
    //create file (txt or csv) with streamwriter which has the name of the Subject and Information which game 
    swFeedbackGame = File.CreateText (UIManagerScript.SUBJECTID+"FeedbackGameData444.csv"); 
    //write headers to file 
    swFeedbackGame.Write ("PositionRingFeeback" + "," + "PositionSphereMiddle" + "," + "distanceRingFeedbackTOSphere" + "," + "Collisions" + "," + "Timer"+System.Environment.NewLine); 
} 

public void SaveDataFeedback() 
{ 
    //start writing in file only when feedback game is starting 
    //if (StartButtonManager.startingGame) { 

    if (StartButtonManager.startingGame) 
    { 
     //get position of center of the ring 
     PositionRingFeedback = GameObject.Find ("Ring").transform.position; 

     //position of the center of the ring (y axis) 
     PositionRINGFeedback = PositionRingFeedback.y; 

     //error, meaning difference between position of the spheremiddle and center of the ring 
     distanceRingFeedbackTOSphere = PositionRINGFeedback - Sinewave.posSpheremiddle; 

     //write data to file _ columns are separated by a , 
     swFeedbackGame.Write (PositionRINGFeedback + "," + Sinewave.posSpheremiddle + "," + distanceRingFeedbackTOSphere + "," + CounterManager.counterHitSinewave + "," + UIManagerScript.myTimer + System.Environment.NewLine); 
     swFeedbackGame.Flush(); 
    } 
    else 
    { 
     swFeedbackGame.Close(); 
    } 
} 

// Update is called once per frame 
public void FixedUpdate() 
{ 
    //saves the data from the FeedbackGame every Frame 
    SaveDataFeedback(); 
} 
+0

могли бы вы, пожалуйста, правильно отступы код –

+1

кажется каждый раз, когда вы перезагрузки файл CSV является заново, проверьте, прежде чем писать, если существует, то текст будет appeand, и если не существует, то создать новый файл – Mostafiz

+1

Как насчет инициализации внутри 'с помощью() {} ', а затем вставить создателя потока в' SaveDataFeedback() 'вместо того, чтобы полагаться на глобальный экземпляр? –

ответ

1

Инициализировать свой поток внутри, используя так:

using(StreamWriter sw = new StreamWriter) 
{ 
    //your code here this 
    //this doesn't need a sw.Open(), or sw.Close() 
} 

но будьте осторожны, если у вас есть вложенные потоки.

0

Вам следует избегать открытия/закрытия файлов или сохранения длинных промежутков между открытыми и закрытыми различными способами. Храните обе операции в одном методе.

WriteAllText и AppendAllText Статические методы пригождаются. Они открывают файл, записывают содержимое в него, а затем закрывают файл только одним оператором.

Если не будет слишком много вызовов для записи содержимого в файл, я бы предпочел использовать эти методы, вместо того чтобы явно открывать и закрывать их самостоятельно.

// Use this for initialization 
string FileName; 
public void Start() 
{ 
    FileName = UIManagerScript.SUBJECTID + "FeedbackGameData444.csv"; 

    //create file (txt or csv) with streamwriter which has the name of the Subject and Information which game 
    //and write headers to file 
    WriteToFile(FileName, true, "PositionRingFeeback" + "," + "PositionSphereMiddle" + "," + "distanceRingFeedbackTOSphere" + "," + "Collisions" + "," + "Timer" + System.Environment.NewLine); 
} 

public void SaveDataFeedback() 
{ 
    //start writing in file only when feedback game is starting 
    //if (StartButtonManager.startingGame) { 

    if (StartButtonManager.startingGame) 
    { 
     //get position of center of the ring 
     PositionRingFeedback = GameObject.Find("Ring").transform.position; 

     //position of the center of the ring (y axis) 
     PositionRINGFeedback = PositionRingFeedback.y; 

     //error, meaning difference between position of the spheremiddle and center of the ring 
     distanceRingFeedbackTOSphere = PositionRINGFeedback - Sinewave.posSpheremiddle; 

     //write data to file _ columns are separated by a , 
     WriteToFile(FileName, false, PositionRINGFeedback + "," + Sinewave.posSpheremiddle + "," + distanceRingFeedbackTOSphere + "," + CounterManager.counterHitSinewave + "," + UIManagerScript.myTimer + System.Environment.NewLine); 
    } 
} 

// Update is called once per frame 
public void FixedUpdate() 
{ 
    //saves the data from the FeedbackGame every Frame 
    SaveDataFeedback(); 
} 

private void WriteToFile(string fileName, bool createNew, string contents) 
{ 
    if (createNew) 
     File.WriteAllText(fileName, contents); 
    else 
     File.AppendAllText(fileName, contents); 
} 
+0

Благодарим за помощь! Я не могу проголосовать за ваш ответ ... = (это невозможно. Проблема в том, что я пишу: WriteToFile, он выглядит красным ... мне нужен специальный набор инструментов для этого? Когда я продолжаю, это написано, что это не существует в этом контексте.Спасибо большое! – sportente

+0

Я добавил этот метод в конце кода. Вы пропустили это? –

+0

Отлично! Спасибо, я попробую. Где я могу выбрать, где будет создан новый файл? я работаю над MAC. – sportente

0

ООП прибывает в реск.

Разумеется, это немного verbouse, но это хороший дизайн, который вы всегда можете продлить и так далее. Логика о протоколировании неактивна, поэтому вызывающий абонент может самостоятельно распоряжаться вашим регистратором, и вам просто нужно написать все, что захотите (обратите внимание, что вы передаете данные игрового объекта, и регистратор делает все для вас). Пример кода:

class Game 
{ 
    private readonly ILogger _logger; 

    public Game(ILogger logger) 
    { 
     _logger = logger; 
    } 

    public void Start() 
    { 
     _logger.StartWriting(); 
    } 

    public void SaveDataFeedback() 
    { 
     var dataobject = new GameData(); 
     // filling data object 
     _logger.WriteData(dataobject); 
    } 
} 

internal interface ILogger 
{ 
    void StartWriting(); 
    void WriteData(GameData data); 
} 

public class GameData 
{ 
    public double PositionRingFeeback { get; set; } 
    public double PositionSphereMiddle { get; set; } 
    public double DistanceRingFeedbackToSphere { get; set; } 
    public int Collisions { get; set; } 
    public TimeSpan Timer { get; set; } 
} 

class FileLogger : ILogger, IDisposable 
{ 
    private readonly string _filename; 
    private StreamWriter _sr; 

    public FileLogger(string filename) 
    { 
     _filename = filename; 
    } 

    public void StartWriting() 
    { 
     _sr = new StreamWriter(new FileStream(_filename, FileMode.OpenOrCreate), Encoding.UTF8); 
     _sr.WriteLine("PositionRingFeeback" + "," + "PositionSphereMiddle" + "," + "distanceRingFeedbackTOSphere" + "," + "Collisions" + "," + "Timer"); 
    } 

    public void WriteData(GameData data) 
    { 
     _sr.Write("{0}{1}{2}{3}{4}", data.PositionRingFeeback, data.PositionSphereMiddle, data.DistanceRingFeedbackToSphere, data.Collisions, data.Timer); 
    } 

    public void Dispose() 
    { 
     _sr.Dispose(); 
    } 
} 

Затем вызываемая избавляется сам регистратор:

using (var logger = new FileLogger("data.txt")) 
{ 
    var game = new Game(logger); 
    game.Start(); 
} 

Если вам не нужен такой уровень инкапсулирования, вы можете использовать только события:

class Game 
{ 
    public delegate void GameStartedHandler(Game sender, EventArgs eventArgs); 
    public delegate void GameEventHandler(Game sender, GameData eventData); 

    public event GameStartedHandler GameStarted = delegate { }; 
    public event GameEventHandler GameEvent = delegate { }; 

    public void Start() 
    { 
     GameStarted(this, EventArgs.Empty); 
    } 

    public void SaveDataFeedback() 
    { 
     var dataobject = new GameData(); 
     // filling data object 
     GameEvent(this, dataobject); 
    } 
} 

, но в этом случае вызов более сложный, поскольку он должен управлять самим протоколом:

using (var logger = new StreamWriter(new FileStream("data.txt", FileMode.OpenOrCreate), Encoding.UTF8)) 
{ 
    var game = new Game(); 
    game.GameStarted += (sender, eventArgs) => logger.WriteLine("PositionRingFeeback" + "," + "PositionSphereMiddle" + "," + "distanceRingFeedbackTOSphere" + "," + "Collisions" + "," + "Timer"); 
    game.GameEvent += (sender, data) => logger.Write("{0}{1}{2}{3}{4}", data.PositionRingFeeback, data.PositionSphereMiddle, data.DistanceRingFeedbackToSphere, data.Collisions, data.Timer); 
    game.Start(); 
} 
Смежные вопросы