如何在ruby中读取INI文件

时间:2009-03-03 18:55:10

标签: ruby configuration

如何在ruby中读/写一个ini文件。我有一个我需要的ini文件

  1. 更改条目
  2. 写到不同的位置
  3. 我如何在红宝石中做到这一点?关于这方面的文件很惨淡。

6 个答案:

答案 0 :(得分:12)

使用InIFile Gem

正如@method所说,使用inifile gem。还有一个ini宝石,但我还没有使用它。

我发现documentation here比宝石页链接到的documentation here更有帮助。

没有太多的例子,所以这里有一些代码可以帮助你入门:

示例设置

首先,使用以下内容创建文件/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

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

答案 1 :(得分:11)

我最近使用过ruby-inifile。与这里简单的片段相比,这可能是过度杀伤......

答案 2 :(得分:2)

这是用于读取和写入.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

node.line_end = @line_end = lineno - 1; 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

希望这有帮助。

答案 3 :(得分:1)

这是另一种选择: http://rubygems.org/gems/ini

答案 4 :(得分:0)

如果我理解正确,

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时,文件将在块终止时自动关闭。

答案 5 :(得分:-4)

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