10

我需要将.ini文件解析为数组,然后更改数组的值并将其导出到同一个.ini文件。我设法读取了该文件,但没有找到任何简单的方法将其写回。有什么建议么?

示例.ini文件:

1 = 0;
2 = 1372240157;    // timestamp.
4

5 回答 5

11

为了写.ini回文件,您需要创建自己的函数,因为 PHP 没有提供开箱即用的函数,除了读取(可以在这里找到:http: //php.net/manual/pl/function.解析-ini-file.php)。

可能将多维数组封装为.ini-syntax 兼容字符串的函数示例可能如下所示:

function arr2ini(array $a, array $parent = array())
{
    $out = '';
    foreach ($a as $k => $v)
    {
        if (is_array($v))
        {
            //subsection case
            //merge all the sections into one array...
            $sec = array_merge((array) $parent, (array) $k);
            //add section information to the output
            $out .= '[' . join('.', $sec) . ']' . PHP_EOL;
            //recursively traverse deeper
            $out .= arr2ini($v, $sec);
        }
        else
        {
            //plain key->value case
            $out .= "$k=$v" . PHP_EOL;
        }
    }
    return $out;
}

你可以像这样测试它:

$x = [
  'section1' => [
    'key1' => 'value1',
    'key2' => 'value2',
    'subsection' => [
      'subkey' => 'subvalue',
      'further' => ['a' => 5],
      'further2' => ['b' => -5]]]];
echo arr2ini($x);

(请注意,短数组语法仅在 PHP 5.4+ 之后可用。)

另请注意,它不会保留您问题中存在的评论。当软件(而不是人类)更新文件时,没有简单的方法来记住它们。

于 2013-06-26T10:05:48.917 回答
3

我对rr-提供的功能进行了重大更改(非常感谢您的启动!)

我对该版本中处理多维属性的方式不满意。我从parse_ini_file的 php 文档页面中获取了示例 ini 文件,并得到了一个包含键的结果third_section.phpversion-third_section.urls不是我所期望的。

我尝试使用RecursiveArrayIterator进行无限嵌套,但不幸的是,带有键值对的标头是parse_ini_string在收到错误消息之前将处理的最大递归限制。

所以我从头开始,添加了一些曲线球作为第四个也是最后一个项目,最后得到了这个:

$test = array(
    'first_section' => array(
        'one' => 1,
        'five' => 5,
        'animal' => "Dodo bird",
    ),
    'second_section' => array(
        'path' => "/usr/local/bin",
        'URL' => "http://www.example.com/username",
    ),

    'third_section' => array(
        'phpversion' => array(5.0, 5.1, 5.2, 5.3),
        'urls' => array(
            'svn' => "http://svn.php.net",
            'git' => "http://git.php.net",
        ),
    ),

    'fourth_section' => array(
        7.0, 7.1, 7.2, 7.3,
    ),
    'last_item' => 23,
);
echo '<pre>';
print_r($test);
echo '<hr>';
$ini = build_ini_string($test);
echo $ini;
echo '<hr>';
print_r( parse_ini_string($ini, true) );

function build_ini_string(array $a) {
    $out = '';
    $sectionless = '';
    foreach($a as $rootkey => $rootvalue){
        if(is_array($rootvalue)){
            // find out if the root-level item is an indexed or associative array
            $indexed_root = array_keys($rootvalue) == range(0, count($rootvalue) - 1);
            // associative arrays at the root level have a section heading
            if(!$indexed_root) $out .= PHP_EOL."[$rootkey]".PHP_EOL;
            // loop through items under a section heading
            foreach($rootvalue as $key => $value){
                if(is_array($value)){
                    // indexed arrays under a section heading will have their key omitted
                    $indexed_item = array_keys($value) == range(0, count($value) - 1);
                    foreach($value as $subkey=>$subvalue){
                        // omit subkey for indexed arrays
                        if($indexed_item) $subkey = "";
                        // add this line under the section heading
                        $out .= "{$key}[$subkey] = $subvalue" . PHP_EOL;
                    }
                }else{
                    if($indexed_root){
                        // root level indexed array becomes sectionless
                        $sectionless .= "{$rootkey}[] = $value" . PHP_EOL;
                    }else{
                        // plain values within root level sections
                        $out .= "$key = $value" . PHP_EOL;
                    }
                }
            }

        }else{
            // root level sectionless values
            $sectionless .= "$rootkey = $rootvalue" . PHP_EOL;
        }
    }
    return $sectionless.$out;
}

我的输入和输出数组匹配(无论如何在功能上),我的 ini 文件如下所示:

fourth_section[] = 7
fourth_section[] = 7.1
fourth_section[] = 7.2
fourth_section[] = 7.3
last_item = 23

[first_section]
one = 1
five = 5
animal = Dodo bird

[second_section]
path = /usr/local/bin
URL = http://www.example.com/username

[third_section]
phpversion[] = 5
phpversion[] = 5.1
phpversion[] = 5.2
phpversion[] = 5.3
urls[svn] = http://svn.php.net
urls[git] = http://git.php.net

我知道这可能有点矫枉过正,但我​​在自己的两个项目中确实需要这个功能。现在我可以读取一个ini文件,进行更改并保存它。

于 2017-07-23T14:04:00.157 回答
1

RR 的答案有效,我添加了一个更改

在 else 语句中

//plain key->value case
$out .= "$k=$v" . PHP_EOL;

将其更改为

//plain key->value case
$out .= "$k=\"$v\"" . PHP_EOL;

通过在值周围加上 ",您可以在 INI 中使用较大的值,否则 parse_ini_* 函数将出现问题

http://missioncriticallabs.com/blog/2009/08/double-quotation-marks-in-php-ini-files/

于 2015-02-05T16:13:56.033 回答
0

这是我对rr-的增强版答案(感谢他),我的函数是 生态系统中类的一部分,因此使用了一个名为Arr::isAssoc的函数,它基本上是检测给定数组是否为关联数组或不。


  private function arrayToConfig(array $array, array $parent = []): string
  {
    $returnValue = '';

    foreach ($array as $key => $value)
      {
        if (is_array($value)) // Subsection case
          {
            // Merge all the sections into one array
            if (is_int($key)) $key++;
            $subSection = array_merge($parent, (array)$key);
            // Add section information to the output
            if (Arr::isAssoc($value))
              {
                if (count($subSection) > 1) $returnValue .= PHP_EOL;
                $returnValue .= '[' . implode(':', $subSection) . ']' . PHP_EOL;
              }
            // Recursively traverse deeper
            $returnValue .= $this->arrayToConfig($value, $subSection);
            $returnValue .= PHP_EOL;
          }
        elseif (isset($value)) $returnValue .= "$key=" . (is_bool($value) ? var_export($value, true) : $value) . PHP_EOL; // Plain key->value case
      }

    return count($parent) ? $returnValue : rtrim($returnValue) . PHP_EOL;
  }
于 2021-06-01T12:31:28.967 回答
-2

使用 php 内部函数怎么样?http://php.net/manual/en/function.parse-ini-file.php

于 2013-06-26T09:56:20.600 回答