C# 从.acf/manifest文件读取值

C# 从.acf/manifest文件读取值,c#,manifest,steam,C#,Manifest,Steam,我试图读取的文件的格式如下所示。如何使用c#读取此文件以提取属性值?有我可以利用的库吗 "AppState" { "appid" "244210" "Universe" "1" "name" "Assetto Corsa" "StateFlags" "4" "installdir" "assettocorsa" "LastUpdated" "1469806809" "UpdateResult" "0" "SizeOnD

我试图读取的文件的格式如下所示。如何使用c#读取此文件以提取属性值?有我可以利用的库吗

"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"
}
}

所以我不知道你是否还需要它,但我自己写的。 这是我的密码

在我的测试中,它工作得非常好

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!");
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.IO;
名称空间Steam\u acf\u文件\u读取器
{
AcfReader类
{
公共字符串文件位置{get;private set;}
公共AcfReader(字符串文件位置)
{
if(File.Exists(FileLocation))
this.FileLocation=FileLocation;
其他的
抛出新的FileNotFoundException(“错误”,FileLocation);
}
公共bool CheckIntegrity()
{
字符串内容=File.ReadAllText(文件位置);
int quote=Content.Count(x=>x==“”);
int-braceleft=Content.Count(x=>x='{');
int-braceright=Content.Count(x=>x=''}');
返回((括号左==括号右)&&(引号%2==0));
}
公共ACF_结构ACFFileToStruct()
{
返回acffieltostruct(File.ReadAllText(FileLocation));
}
私有ACF_结构ACFFileToStruct(字符串区域读入)
{
ACF_Struct ACF=新的ACF_Struct();
int LengthOfRegion=区域读取长度;
int CurrentPos=0;
while(长度区域>当前位置)
{
int FirstItemStart=RegionToReadIn.IndexOf(“”,CurrentPos);
如果(FirstItemStart==-1)
打破
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);
如果(SecondItemStartBraceleft==-1 | | SecondItemStartQuote打开项)
返回i;
}
}
抛出新异常(“结束字符不足!”);
}
}
}

我知道我可以去掉空白,并在引号之间找到值,但这相当不容易。