public async Task <bool> TryReplaceSongAsync(OfflineSong oldSong, OfflineSong newSong) { bool replaced = false; using (StreamReader sr = File.OpenText(infoFilePath)) using (StreamWriter sw = File.CreateText(infoFilePath + "temp")) { //Get total lines LUint totalLines; //Read and assign to totalLines if (!TryGetTotalLines(sr, out totalLines)) { sr.Close(); await sw.FlushAsync(); File.Delete(infoFilePath + "temp"); return(false); } //Write totalLines on new one await sw.WriteLineAsync(totalLines.ToString()); string findingString = SongCollectionFormatter.SongFormatter(oldSong); for (LUint i = 0; i < totalLines; i++) { //Read new line string songLine = await sr.ReadLineAsync(); if (songLine == findingString) { //Write new song if found await sw.WriteLineAsync(SongCollectionFormatter.SongFormatter(newSong)); replaced = true; } else { //Write the line that was read if not found await sw.WriteLineAsync(songLine); } } } if (replaced) { File.Delete(infoFilePath); File.Move(infoFilePath + "temp", infoFilePath); return(true); } else { File.Delete(infoFilePath + "temp"); return(false); } }
internal static string SongFormatter(OfflineSong s) { return($"{s.timesPlayed}»{s.song.Title}»{s.song.FilePath}»{s.song.Duration}»{s.song.Url}"); }
public async Task <bool> TryChangeTimesPlayed(LUint lineNo, OfflineSong offlineSong) { using (StreamWriter sw = File.CreateText(infoFilePath + "temp")) using (StreamReader sr = File.OpenText(infoFilePath)) { LUint totalLines; string line = await sr.ReadLineAsync(); #region Precautions if (!LUint.TryParse(line, out totalLines)) { LogHelper.Logln($"{infoFilePath} is not encoded as expected.", LogType.Error); sr.Close(); await sw.FlushAsync(); File.Delete(infoFilePath + "temp"); return(false); } if (totalLines == 0) { LogHelper.Logln($"Trying to change {infoFilePath}, which has 0 line of song in it!", LogType.Error); sr.Close(); await sw.FlushAsync(); File.Delete(infoFilePath + "temp"); return(false); } if (totalLines < lineNo) { LogHelper.Logln($"Trying to change line {lineNo} out of {totalLines} in {infoFilePath}!.", LogType.Error); sr.Close(); await sw.FlushAsync(); File.Delete(infoFilePath + "temp"); return(false); } #endregion //totalLines is now assigned try { await sw.WriteLineAsync(totalLines.ToString()); bool songRearranged = false; for (int i = 0; i < lineNo; i++) { string songLine = await sr.ReadLineAsync(); if (!songRearranged) { if (SongCollectionFormatter.GetTimesPlayed(songLine) == offlineSong.timesPlayed) { int min = Math.Min(SongCollectionFormatter.GetSongTitle(songLine).Length , offlineSong.song.Title.Length); for (int j = 0; j < min; j++) { if (offlineSong.song.Title[j] < SongCollectionFormatter.GetSongTitle(songLine)[j] || j == min - 1) { songRearranged = true; await sw.WriteLineAsync(SongCollectionFormatter.SongFormatter(offlineSong)); break; } else if (offlineSong.song.Title[j] > SongCollectionFormatter.GetSongTitle(songLine)[j]) { break; } } } else if (SongCollectionFormatter.GetTimesPlayed(songLine) < offlineSong.timesPlayed) { //We might want to re-arrange it if the song being changed the times played has //a promotion of rank songRearranged = true; await sw.WriteLineAsync(SongCollectionFormatter.SongFormatter(offlineSong)); } } await sw.WriteLineAsync(songLine); } await sr.ReadLineAsync(); //Move to next line on the reader since we don't need to use it if (!songRearranged) //If ranking does not change { await sw.WriteLineAsync(SongCollectionFormatter.SongFormatter(offlineSong)); } for (; lineNo < totalLines; lineNo++) //DEBUNK THIS { await sw.WriteLineAsync(await sr.ReadLineAsync()); } } catch (Exception e) { LogHelper.Logln($"Error occured while reading {infoFilePath} and writing {infoFilePath + "temp"}. {e.Message}", LogType.Error); sr.Close(); await sw.FlushAsync(); File.Delete(infoFilePath + "temp"); return(false); } } #region Clean-up try { File.Delete(infoFilePath); File.Move(infoFilePath + "temp", infoFilePath); } catch (Exception e) { LogHelper.Logln($"Error while deleting ${infoFilePath} and replacing {infoFilePath} with {infoFilePath + "temp"}. {e.Message}", LogType.Error); } LogHelper.Logln($"Successfully rewrite times played and flushed all underlying streams.", LogType.Success); #endregion return(true); }
internal OfflineSongInfo(OfflineSong offSong, LUint lineNo) { this.offSong = offSong; lineNumber = lineNo; }
public async Task <bool> TryReplaceSongAsync(OfflineSong newSong, LUint lineNo) { using (StreamWriter sw = File.CreateText(infoFilePath + "temp")) using (StreamReader sr = File.OpenText(infoFilePath)) { LUint totalLines; string line = await sr.ReadLineAsync(); if (!LUint.TryParse(line, out totalLines)) { LogHelper.Logln($"{infoFilePath} is not encoded as expected.", LogType.Error); sr.Close(); await sw.FlushAsync(); File.Delete(infoFilePath + "temp"); return(false); } if (totalLines == 0) { LogHelper.Logln($"Trying to change {infoFilePath}, which has 0 line of song in it!", LogType.Error); sr.Close(); await sw.FlushAsync(); File.Delete(infoFilePath + "temp"); return(false); } if (totalLines < lineNo) { LogHelper.Logln($"Trying to change line {lineNo} out of {totalLines} in {infoFilePath}!.", LogType.Error); sr.Close(); await sw.FlushAsync(); File.Delete(infoFilePath + "temp"); return(false); } try { await sw.WriteLineAsync(totalLines.ToString()); for (int i = 0; i < lineNo; i++) { await sw.WriteLineAsync(await sr.ReadLineAsync()); } //Write the changing value await sr.ReadLineAsync(); await sw.WriteLineAsync( SongCollectionFormatter.SongFormatter(newSong)); for (; lineNo < totalLines; lineNo++) { await sw.WriteLineAsync(await sr.ReadLineAsync()); } } catch (Exception e) { LogHelper.Logln($"Error occured while reading {infoFilePath} and writing {infoFilePath + "temp"}. {e.Message}", LogType.Error); sr.Close(); await sw.FlushAsync(); File.Delete(infoFilePath + "temp"); return(false); } } try { File.Delete(infoFilePath); File.Move(infoFilePath + "temp", infoFilePath); } catch (Exception e) { LogHelper.Logln($"Error while deleting ${infoFilePath} and replacing {infoFilePath} with {infoFilePath + "temp"}. {e.Message}", LogType.Error); } LogHelper.Logln($"Successfully rewrite times played and flushed all underlying streams.", LogType.Success); return(true); }
/// <summary> /// Please make sure the infoFilePath exists /// </summary> /// <param name="song"></param> /// <returns></returns> public async Task <bool> TryAddSongAsync(OfflineSong song) { bool songAdded; using (StreamReader sr = File.OpenText(infoFilePath)) using (StreamWriter sw = File.CreateText(infoFilePath + "temp")) { LUint totalLines; string line = await sr.ReadLineAsync(); if (!LUint.TryParse(line, out totalLines)) { LogHelper.Logln($"{infoFilePath} is not encoded as expected.", LogType.Error); sr.Close(); await sw.FlushAsync(); sw.Close(); File.Delete(infoFilePath + "temp"); return(false); } if (totalLines == 0) { await sw.WriteLineAsync('1'); await sw.WriteLineAsync(SongCollectionFormatter.SongFormatter(song)); sr.Close(); await sw.FlushAsync(); sw.Close(); File.Delete(infoFilePath); File.Move(infoFilePath + "temp", infoFilePath); return(true); } #if DEBUG LogHelper.Logln($"Total lines = {totalLines}", LogType.Warning); #endif await sw.WriteLineAsync((totalLines + 1).ToString()); //We are now done with getting and writing the number of totalLines of the new file songAdded = false; for (int i = 0; i < totalLines; i++) { string songLine = await sr.ReadLineAsync(); if (!songAdded) { #if DEBUG LogHelper.Logln("!songAdded; i = " + i); #endif LUint songLineTimesPlayed = SongCollectionFormatter.GetTimesPlayed(songLine); if (songLineTimesPlayed == song.timesPlayed) { //2»aaaaaaa... //1»abcde»... //songLine //1»bcdefeee»... //song.song string songTitle = SongCollectionFormatter.GetSongTitle(songLine); int minLength = Math.Min(song.song.Title.Length, songTitle.Length); //5, 8 => 5 for (int j = 0; j < minLength; j++) { if (song.song.Title[j] < songTitle[j]) //if the adding song is less than the existed one alphabetically { await sw.WriteLineAsync(SongCollectionFormatter.SongFormatter(song)); songAdded = true; break; } else if (j == minLength - 1) //If the adding song is a modification of the existed one { if (song.song.Title.Length != songTitle.Length) //the original or the new one might be a remix { //It does not matter anymore if the new title is an inserted of an old one await sw.WriteLineAsync(SongCollectionFormatter.SongFormatter(song)); songAdded = true; break; } else //same title, exit { string songDuration = SongCollectionFormatter.GetDuration(songLine); //Check duration of both if (songDuration == song.song.Duration) { //Same song sr.Close(); await sw.FlushAsync(); sw.Close(); File.Delete(infoFilePath + "temp"); return(true); } //The else case is automatically handled } } else if (song.song.Title[j] > songTitle[j]) { break; } } } else if (songLineTimesPlayed < song.timesPlayed) { await sw.WriteLineAsync(SongCollectionFormatter.SongFormatter(song)); songAdded = true; } } await sw.WriteLineAsync(songLine); } if (!songAdded) { //When you have eliminated the impossible, whatever remains, however improbable, must be the truth. //- Sherlock Holmes/Sir Arthur Conan Doyle await sw.WriteLineAsync(SongCollectionFormatter.SongFormatter(song)); songAdded = true; } } #region Clean-up (works perfectly) #if DEBUG LogHelper.Logln("Flushed sr and sw.", LogType.Success); #endif try { #if DEBUG if (songAdded) { LogHelper.Logln("Since songAdded, delete old file, replace new file", LogType.Success); #endif File.Delete(infoFilePath); File.Move(infoFilePath + "temp", infoFilePath); #if DEBUG } else { LogHelper.Logln("Since !songAdded, delete new file.", LogType.Success); File.Delete(infoFilePath + "temp"); } #endif } catch (Exception e) { LogHelper.Logln($"Error while deleting ${infoFilePath} and replacing {infoFilePath} with {infoFilePath + "temp"}. {e.Message}", LogType.Error); } #if DEBUG LogHelper.Logln("TryAddSongAsync algorithm got to the bottom of before returning.", LogType.Success); #endif #endregion return(songAdded); }