Writing a list of arrays using csvhelper C# - 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; }
}
}

Related

Exchange of two elements of a doubly linked list C#

How can I swap two elements of a two-linked list(by switching links)? I realized that I need to consider four cases: change with the first / last elements, change neighboring elements, and all other cases.
The cell structure is as follows:
public class Item<T>
{
private T _Data;
private Item<T> _Next;
private Item<T> _Prev;
public T Value
{
get { return _Data; }
set { this._Data = value; }
}
public Item(T Data)
{
this._Data = Data;
}
public Item()
{
this._Data = default;
}
public Item<T> Next
{
get { return this._Next; }
set { this._Next = value; }
}
public Item<T> Prev
{
get { return this._Prev; }
set { this._Prev = value; }
}
}
This is an implementation attempt. What's wrong?(Here I also do insert sort, but it all depends on the exchange of two elements)
public override D_List<T> Sorting(D_List<T> a)
{
for (int top = 1; top < a.Count; top++)
{
int k = top;
while (k > 0 && a[k-1] > a[k])
{
k--;
}
if (k == 0)
{
a[top].Prev.Next = a[top].Next;
a[top].Next.Prev = a[top].Prev;
a[top].Next = a[k];
a[top].Prev = null;
a[k].Prev = a[top];
}
else if(k == a.Count - 2)
{
a[k].Prev.Next = a[top];
a[top].Prev = a[k].Prev;
a[k].Next = null;
a[k].Prev = a[top];
}
else if(k+1 == top)//стоят подряд
{
a[k].Prev.Next = a[top];
a[top].Prev = a[k].Prev;
a[k].Next = a[top].Next;
a[top].Next = a[k];
a[k].Next.Prev = a[k];
}
else
{
a[k].Prev = a[top];
a[top].Prev.Next = a[top].Next;
a[top].Next.Prev = a[top].Prev;
a[top].Prev = a[k].Prev;
a[top].Next = a[k];
a[top].Next.Prev = a[top];
}
}
return a;
}

Creating arrays of objects of different derived classes using txt file reading. How to do better?

I have an abstract class. From which many other classes are inherited that need to be added to the file.
Then it is necessary to do the exact opposite, that is, the result will be an array of objects of different objects of derived classes.
What would be the best way to do this? Because my implementation seems to me the worst option.
In a text file, it looks like this:
Student JohnCamper
{<<FirstName>> : <<John>>,
<<LastName>> : <<Camper>>,
<<StudentID>> : <<45213>>,
<<Place Of Residence>> : <<94-932>>,
<<Sex>> : <<Male>>}
TaxiDriver ArnoldTrump
{<<FirstName>> : <<Arnold>>,
<<LastName>> : <<Trump>>}
Code:
public abstract class People
{
private Attribute<string>[] _attributes = new Attribute<string>[2];
protected People(string firstName, string lastName)
{
var firstname = new Attribute<string>(firstName, "FirstName");
var lastname = new Attribute<string>(lastName, "LastName");
_attributes[0] = firstname;
_attributes[1] = lastname;
}
public virtual void Teach()
{
Console.WriteLine("teaching someone");
}
public virtual void Study()
{
Console.WriteLine("{engaged in self-education");
}
public virtual void Drive()
{
Console.WriteLine("{is driving");
}
public string[] GetAttributesNames()
{
var result = new string[_attributes.Length];
for (var index = 0; index < result.Length; index++)
{
result[index] = _attributes[index].GetName();
}
return result;
}
public string[] GetAttributesData()
{
var result = new string[_attributes.Length];
for (int index = 0; index < result.Length; index++)
{
result[index] = _attributes[index].GetData();
}
return result;
}
private void Copy()
{
var temp = new Attribute<string>[_attributes.Length + 1];
for (var index = 0; index < _attributes.Length; index++)
{
temp[index] = _attributes[index];
}
_attributes = temp;
}
protected void AddAttribute(Attribute<string> attribute)
{
Copy();
var index = _attributes.Length - 1;
_attributes[index] = attribute;
}
}
public People[] ReadFile()
{
People[] result;
var sizePattern = new Regex(#".*\s{(.|\n)*?}");
var linePattern = new Regex(#"<<.*>>\s:\s<<(.*)>>");
var objTypePattern = new Regex(#"(.*)\s(.*){");
using (var sr = _file.OpenText())
{
var text = sr.ReadToEnd();
var matches = sizePattern.Matches(text);
result = new People[CalcSize(text)];
for (var index = 0; index < matches.Count; index++)
{
result[index] = ObjectCreate(matches[index]);
}
}
return result;
int CalcSize(string text)
{
var count = 0;
foreach (Match match in sizePattern.Matches(text))
{
count++;
}
return count;
}
People ObjectCreate(Match match)
{
People people = null;
var groups = match.Groups;
var objType = match.Value.Split(" ")[0];
var attributes = GetAttributes(match);
if (objType == "Student")
{
people = new Student(attributes[0],attributes[1],attributes[2],attributes[3],attributes[4]);
}
else if (objType == "TaxiDriver")
{
people = new TaxiDriver(attributes[0],attributes[1]);
}
return people;
}
string[] GetAttributes(Match match)
{
var text = match.Value;
var matches = linePattern.Matches(text);
var size = matches.Count;
var attributes = new string[size];
for (var index = 0; index < size; index++)
{
var group = matches[index].Groups;
var temp = group[1].Value;
attributes[index] = temp;
}
return attributes;
}
}
public class Student : People
{
public Student(string firstName, string lastName, string studentId,string stPlaceOfResidence, string studentSex) : base(firstName, lastName)
{
var id = new Attribute<string>(studentId, "StudentID");
var sex = new Attribute<string>(studentSex,"Sex");
var placeOfResidence = new Attribute<string>(stPlaceOfResidence, "Place Of Residence");
AddAttribute(id);
AddAttribute(placeOfResidence);
AddAttribute(sex);
}
public override void Study()
{
Console.WriteLine("Student is studying");
}
}

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?

C# Compare two list and return value

I have a problem. I try compare two list currentItemsInColl and bPList. Inside bPList i have other list RequiredItems and now is what I need.
I want compare currentItemsInColl and RequiredItems and return bPList.craftingBlueprint.
I try Compare but I dont know how use it :/
using Devdog.InventoryPro;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CraftingAutoUpdate : MonoBehaviour {
public ItemCollectionBase itemCollection;
public ItemCollectionBase rewardCollection;
public CraftingCategory craftingCategory;
[Header("Blue Print List")]
public List<BlueprintList> bPList = new List<BlueprintList>();
public List<CurrentItemInCollList> currentItemsInColl = new List<CurrentItemInCollList>();
private CraftingBlueprint readyBlueprint;
public void OnShow()
{
GetBluePrint();
InvokeRepeating("StartUpdate",0f,0.05f);
}
public void OnHide()
{
CancelInvoke("StartUpdate");
}
private void StartUpdate()
{
UpdateDirectory();
UpdateFindMatchItems();
UpdateCraftResults();
}
private void GetBluePrint()
{
bPList.Clear();
foreach (var b in craftingCategory.blueprints)
{
if (b != null)
{
var rI = b.requiredItems;
var listReqItems = new List<RequiredItem>();
foreach (var e in rI)
{
listReqItems.Add(new RequiredItem(e.item.ID, e.amount));
}
bPList.Add(new BlueprintList(b.name, b, listReqItems));
}
}
}
private void UpdateDirectory()
{
currentItemsInColl.Clear();
foreach(var item in itemCollection)
{
if (item.item != null)
{
var cT = item.item.ID;
if (currentItemsInColl.Find(u =>u.itemID == cT) == null)
{
var itemCount = itemCollection.GetItemCount(item.item.ID);
currentItemsInColl.Add(new CurrentItemInCollList(item.item.ID, itemCount));
}
}
}
}
In this methode I try find same items in collections:
private void UpdateFindMatchItems()
{
readyBlueprint = null;
bool matchFailed = false;
int requiredItemCount = 0;
int currentItemsInCollCount = currentItemsInColl.Count;
foreach(var bp in bPList)
{
requiredItemCount = bp.RequiredItems.Count;
foreach(var rI in bp.RequiredItems)
{
if(CompareLists(currentItemsInColl, bp.RequiredItems))
{
print("aa");
}
print(currentItemsInCollCount);
}
}
private void UpdateCraftResults()
{
rewardCollection.Clear();
if (readyBlueprint != null)
{
foreach (var items in readyBlueprint.resultItems)
{
rewardCollection.AddItem(items.item,null,true,false);
}
}
}
I try somthing like this but is wont work with this lists:
public static bool CompareLists<T>(List<T> aListA, List<T> aListB)
{
if (aListA == null || aListB == null || aListA.Count != aListB.Count)
return false;
if (aListA.Count == 0)
return true;
Dictionary<T,T> lookUp = new Dictionary<T,T>();
// create index for the first list
for (int i = 0; i < aListA.Count; i++)
{
uint count = 0;
if (!lookUp.TryGetValue(aListA[i], out count))
{
lookUp.Add(aListA[i], 1);
continue;
}
lookUp[aListA[i]] = count + 1;
}
for (int i = 0; i < aListB.Count; i++)
{
uint count = 0;
if (!lookUp.TryGetValue(aListB[i], out count))
{
// early exit as the current value in B doesn't exist in the lookUp (and not in ListA)
return false;
}
count--;
if (count <= 0)
lookUp.Remove(aListB[i]);
else
lookUp[aListB[i]] = count;
}
// if there are remaining elements in the lookUp, that means ListA contains elements that do not exist in ListB
return lookUp.Count == 0;
}
}
And this is my lists:
/* LISTS */
[Serializable]
public class CurrentItemInCollList
{
public uint itemID;
public uint itemAmount;
public CurrentItemInCollList(uint newitemID, uint newItemAmount)
{
itemID = newitemID;
itemAmount = newItemAmount;
}
}
[Serializable]
public class BlueprintList
{
public string bluePrintName;
public CraftingBlueprint craftingBlueprint;
public List<RequiredItem> RequiredItems = new List<RequiredItem>();
public BlueprintList(string newBluePrintName, CraftingBlueprint newcraftingBlueprint, List<RequiredItem> list)
{
bluePrintName = newBluePrintName;
craftingBlueprint = newcraftingBlueprint;
RequiredItems = list;
}
}
[Serializable]
public class RequiredItem
{
public uint itemID;
public uint itemAmount;
public RequiredItem( uint newitemID, uint newItemAmount)
{
itemID = newitemID;
itemAmount = newItemAmount;
}
}
I forgot.. CurrentItemInCollList.itemAmount can be >= RequiredItems.itemAmount
Dictionary use hash values to compare objects.
The stored classes must implement public override int GetHashCode(){}
Use Linq - here is a small console example:
class Program
{
static void Main(string[] args)
{
//Required list
List<Order> currentItemsInColl = new List<Order>();
currentItemsInColl.Add(new Order() { Name = "bike1", Id = "01" });
currentItemsInColl.Add(new Order() { Name = "bike4", Id = "04" });
//List of all items
List<BPP> bPList = new List<BPP>();
bPList.Add(new BPP() { BikeName = "bike1", Idzzz = "01" });
bPList.Add(new BPP() { BikeName = "bike2", Idzzz = "02" });
bPList.Add(new BPP() { BikeName = "bike3", Idzzz = "03" });
bPList.Add(new BPP() { BikeName = "bike4", Idzzz = "04" });
bPList.Add(new BPP() { BikeName = "bike5", Idzzz = "05" });
//Blueprint List
List<BPP> Blueprint = new List<BPP>();
//get all items into the Blueprint list
foreach (Order i in currentItemsInColl)
{
List<BPP> tmp = bPList.FindAll(x => x.Idzzz.Contains(i.Id));
//here you add them all to a list
foreach (BPP item in tmp)
{
Blueprint.Add(item);
}
}
Console.ReadLine();
}
}
public class Order
{
public string Id { get; set; }
public string Name { get; set; }
}
public class BPP
{
public string Idzzz { get; set; }
public string BikeName { get; set; }
}
Sidenote: i am comparing the ID's in each of the lists! Hope it helps.

Reading values from an .acf / manifest file

The file I'm trying to read is presented in the format below. How using c# can I read this file to extract property values? Are there any libraries I can leverage?
"AppState"
{
"appid" "244210"
"Universe" "1"
"name" "Assetto Corsa"
"StateFlags" "4"
"installdir" "assettocorsa"
"LastUpdated" "1469806809"
"UpdateResult" "0"
"SizeOnDisk" "23498042501"
"buildid" "1251512"
"LastOwner" "76561198018619129"
"BytesToDownload" "11541616"
"BytesDownloaded" "11541616"
"AutoUpdateBehavior" "0"
"AllowOtherDownloadsWhileRunning" "0"
"UserConfig"
{
"language" "english"
}
"MountedDepots"
{
"228983" "8124929965194586177"
"228984" "3215975441341951460"
"228985" "5758075142805954616"
"228990" "1829726630299308803"
"229002" "7260605429366465749"
"244211" "3837890045968273966"
}
"InstallScripts"
{
"0" "_CommonRedist\\vcredist\\2010\\installscript.vdf"
"1" "_CommonRedist\\vcredist\\2012\\installscript.vdf"
"2" "_CommonRedist\\vcredist\\2013\\installscript.vdf"
"3" "_CommonRedist\\DirectX\\Jun2010\\installscript.vdf"
"4" "_CommonRedist\\DotNet\\4.0\\installscript.vdf"
}
}
So I don't know if you still need it, but I wrote it myself.
Here is my code.
In my tests it worked perfectly.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Steam_acf_File_Reader
{
class AcfReader
{
public string FileLocation { get; private set; }
public AcfReader(string FileLocation)
{
if (File.Exists(FileLocation))
this.FileLocation = FileLocation;
else
throw new FileNotFoundException("Error", FileLocation);
}
public bool CheckIntegrity()
{
string Content = File.ReadAllText(FileLocation);
int quote = Content.Count(x => x == '"');
int braceleft = Content.Count(x => x == '{');
int braceright = Content.Count(x => x == '}');
return ((braceleft == braceright) && (quote % 2 == 0));
}
public ACF_Struct ACFFileToStruct()
{
return ACFFileToStruct(File.ReadAllText(FileLocation));
}
private ACF_Struct ACFFileToStruct(string RegionToReadIn)
{
ACF_Struct ACF = new ACF_Struct();
int LengthOfRegion = RegionToReadIn.Length;
int CurrentPos = 0;
while (LengthOfRegion > CurrentPos)
{
int FirstItemStart = RegionToReadIn.IndexOf('"', CurrentPos);
if (FirstItemStart == -1)
break;
int FirstItemEnd = RegionToReadIn.IndexOf('"', FirstItemStart + 1);
CurrentPos = FirstItemEnd + 1;
string FirstItem = RegionToReadIn.Substring(FirstItemStart + 1, FirstItemEnd - FirstItemStart - 1);
int SecondItemStartQuote = RegionToReadIn.IndexOf('"', CurrentPos);
int SecondItemStartBraceleft = RegionToReadIn.IndexOf('{', CurrentPos);
if (SecondItemStartBraceleft == -1 || SecondItemStartQuote < SecondItemStartBraceleft)
{
int SecondItemEndQuote = RegionToReadIn.IndexOf('"', SecondItemStartQuote + 1);
string SecondItem = RegionToReadIn.Substring(SecondItemStartQuote + 1, SecondItemEndQuote - SecondItemStartQuote - 1);
CurrentPos = SecondItemEndQuote + 1;
ACF.SubItems.Add(FirstItem, SecondItem);
}
else
{
int SecondItemEndBraceright = RegionToReadIn.NextEndOf('{', '}', SecondItemStartBraceleft + 1);
ACF_Struct ACFS = ACFFileToStruct(RegionToReadIn.Substring(SecondItemStartBraceleft + 1, SecondItemEndBraceright - SecondItemStartBraceleft - 1));
CurrentPos = SecondItemEndBraceright + 1;
ACF.SubACF.Add(FirstItem, ACFS);
}
}
return ACF;
}
}
class ACF_Struct
{
public Dictionary<string, ACF_Struct> SubACF { get; private set; }
public Dictionary<string, string> SubItems { get; private set; }
public ACF_Struct()
{
SubACF = new Dictionary<string, ACF_Struct>();
SubItems = new Dictionary<string, string>();
}
public void WriteToFile(string File)
{
}
public override string ToString()
{
return ToString(0);
}
private string ToString(int Depth)
{
StringBuilder SB = new StringBuilder();
foreach (KeyValuePair<string, string> item in SubItems)
{
SB.Append('\t', Depth);
SB.AppendFormat("\"{0}\"\t\t\"{1}\"\r\n", item.Key, item.Value);
}
foreach (KeyValuePair<string, ACF_Struct> item in SubACF)
{
SB.Append('\t', Depth);
SB.AppendFormat("\"{0}\"\n", item.Key);
SB.Append('\t', Depth);
SB.AppendLine("{");
SB.Append(item.Value.ToString(Depth + 1));
SB.Append('\t', Depth);
SB.AppendLine("}");
}
return SB.ToString();
}
}
static class Extension
{
public static int NextEndOf(this string str, char Open, char Close, int startIndex)
{
if (Open == Close)
throw new Exception("\"Open\" and \"Close\" char are equivalent!");
int OpenItem = 0;
int CloseItem = 0;
for (int i = startIndex; i < str.Length; i++)
{
if (str[i] == Open)
{
OpenItem++;
}
if (str[i] == Close)
{
CloseItem++;
if (CloseItem > OpenItem)
return i;
}
}
throw new Exception("Not enough closing characters!");
}
}
}

Categories