How to save List to binary file - c#

I'm trying to create a little clicker game with unity and now I need to save Shop's items in a binary file.
The below code is my Shop class which is called when I click on the button icon, I need to check if the shop data exists in my save file before loading the shop and if exists replace the default list with the saved one, example:
The first time I click on the shop the game should save every shop item available with cost, name, image and level, when the player buy something the code saves the shop items/changes into the file and when the player opens the shop again it should reload the values from the save file.
I know how to save the info into a file if is just a boolean, int, float, etc but not a list
public class Shop : MonoBehaviour
{
// Singleton Instance
public static Shop Instance = null;
[System.Serializable] public class ShopItem
{
public float costMultiplier;
public string itemName;
public Sprite image;
public float price;
public Button purchase;
public int level;
}
[SerializeField]
public List<ShopItem> shopItemsList;
GameObject ItemTemplate;
GameObject ShopItemObj;
[SerializeField] Transform ShopScrollView;
public GameObject ShopCanvas;
private void Awake()
{
SingletonSetup();
}
private void SingletonSetup()
{
if (Instance == null)
{
Instance = this;
}
else if (Instance != this)
{
Destroy(gameObject);
}
}
private void Start()
{
ItemTemplate = ShopScrollView.GetChild(0).gameObject;
int len = shopItemsList.Count;
GameData data = SaveSystem.LoadData();
for (int i = 0; i < len; i++)
{
ShopItemObj = Instantiate(ItemTemplate, ShopScrollView);
/*if (data.firstRun)
{*/
ShopItemObj.transform.GetChild(0).GetComponent<Image>().sprite = shopItemsList[i].image;
if (shopItemsList[i].level == 0)
{
ShopItemObj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = "$" + GameController.Instance.MoneyConverter(shopItemsList[i].price, GameController.Instance.scientificNumbers);
}
else
{
ShopItemObj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = "$" + GameController.Instance.MoneyConverter((shopItemsList[i].price * shopItemsList[i].costMultiplier), GameController.Instance.scientificNumbers);
}
ShopItemObj.transform.GetChild(2).GetComponent<TextMeshProUGUI>().text = shopItemsList[i].itemName;
float price = shopItemsList[i].price;
ShopItemObj.transform.GetChild(3).GetComponent<Button>().onClick.AddListener(() => { OnPuchase(price); });
ShopItemObj.transform.GetChild(4).GetComponent<TextMeshProUGUI>().text = "level: " + shopItemsList[i].level;
/*}
else
{
ShopItemObj.transform.GetChild(0).GetComponent<Image>().sprite = data.shopItemsList[i].image;
if (shopItemsList[i].level == 0)
{
ShopItemObj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = "$" + GameController.Instance.MoneyConverter(data.shopItemsList[i].price, GameController.Instance.scientificNumbers);
}
else
{
ShopItemObj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = "$" + GameController.Instance.MoneyConverter((data.shopItemsList[i].price * data.shopItemsList[i].costMultiplier), GameController.Instance.scientificNumbers);
}
ShopItemObj.transform.GetChild(2).GetComponent<TextMeshProUGUI>().text = data.shopItemsList[i].itemName;
float price = data.shopItemsList[i].price;
ShopItemObj.transform.GetChild(3).GetComponent<Button>().onClick.AddListener(() => { OnPuchase(price); });
ShopItemObj.transform.GetChild(4).GetComponent<TextMeshProUGUI>().text = "level: " + data.shopItemsList[i].level;
}*/
}
Destroy(ItemTemplate);
}
private void Update()
{
int len = shopItemsList.Count;
for (int i = 0; i < len; i++)
{
if (!GameController.Instance.CanAffordPurchase(shopItemsList[i].price))
{
ShopItemObj.transform.GetChild(3).GetComponent<Button>().enabled = false;
}
else
{
ShopItemObj.transform.GetChild(3).GetComponent<Button>().enabled = true;
}
}
}
public void OnPuchase(float price)
{
if (GameController.Instance.CanAffordPurchase(price))
{
int len = shopItemsList.Count;
for (int i = 0; i < len; i++)
{
if (shopItemsList[i].level < 1)
{
ShopItemObj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = "$" + GameController.Instance.MoneyConverter(shopItemsList[i].price, GameController.Instance.scientificNumbers);
GameController.Instance.PurchaseItem(price);
}
else
{
ShopItemObj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = "$" + GameController.Instance.MoneyConverter(shopItemsList[i].price * shopItemsList[i].costMultiplier, GameController.Instance.scientificNumbers);
shopItemsList[i].price = shopItemsList[i].price * shopItemsList[i].costMultiplier;
GameController.Instance.PurchaseItem(price * shopItemsList[i].costMultiplier);
}
ShopItemObj.transform.GetChild(4).GetComponent<TextMeshProUGUI>().text = "level: " + (shopItemsList[i].level += 1);
}
SaveSystem.SaveData();
}
else
{
Debug.LogError("Cannot affor the item");
}
}
public void HideCanvas()
{
ShopCanvas.gameObject.SetActive(false);
}
public void ShowCanvas()
{
ShopCanvas.gameObject.SetActive(true);
}
}
My GameData.cs:
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[Serializable]
public class GameData
{
public static string saveFileName = "Clicker.unity2d";
public float money;
public bool firstRun;
public bool scientificNumbers;
public List<Shop.ShopItem> shopItemsList;
public GameData()
{
money = GameController.Instance.money;
firstRun = GameController.Instance.firstRun;
scientificNumbers = GameController.Instance.scientificNumbers;
}
}
public static class SaveSystem
{
public static void SaveData()
{
BinaryFormatter formatter = new BinaryFormatter();
string path = Application.persistentDataPath + "/" + GameData.saveFileName;
FileStream stream = new FileStream(path, FileMode.Create);
GameData data = new GameData();
formatter.Serialize(stream, data);
stream.Close();
}
public static GameData LoadData()
{
string path = Application.persistentDataPath + "/" + GameData.saveFileName;
if (File.Exists(path))
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(path, FileMode.Open);
GameData data = formatter.Deserialize(stream) as GameData;
stream.Close();
return data;
}
else
{
return new GameData { firstRun = true };
}
}
}

Where should the list be saved? The list should be in an object (for example your GameData has also List<>), so you can use the function below to create a file and save your List using BinaryFormatter:
private void CreateGameFile(List<Shop.ShopItem> list)
{
string path = Path.Combine(Application.persistentDataPath + "/" + gameName + GetGameFileExtension());
IFormatter formatter = new BinaryFormatter();
/// Create game file.
FileStream file = new FileStream(path, FileMode.CreateNew, FileAccess.ReadWrite);
GameData game = new GameData
{
money = GameController.Instance.money,
firstRun = GameController.Instance.firstRun,
scientificNumbers = GameController.Instance.scientificNumbers,
shopItemsList = list
};
formatter.Serialize(file, game);
file.Close();
}

Related

access returned object in another class

I'm trying to read id3 tags from a directory and I found some code online i've been trying to understand.
I understand most of it except the method GetTag(), it creates a new instance and returns an object but i can't access it from my main program.
public class Mp3Reader
{
private string _fileName;
private Stream _stream;
private byte[] data;
private const int SIZE = 128;
public Mp3Reader(string fileName)
{
_fileName = fileName;
_stream = new FileStream(_fileName, FileMode.Open, FileAccess.Read);
}
public Mp3Tag GetTag()
{
Mp3Tag tag = new Mp3Tag();
data = new byte[SIZE];
_stream.Seek(-128, SeekOrigin.End);
_stream.Read(data, 0, SIZE);
//_stream.Close();
byte b1 = data[0];
byte b2 = data[1];
byte b3 = data[2];
if ((Convert.ToChar(b1) != 'T') || (Convert.ToChar(b2) != 'A') || (Convert.ToChar(b3) != 'G'))
{
throw new Exception("This File is NOT a MP3 file with ID3 v1");
}
for (int i = 3; i < 33; i++)
{
if (data[i] != 0)
tag.Title += Convert.ToChar(data[i]);
}
for (int i = 33; i < 63; i++)
{
if (data[i] != 0)
tag.Artist += Convert.ToChar(data[i]);
}
for (int i = 63; i < 93; i++)
{
if (data[i] != 0)
tag.Album += Convert.ToChar(data[i]);
}
for (int i = 93; i < 97; i++)
{
if (data[i] != 0)
tag.Year += Convert.ToChar(data[i]);
}
for (int i = 97; i < 127; i++)
{
if (data[i] != 0)
tag.Comment += Convert.ToChar(data[i]);
}
tag.Genere = data[127].ToString();
return tag;
}
}
main
static void Main(string[] args)
{
string folder = #"D:\\508-507-2209 (2017)";
var files = Directory.GetFiles(folder);
foreach(var val in files)
{
Mp3Reader tag2 = new Mp3Reader(val);
tag2.GetTag();
Console.WriteLine("");
}
}
mp3tag.cs
public class Mp3Tag
{
public string Title { get; set; }
public string Artist { get; set; }
public string Album { get; set; }
public string Year { get; set; }
public string Genere { get; set; }
public string Comment { get; set; }
}
If I manually Console.WriteLine(tag.xxx) right above my return it'll output to the terminal fine, what I don't understand is what to do with the "tag" variable that it created. why can't i access tag.Title in my main program?
tag.Genere = data[127].ToString();
Console.WriteLine("Title: " + tag.Title);
Console.WriteLine("Artist: " + tag.Artist);
Console.WriteLine("Album: " + tag.Album); ;
Console.WriteLine("Year: " + tag.Year);
Console.WriteLine("Comments: " + tag.Comment);
Console.WriteLine("Genere" + tag.Genere);
return tag;
shouldn't this be
static void Main(string[] args)
{
string folder = #"D:\\508-507-2209 (2017)";
var files = Directory.GetFiles(folder);
foreach(var val in files)
{
Mp3Reader tag2 = new Mp3Reader(val);
Mp3Tag mp3tag = tag2.GetTag(); // <- this here
Console.WriteLine("");
}

Problem getting value from deserialized file if doesn't exists

I'm currently trying to set a "firstRun" boolean to run a piece of code only when the app is started for the first time.
GameData.cs
[System.Serializable]
public class GameData
{
public static string saveFileName = "Pixel.pixel";
public double money;
public bool firstRun;
public GameData()
{
money = GameController.Instance.CurrentCash;
}
}
SaveSystem.cs
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public static class SaveSystem
{
public static void SaveData()
{
BinaryFormatter formatter = new BinaryFormatter();
string path = Application.persistentDataPath + "/" + GameData.saveFileName;
FileStream stream = new FileStream(path, FileMode.Create);
GameData data = new GameData();
formatter.Serialize(stream, data);
stream.Close();
}
public static GameData LoadData()
{
string path = Application.persistentDataPath + "/" + GameData.saveFileName;
if (File.Exists(path))
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(path, FileMode.Open);
GameData data = formatter.Deserialize(stream) as GameData;
stream.Close();
return data;
}
else
{
return null;
}
}
}
GameController.cs part
public void Start()
{
Setup(START_CASH);
/*AddCash(START_CASH);*/
}
private void Setup(double value)
{
GameData data = SaveSystem.LoadData();
if (!data.firstRun)
{
CurrentCash += value;
SaveSystem.SaveData();
}
else
{
CurrentCash = data.money;
SaveSystem.SaveData();
}
UI.CashDisplay.text = ShortScaleString.parseDouble(CurrentCash, 1, 1000, scientificFormat);
}
My problem is that I need to check if "data.firstRun" is false/doesn't exist to run a setup part but I literally don't know how to achieve this
You should just return a new 'GameData', with your prefered value (true or false):
public static GameData LoadData()
{
string path = Application.persistentDataPath + "/" + GameData.saveFileName;
if (File.Exists(path))
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(path, FileMode.Open);
GameData data = formatter.Deserialize(stream) as GameData;
stream.Close();
return data;
}
else
{
return new GameData { firstRun = true };
}
}

Trying to set up a Save/Load system, need help loading in values from a class to another

So I'm saving and loading values from a specific class. I'm calling out the class that holds the values and using them. But for some reason when the values are loaded in the class that holds the values, the class that calls out the class with values doesn't get those values. How can resolve this?
Checked if values are loaded in, they are(shown in SaveSystem class)
Checked if values are received in the Shop class, they aren't(shown)
public class AllData {
public double bucketProg;
public double milk;
public double totalMilk;
public double milkPrice;
public double totalClicks;
public double coins;
public double totalCoins;
public double upgradeBucketCost = 10;
public double qualityMilkCost = 1000;
public double BucketLevel = 1;
public double milkLevel = 1;
public double multiplier = 1;
}
public class SaveSystem {
AllData allData = new AllData();
public void Save(AllData allData) {
BinaryFormatter bf = new BinaryFormatter();
FileStream file = new FileStream(Application.persistentDataPath + "/allData.hey", FileMode.Create);
bf.Serialize(file, allData);
file.Close();
}
public void Load() {
if (File.Exists(Application.persistentDataPath + "/allData.hey")) {
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/allData.hey", FileMode.Open);
allData = (AllData) bf.Deserialize(file);
file.Close();
//here I made sure to check if the data is being loaded, which it did
Debug.Log(allData.milk);
}
}
}
public class Shop: MonoBehaviour {
AllData allData = new AllData();
private SaveSystem saveSystem = new SaveSystem();
public Text milkText;
public void Start() {
saveSystem.Load();
}
public void Update() {
//output is 0
milkText.text = allData.milk;
saveSystem.Save(this.allData);
}
}
Seems like the problems is you forgetting to mark AllData as System.Serializable;
Also, making the Load function return the AllData that was loaded.
After some modifications, I tested it on my end and it seems to work.
(Tested it on Unity 2019.1.12f1)
This was the code that I used to test:
Shop.cs
public class Shop : MonoBehaviour {
AllData allData = new AllData();
private SaveSystem saveSystem = new SaveSystem();
public Text milkText;
public void Start() {
// assigns '-1' if data was not found;
var loadedData = saveSystem.Load();
allData.milk = (int) (loadedData == null ? -1 : loadedData.milk);
milkText.text = allData.milk.ToString();
}
public void Update() {
if (Input.GetKeyDown(KeyCode.K)){
TestSaving();
}
if (Input.GetKeyDown(KeyCode.J)) {
TestAddingMilkValue();
}
if (Input.GetKeyDown(KeyCode.I)) {
TestLoadingMilkValue();
}
#region Local_Function
void TestSaving() {
Debug.Log("SAVING...");
saveSystem.Save(this.allData);
}
void TestAddingMilkValue() {
Debug.Log("ADD...");
++allData.milk;
milkText.text = allData.milk.ToString();
}
void TestLoadingMilkValue() {
Debug.Log("LOADING...");
var loadedData = saveSystem.Load();
allData.milk = (int)(loadedData == null ? -1 : loadedData.milk);
milkText.text = allData.milk.ToString();
}
#endregion
}
}
SaveSystem.cs
[System.Serializable]
public class AllData {
public double bucketProg = 0;
public double milk = 0;
public double totalMilk = 0;
public double milkPrice = 0;
public double totalClicks = 0;
public double coins = 0;
public double totalCoins = 0;
public double upgradeBucketCost = 10;
public double qualityMilkCost = 1000;
public double BucketLevel = 1;
public double milkLevel = 1;
public double multiplier = 1;
}
public class SaveSystem {
AllData allData = new AllData();
public void Save(AllData allData) {
BinaryFormatter bf = new BinaryFormatter();
FileStream file = new FileStream(Application.persistentDataPath + "/allData.hey", FileMode.Create);
bf.Serialize(file, allData);
file.Close();
}
public AllData Load() {
if (File.Exists(Application.persistentDataPath + "/allData.hey")) {
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/allData.hey", FileMode.Open);
allData = (AllData)bf.Deserialize(file);
file.Close();
return allData;
}
return null;
}
(^ Might want to separate AllData into a different source file.)
Though it is just my personal preference, but you can refactor Load into this too:
// Returns true if the data exists; False if the data did not.
public bool TryLoad(out AllData allData) {
allData = null;
if (File.Exists(Application.persistentDataPath + "/allData.hey")) {
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/allData.hey", FileMode.Open);
allData = (AllData)bf.Deserialize(file);
file.Close();
}
return allData != null;
}
This way, you don't have to manually check if AllData is null whenever you fetch it, as the function "auto-checks" for you.

Network Map with full detail and hierarchy

I wrote a piece of code to run from the first IP address to the last and retrieve the MAC and Hostname of devices in my network.
But, i do not know how to get the hierachy of then. Information like what router is the device conected (via Cable of WiFi also). And some routers are not managed (they don't have IP - they are just "switchs").
First, i didn't think it was possible, since a "tracert" on the CMD does not show then, but when i call the "Network Complete Map" on Windows Control Panel, they get all the information i need - so there is a way. See the image below:
The "switchs" circled in red have no IP, the "TL-xxxx" are routers with DHCP turned of. The "gateway" is a server that has the DHCP and provides connection to the internet.
Thus far, i wrote the following code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Net;
using System.Runtime.InteropServices;
namespace Network
{
[Serializable] public sealed class Map
{
private bool mMARKED = true;
private long mDB = 0L;
private string mIP = string.Empty;
private string mMAC = string.Empty;
private string mBRAND = string.Empty;
private string mNAME = string.Empty;
public bool Save { get { return this.mMARKED; } set { this.mMARKED = value; } }
public long DBId { get { return this.mDB; } set { this.mDB = value; } }
public string IP { get { return this.mIP; } set { this.mIP = value; } }
public string MAC { get { return this.mMAC; } set { this.mMAC = value; } }
public string BRAND { get { return this.mBRAND; } set { this.mBRAND = value; } }
public string NAME { get { return this.mNAME; } set { this.mNAME = value; } }
}
[Serializable] public sealed class Scanner
{
public const string WebOUIFile = "http://standards-oui.ieee.org/oui.txt";
public const string LocalOUIFileName = "oui.txt";
private const long MaxOUIAge = (TimeSpan.TicksPerDay * 90L);
internal Dictionary<string, string> OUIList;
private List<Map> mDevices = new List<Map>(50);
public List<Map> Devices { get { return this.mDevices; } }
public static Scanner Scan;
public Thread Worker;
public bool AutoSave { get; set; }
private string Node;
private byte mInitial;
public static string UploadPath { get; set; }
public byte Initial { get { return this.mInitial; } set { this.mInitial = value; } }
public byte Current { get; private set; }
public byte Limit { get; set; }
public bool Working { get; private set; }
public string Errors;
public string Message { get; private set; }
public bool UpdatingOUI { get; private set; }
public void Interrupt()
{
this.Working = false;
if (this.Worker != null)
{
this.Worker.Abort();
this.Worker = null;
}
this.Node = string.Empty;
this.Initial = 0;
this.Current = 0;
this.Limit = 0;
this.Working = false;
}
public void ToDestroy()
{
this.Interrupt();
this.Errors = string.Empty;
this.Message = string.Empty;
}
public void Stop(bool immediate) { if (immediate) { this.Interrupt(); } }
[DllImport("iphlpapi.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern int SendARP(int DestIP, int SrcIP, out long pMacAddr, ref int PhyAddrLen);
public void ToBegin() { }
public void Stop() { this.Stop(true); }
private static int IPToInt(string Expression)
{
try
{
byte[] IPAddress = System.Net.IPAddress.Parse(Expression).GetAddressBytes();
return (Convert.ToInt32(IPAddress[3]) << 24) | (Convert.ToInt32(IPAddress[2]) << 16) | (Convert.ToInt32(IPAddress[1]) << 8) | Convert.ToInt32(IPAddress[0]);
} catch { return 0; }
}
private Map GetBasics(string IPString)
{
int res = Scanner.IPToInt(IPString);
if (res > 0)
{
long mem = 0L;
int PhyAddrLen = 6;
if (Scanner.SendARP(res, 0, out mem, ref PhyAddrLen) == 0)
{
Map dev = new Map();
byte[] macbytes = BitConverter.GetBytes(mem);
dev.IP = IPString;
string Tmp = BitConverter.ToString(macbytes, 0, 3);
if (this.OUIList != null && this.OUIList.ContainsKey(Tmp)) { dev.BRAND = this.OUIList[Tmp]; }
dev.MAC = Tmp + "-" + BitConverter.ToString(macbytes, 3, 3);
try { dev.NAME = Dns.GetHostEntry(IPString).HostName.ToLower(); } catch { dev.NAME = "unknow"; }
return dev;
}
}
return null;
}
private static void GetNode(ref string IP, ref string Node, ref byte Device)
{
string[] NodeComp = IP.Split('.');
Node = NodeComp[0] + "." + NodeComp[1] + "." + NodeComp[2] + ".";
Device = Convert.ToByte(NodeComp[3]);
}
public static Dictionary<string, string> DonwloadOUTFile(bool ForceUpdate = true)
{
Dictionary<string, string> List = null;
try
{
string Aux = Scanner.UploadPath;
if (Aux == null) { Aux = string.Empty; }
else if (Aux != string.Empty)
{
string Tmp = Aux + "~" + Scanner.LocalOUIFileName;
Aux += Scanner.LocalOUIFileName;
bool FileExists = File.Exists(Aux);
if (FileExists && ((DateTime.UtcNow.Ticks - (new FileInfo(Aux)).CreationTimeUtc.Ticks) > Scanner.MaxOUIAge))
{
File.Delete(Aux);
ForceUpdate = true;
}
string Aux2 = string.Empty;
if (ForceUpdate)
{
List = new Dictionary<string, string>(25000);
using (WebClient Downloader = new WebClient()) { Downloader.DownloadFile(Scanner.WebOUIFile, Tmp); }
using (StreamReader Reader = new StreamReader(Tmp))
using (StreamWriter Writer = new StreamWriter(Aux))
{
do
{
Aux = Reader.ReadLine();
if (Aux.ToLower().Contains("(hex)"))
{
Aux2 = Aux.Substring(0, 8).ToUpper();
Aux = Aux.Substring(Aux.LastIndexOf('\t') + 1);
if (!List.ContainsKey(Aux2))
{
List.Add(Aux2, Aux);
Writer.WriteLine(Aux2 + "\t" + Aux);
}
}
} while (Reader.Peek() >= 0);
Reader.Close();
Writer.Close();
}
try { File.Delete(Tmp); } catch { /* NOTHING */ }
}
else if (FileExists)
{
List = new Dictionary<string, string>(25000);
using (StreamReader Reader = new StreamReader(Aux))
{
do
{
Aux = Reader.ReadLine();
if (Aux != null && Aux.Length > 9)
{
Aux2 = Aux.Substring(0, 8);
if (!List.ContainsKey(Aux2)) { List.Add(Aux2, Aux.Substring(9)); }
}
} while (Reader.Peek() >= 0);
Reader.Close();
}
}
}
}
catch
{
if (List != null) { List.Clear(); }
List = null;
}
return List;
}
private void ReadScaner()
{
this.UpdatingOUI = true;
try { this.OUIList = Scanner.DonwloadOUTFile(ForceUpdate: false); } catch { /* NOTHING */ }
this.UpdatingOUI = false;
if (this.OUIList == null || this.OUIList.Count == 0) { this.Errors += "\nErrorOUIFileDownload"; }
Map Dev = null;
this.Current = this.Initial;
if (this.Limit < this.Initial)
{
Dev = this.GetBasics(this.Node + this.Initial.ToString());
if (Dev != null) { this.Devices.Add(Dev); }
}
else
{
bool ToAdd = true;
while (this.Current <= this.Limit)
{
Dev = this.GetBasics(this.Node + this.Current.ToString());
this.Current += 1;
if (Dev != null)
{
ToAdd = true;
foreach (Map iDev in this.Devices)
{
if (iDev.MAC == Dev.MAC)
{
ToAdd = false;
break;
}
}
if (ToAdd) { this.Devices.Add(Dev); }
}
}
}
this.Message = "Finished!";
this.Interrupt();
}
public void GetRange(string IPInitial, byte Limit, bool AutoSave = true)
{
if (!this.Working)
{
this.AutoSave = AutoSave;
this.Working = true;
Scanner.GetNode(ref IPInitial, ref this.Node, ref this.mInitial);
this.Limit = Limit;
this.Worker = new Thread(this.ReadScaner);
this.Worker.IsBackground = true;
this.ToBegin();
this.Worker.Start();
}
}
public static void GetRange(bool AutoSave, string IPInitial, byte Limit)
{
if (Scanner.Scan == null)
{
Scanner.Scan = new Scanner();
Scanner.Scan.GetRange(IPInitial, Limit, AutoSave: AutoSave);
}
}
~Scanner()
{
if (this.OUIList != null)
{
this.OUIList.Clear();
this.OUIList = null;
}
}
}
}
How do i make that code able to get the hierarchy like windows does?

Writing a list of arrays using csvhelper C#

I am trying to write a List<double[]> into a csv file. Based on my experiments it is not possible using WriteRecords() directly, so I am looking for alternatives.
I cannot create a class to map this data because the number of elements in the arrays varies from execution to execution, and ranges from 1 to 75.
I have tried to go through each element of the array manually with WriteField() but it is really slow., and I have thousands of elements.
Is there anyway to accomplish this fast enough?
Thanks.
Edit:
Code
class ExportData
{
private Dictionary<int, Dictionary<SensorT, ListIndex>> _dict_sensorN;
private List<double[]> _values_list;
private int _current_max_Count=-1;
private static int _max_Count = 3000;
int n_columns = 0;
private CsvWriter csv;
public ExportData(List<SensorControl> sensorsUC)
{
//We create a dictionary with two keys that will store all the info from the sensors
_dict_sensorN = new Dictionary<int, Dictionary<SensorT, ListIndex>>();
foreach (SensorControl SensorC in sensorsUC)
{
Dictionary<SensorT, ListIndex> dict_sensorM = new Dictionary<SensorT, ListIndex>();
if (SensorC.emg)
{
ListIndex Index = new ListIndex();
Index.Column = n_columns;
Index.Row = 0;
dict_sensorM.Add(SensorT.EMG, Index);
n_columns++;
}
if (SensorC.triggers)
{
ListIndex Index = new ListIndex();
Index.Column = n_columns;
Index.Row = 0;
dict_sensorM.Add(SensorT.Trigger1, Index);
n_columns++;
Index.Column = n_columns;
Index.Row = 0;
dict_sensorM.Add(SensorT.Trigger2, Index);
n_columns++;
}
if (SensorC.acc)
{
ListIndex Index = new ListIndex();
Index.Column = n_columns;
Index.Row = 0;
dict_sensorM.Add(SensorT.ACC, Index);
n_columns++;
}
_dict_sensorN.Add(SensorC.sensorNumber, dict_sensorM);
}
//Initialize the array
_values_list = new List<double[]>();
//Initialize the document
DateTime currentDate = DateTime.Now;
string fileName = "exp_" + currentDate.ToString("yyyy-dd-M--HH-mm-ss") + ".csv";
try
{
var textWriter = new StreamWriter(fileName);
csv = new CsvWriter(textWriter);
}
catch (IOException e)
{
Console.WriteLine(e.Message + "\n Cannot create file.");
return;
}
}
public void AddToBuffer(SensorPoint sp)
{
Dictionary<SensorT, ListIndex> dict_sensorM = new Dictionary<SensorT, ListIndex>();
ListIndex Index = new ListIndex();
if (_dict_sensorN.TryGetValue(sp.ID, out dict_sensorM))
{
SensorT type = ToSensorT(sp.SensorType, sp.Battery);
if(type == SensorT.Trigger1) {
if (dict_sensorM.TryGetValue(type, out Index))
{
if (_current_max_Count < Index.Row)
{
_current_max_Count = Index.Row + 1;
_values_list[Index.Row] = new double[n_columns];
}
_values_list[Index.Row][Index.Column] =sp.Trigger1_int;
Index.Row++;
}
if (dict_sensorM.TryGetValue(SensorT.Trigger2, out Index))
{
if (_current_max_Count < Index.Row)
{
_current_max_Count = Index.Row + 1;
_values_list[Index.Row] = new double[n_columns];
}
_values_list[Index.Row][Index.Column] = sp.Trigger2_int_pos;
Index.Row++;
}
}
else {
if (dict_sensorM.TryGetValue(type, out Index))
{
if (_current_max_Count < Index.Row)
{
_current_max_Count = Index.Row;
_values_list.Add(new double[n_columns]);
}
_values_list[Index.Row][Index.Column] = sp.YPoint;
Index.Row++;
}
}
}
if (_current_max_Count > _max_Count) AddToFile();
}
private void AddToFile() {
csv.WriteRecords(_values_list);
}
private SensorT ToSensorT(SensorType stype, int battery)
{
if (stype == SensorType.EMG)
{
return SensorT.EMG;
}
else if (stype == SensorType.EMG_Trigger )
{
if (battery < 0) return SensorT.Trigger1;
else return SensorT.EMG;
}
else if (stype == SensorType.ACC)
{
return SensorT.ACC;
}
else {
return SensorT.Unknown;
}
}
}
/// <summary>
/// In order to create a multivalue dictionary it is necessary another class
/// </summary>
class ListIndex {
public int Column { get; set; }
public int Row { get; set; }
}
}

Categories