如何在ruby中读取INI文件

drkbr07n  于 2023-06-22  发布在  Ruby
关注(0)|答案(7)|浏览(132)

如何在ruby中读/写ini文件我有一个ini文件
1.读
1.更改分录
1.写出到不同的位置
我在Ruby怎么做?这方面的记录是暗淡的。

btqmn9zl

btqmn9zl1#

使用InIFile Gem

正如@method所说,使用inifile gem。还有一个ini gem,但我还没有用过。
我发现documentation heredocumentation here稍微更有帮助,documentation here是gem页面链接的地方。
这里没有太多的例子,所以这里有一些代码可以让你开始:

设置示例

首先,创建一个包含以下内容的文件/tmp/desktop.ini

[Desktop Entry]
Version=1.0
Type=Application
Name=Foo Viewer
Comment=The best viewer for Foo objects available!
TryExec=fooview
Exec=fooview %F
Icon=fooview

确保您已经从命令行运行了gem install inifile

示例代码

创建一个类似/tmp/ini-test.rb的文件,包含以下内容:

require 'inifile'
require 'pp'

# read an existing file
file = IniFile.load('/tmp/desktop.ini')
data = file["Desktop Entry"]

#output one property
puts "here is one property:"
puts data["Name"]

# pretty print object
puts "here is the loaded file:"
pp file

# create a new ini file object
new_file = IniFile.new

# set properties
new_file["Desktop Entry"] = {
    "Type" => "Application",
    "Name" => 'test',
    "Exec" => 'command',
}

# pretty print object
puts "here is a object created with new:"
pp new_file

# set file path
new_file.filename = "/tmp/new_ini_file.ini"

# save file
new_file.write()
puts "the new object has been saved as a file to /tmp/new_ini_file.ini"

示例结果

使用ruby /tmp/ini-test.rb运行该文件应该会产生如下结果:

here is one property:
Foo Viewer

here is the loaded file:
{ this output hidden for brevity }

here is a object created with new:
#<IniFile:0x007feeec000770
 @comment=";#",
 @content=nil,
 @default="global",
 @encoding=nil,
 @escape=true,
 @filename=nil,
 @ini=
  {"Desktop Entry"=>
    {"Type"=>"Application",
     "Name"=>"test",
     "Exec"=>"command",
     "Icon"=>"icon_filename",
     "Comment"=>"comment"}},
 @param="=">

the new object has been saved as a file to /tmp/new_ini_file.ini

根据需要进行修改以满足您的需求。

mbyulnm0

mbyulnm02#

我最近用了ruby-inifile。也许与这里的简单片段相比,这是矫枉过正。。

weylhg0b

weylhg0b3#

这里的模块用于阅读和写入. ini文件,尽可能减少对原始文件的更改(用于读取人类和机器的文件):
``

class IniFileExc < RuntimeError
end 

 class IniNode
  def initialize(name, value=nil)
    @line_start = -1;
    @line_end = -1;
    @level = 0;
    @name = name;
    @value = value;
    @keys = {};
    @keylist = [];
    @modified = false;
    @deleted = false;
  end
  attr_reader :level,:line_start,:line_end,:name,:value,:keylist,:keys,:modified,:deleted
  attr_writer :level,:line_start,:line_end,:name,:value,:keylist,:keys,:modified,:deleted

 def to_str
    return @name.to_s + ' = ' + @value.to_s;
  end

 def to_s
    return @value.to_s;
  end
  def to_i
    return @value.to_i
  end
  def to_f
    return @value.to_f;
  end

 def 
    insert(key, nil);
    return @keys[key];
  end

 def insert(key, value)
    return false  if (@keys.has_key?(key));
    node = nil;
    if (value && ((value.class == IniNode) || (value.class == IniSection)))
      node = value;
    else
      if (@level <= 0)
        node = IniSection.new(key);
      else
        node = IniNode.new(key, value)
      end
    end
    node.line_start = @line_end + 1  if (node.line_start < 0);
    node.level = @level + 1;
    @keys[key] = node;
    @keylist.push(key);
    return true;
  end

 def []=(key, value)
    rc = insert(key, value);
    @keys[key].value = value;
    @keys[key].modified = true;
    @modified = true;
  end

 def delete(key)
    return false  if (! @keys.has_key?(key));
    @keys[key].deleted = true;
    @modified = true;
  end
end

 class IniSection < IniNode
  def initialize(name)
    super(name);
  end

 def to_str
    return  ('[' + @name + ']');
  end
end

``

class IniFile < IniNode
  def initialize(path, load=true)
    super(path);
    @lines = [];
    reload()  if (load);
  end 

 def reload
    begin
      input = File.new(@name, "r");
    rescue
      raise;
    else
      prevnode = node = self;
      lineno = 0;
      input.each do |line|
        @lines.push(line);
        parsed_node = parse_line(lineno, line);
        if (parsed_node);
          if (parsed_node.class == IniSection)
            if (parsed_node != node)
              prev_node = node;
              node = parsed_node;
              insert(node.name, node);
              prev_node.line_end = lineno - 1;
            end
          else
            node.insert(parsed_node.name, parsed_node);
          end
        end
        lineno += 1;
      end
      input.close;

   node.line_end = @line_end = lineno - 1;
end

 end

 def parse_line(lineno, line)
    return nil  if (line =~ /^\s*$/);
    return nil  if (line =~ /^\s*#/);
    return nil  if (line =~ /^\s*;/);
    if (line =~ /^\s*[\s*(.+)\s*].$/)
      rv = IniSection.new($1);
      rv.line_start = lineno;
      rv.level = @level + 1;
      return rv;
    elsif (line =~ /^\s(\S?.[^=\s])\s=\s*(\S?[^#;][^#;\s\n]).$/)
      rv = IniNode.new($1, $2);
      rv.line_start = rv.line_end = lineno;
      rv.level = @level + 2;
      return rv;
    end
    return nil;
  end

 def write
    inserted = {};
    @keylist.each do |sect|
      sectnode = @keys[sect];
      next  if (!sectnode.modified || sectnode.deleted);
      if (sectnode.line_end < 0)
        @lines.push("\n");
        @lines.push(sectnode.to_str + "\n");
      end
      sectnode.keylist.each do |key|
        keynode = sectnode.keys[key];
        next  if (!keynode.modified || keynode.deleted);
        if (keynode.line_end < 0)
          if (sectnode.line_end < 0)
            @lines.push(keynode.to_str + "\n");
          else
            idx = sectnode.line_end.to_i;
            inserted[idx] = []  if (! inserted.has_key?(idx));
            inserted[idx].push(keynode.to_str);
          end
        else
          line = @lines[keynode.line_start];
          if (line =~ /^(\s*)(\S?.[^=\s]\s=\s*\S?.+[^#;\s])(\s*[#;].)$/)
            line = $1 + keynode.to_str + $3 + "\n";
          else
            line = line.gsub(/^(\s)(\S?.[^=\s]\s=\s*\S?[^#;]+[^#;\n\s])(.*)$/){
              $1 + keynode.to_str + $3};
          end
          @lines[keynode.line_start] = line;
        end
      end
    end

``

deleted = {};
    @keylist.each do |sect|
      sectnode = @keys[sect];
      next  if (!sectnode.deleted && !sectnode.modified);
      if (sectnode.deleted && (sectnode.line_start >= 0) && (sectnode.line_end >= 0) \
          && (sectnode.line_end >= sectnode.line_start))
        for i in sectnode.line_start..sectnode.line_end
          deleted[i] = true;
        end
      end
      sectnode.keylist.each do |key|
        keynode = sectnode.keys[key];
        next  if (!keynode.deleted);
        deleted[keynode.line_start.to_i] = true  \
          if ((keynode.line_start >= 0) && (keynode.line_end >= 0) && (keynode.line_start == keynode.line_end));
      end
    end 

 begin
  file = File.new(@name, 'w');
rescue
  raise(IniFileExc, "Failed to open " + @name + " for writing: #{$!}", caller);
else
  cnt = -1;
  @lines.each do |line|
    cnt += 1;
    if (inserted.has_key?(cnt))
      inserted[cnt].each do |ins|
        file.puts(ins + "\n");
      end
    end
    next  if (deleted[cnt]);
    file.puts(line);
  end
  file.close;
end

 end
end

使用示例:

begin
  ini = IniFile.new('file.ini');
  ini['common']['param'] = 'value';
  ini['common'].delete('unused_param');
  ini.delete('unused_section');
  print "Valuable value: ", ini['common']['param'], "\n";
  ini.write;
rescue IniFileExc
  print "Oh, that's not good: ", $!, "\n";
end

希望这能帮上忙。

3mpgtkmj

3mpgtkmj5#

如果我没理解错的话

outFile = File.new('out.ini', 'w')
File.open('in.ini', 'r') do |inFile|
  inFile.each_line do |line|
    # foo is the entry you want to change, baz is its new value.
    outFile.puts(line.sub(/foo=(.*)/, 'foo=baz'))
  end
end
outFile.close

请注意,当您将File.open与块一起使用时,当块终止时,文件将自动关闭。

a5g8bdjr

a5g8bdjr6#

我遇到了同样的问题,并尝试使用inifile,这里也提到了ini gem,它只是一个旧版本,不兼容Ruby >= 1.9。我遇到了一些问题:inifile 3.0.0 can't read quoted values,2.0.2可以,但打破了他们,也不能读取列表值分隔为;,只保存第一部分-我猜它认为他们作为注解,但我也不希望注解被删除-并添加额外的空格和空行.
所以我决定标准的GLib X1 E1 F1 X阅读器是最可靠的解决方案,并使用了这个X1 E2 F1 X。你可以在这里看到整个脚本和结果的比较,但它基本上是这样做的

require 'glib2'

file1 = GLib::KeyFile.new
file1.load_from_file(filename1)
file2 = GLib::KeyFile.new
# you can also use file2.load_from_data(File.read(filename2))
file2.load_from_file(filename2)
file1.set_string(group, key, file2.get_string(group, key))
# the binding doesn't expose save_to_file, so we have no choise
File.open(filename2, "w") do |out|
  out.write file1.to_data
end

您还可以看到一个示例here。我注意到的唯一意想不到的变化是在文件末尾添加了一个换行符。
我还找到了iniparsegem,它在我的情况下工作得很好,结果是一样的,但我仍然觉得GLib更可靠。我将使用与inifile相同的API创建一个inifile-glib gem,如果这样做了,我将更新答案。

xj3cbfub

xj3cbfub7#

file = File.new("your.ini", "r")
  while (line = file.gets)
   puts "#{line}" #additionally make changes
  end
file.close

相关问题