首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >解析INI文件

解析INI文件
EN

Stack Overflow用户
提问于 2012-05-07 23:12:32
回答 3查看 801关注 0票数 0

我正在使用C++/CLI在Visual Studio2008中构建一个程序,我一直试图将我的默认用户目录设置保存在一个txt文件中。到目前为止,我设法将它保存在txt文件中,如下所示。

代码语言:javascript
运行
复制
Input Directory=C:\Input
Output Directory=C:\Output

问题是,我的程序如何检测单词"Input Directory=“并只接受它后面的单词呢?

有没有办法在文本文件中搜索特定的单词,并在C++/CLI中替换它?例如,我可以搜索"C:\Input“并将其替换为"D:\Input”。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-05-09 01:06:14

经过一天的努力寻找简单的解决方案后,我决定省略@Hans Passant建议的"Input Directory =“,并做一个粗略的变通方法,使用类似于this的技术,将第一行读取为输入,第二行读取为输出文件夹设置。

感谢所有回复的人。

票数 0
EN

Stack Overflow用户

发布于 2012-05-07 23:17:42

您可以通过多种方式读取文件。使用c++\cli的好处之一是您可以利用非常简洁的.net接口。

因此,您可以使用File::ReadAllLines,然后扫描每一行以查找字符串"Input Directory“

票数 1
EN

Stack Overflow用户

发布于 2012-05-07 23:30:25

我认为它是一种类似INI的语法,但没有节,为了解析它,需要执行以下操作。

在将用于解析文件的类的构造函数中(例如):

  • 创建一个Dictionary<string, string>,您将在其中保留已解析的值(为键指定一个不区分大小写的比较器)。
  • 读取文件的每一行,跳过空行(如果您想支持,则跳过注释行)。
  • 在每个字符串行中搜索第一个"=“字符。左边的部分是选项的名称,右边的部分是值。
  • 将它们保存在字典中。

GetValue()方法中执行以下操作:

  • 在字典中搜索给定的键并返回它。
  • 如果没有任何具有给定值的键,只需返回默认值。

这是一个简单的INI解析器的可能实现(如果您不需要节名称,只需为其传递一个空字符串)。

代码语言:javascript
运行
复制
using namespace System;
using namespace System::Text;
using namespace System::IO;
using namespace System::Globalization;
using namespace System::Collections::Generic;

namespace Testy
{
    ref class IniParser
    {
    public:
        IniParser()
        {
            _values = gcnew Dictionary<String^, Dictionary<String^, String^>^>(
                StringComparer::InvariantCultureIgnoreCase);
        }

        IniParser(String^ path) 
        {
            _values = gcnew Dictionary<String^, Dictionary<String^, String^>^>(
                StringComparer::InvariantCultureIgnoreCase);

            Load(path);
        }

        void Load(String^ path)
        {
            String^ currentSection = "";
            for each (String^ line in File::ReadAllLines(path))
            {
                if (String::IsNullOrWhiteSpace(line))
                    continue;

                if (line->StartsWith(L";", StringComparison::InvariantCultureIgnoreCase))
                    continue;

                if (line->StartsWith(L"[", StringComparison::InvariantCultureIgnoreCase) && line->EndsWith(L"]", StringComparison::InvariantCultureIgnoreCase))
                {
                    String^ sectionName = line->Substring(1, line->Length - 2);
                    if (String::IsNullOrWhiteSpace(sectionName))
                        continue;

                    currentSection = sectionName;
                }

                array<String^>^ parts = line->Split(gcnew array<wchar_t>(2) { '=' }, 2);
                if (parts->Length == 1)
                    SetString(currentSection, parts[0]->Trim(), "");
                else
                    SetString(currentSection, parts[0]->Trim(), parts[1]->Trim());
            }
        }

        bool ContainsSection(String^ sectionName)
        {
            return _values->ContainsKey(sectionName);
        }

        bool ContainsValue(String^ sectionName, String^ valueName)
        {
            Dictionary<String^, String^>^ values = GetSection(sectionName);
            if (values == nullptr)
                return false;

            return values->ContainsKey(valueName);
        }

        void Clear()
        {
            _values->Clear();
        }

        void SetString(String^ sectionName, String^ valueName, String^ value)
        {
            Dictionary<String^, String^>^ values = GetSection(sectionName);
            if (values == nullptr)
            {
                values = gcnew Dictionary<String^, String^>(StringComparer::InvariantCultureIgnoreCase);
                _values->Add(sectionName, values);
            }

            if (values->ContainsKey(valueName))
                values[valueName] = value;
            else
                values->Add(valueName, value);
        }

        String^ GetString(String^ sectionName, String^ valueName, String^ defaultValue)
        {
            Dictionary<String^, String^>^ values = GetSection(sectionName);
            if (values == nullptr)
                return defaultValue;

            if (values->ContainsKey(valueName))
                return values[valueName];

            return defaultValue;
        }

    private:
        Dictionary<String^, Dictionary<String^, String^>^>^ _values;

        Dictionary<String^, String^>^ GetSection(String^ sectionName)
        {
            if (_values->ContainsKey(sectionName))
                return _values[sectionName];

            return nullptr;
        }
    };
}

您应该添加错误检查,并且可以省略不需要的部分(例如,节和注释)。要“读取”不同的值类型,可以实现更多的GetXYZ()方法来将GetString()的结果解析为所需的值(例如,float )。

另一种解决方案是通过to...simply导入本地函数来解析INI。它们工作得很好!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10484550

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档