3
$\begingroup$

I have faced a quite simple problem, but, honestly, I don't know what would be better to do. I have a .ini file generated by a Fortran program with with this type of data:

abcd   =   1234.0
efgh   =   .false.
(* etc. *)

I need to import it into Mathematica and assign the corresponding values to the variables abcd and efgh.

My solution is:

data = Import["file", "Table"]

As a result we have such structure:

{{"params_ini"}, {"abcd", "=", 1234.}, {"efgh", "=", ".false."}, ...}

Finally,

First[data[[2]]] = Last[data[[2]]]
(* etc *)

I am sure that there are simpler ways to do it. Does anyone know?

$\endgroup$
  • $\begingroup$ closely related: 783 $\endgroup$ – Kuba Aug 7 '17 at 20:39
  • $\begingroup$ Is the data in your .ini file limited to numbers and booleans? $\endgroup$ – m_goldberg Aug 8 '17 at 1:01
  • $\begingroup$ Yes, there are only numbers and booleans $\endgroup$ – Alex Aug 8 '17 at 9:37
5
$\begingroup$

Mathematica can import .ini files, although it wants the data definitions to be in the form "item=value". That is, it does not expect white space. Also, it doesn't understand that ".true." and ".false." represent booleans. Still there are advantages to importing the file directly as an .ini file.

Let's explore how we might go about it.

I will use a file called data.ini which contains the text

a   =   1234.0
b   =   .false.
c   =   1.23e3
d   =   text
e   =   -1.23E-2
f   =   .true.

As you can see this file provides a greater range of test data than the one you proposed.

path = FileNameJoin[{$HomeDirectory, "Desktop", "data.ini"}];
iniData = 
  Association[
    Map[StringTrim[StringTrim[#], "."] &, Import[path, "DataRules"], {-1}]]

<|"a" -> "1234.0", "b" -> "false", "c" -> "1.23e3", "d" -> "text", "e" -> "-1.23E-2", "f" -> "true"|>

We get an association. However, we still need to convert the strings representing numbers and booleans to Mathematica numbers and booleans. I suggest doing that with an interpreter because interpreters can recognize the strings "true" and "false" and handle Fortran numbers of the form "1.23e03", and "45.12E-3".

data = Interpreter["Number" | "Boolean"| "String"] /@ iniData

<|"a" -> 1234., "b" -> False, "c" -> 1230., "d" -> "text", "e" -> -0.0123, "f" -> True|>

I think the association data might be an entirely satisfactory representation for your .ini file data and that there is no need to go further. But if you insist on making assignments, they can be done this way.

Clear[a, b, c, d, e, f]
KeyValueMap[Set[Evaluate[Symbol[#1]], #2] &, data];
{a, b, c, d, e, f}

{1234., False, 1230., "text", -0.0123, True}

Update

The above requires V11.1 or later. Those using an earlier version should try

data = 
  Association[
    Rule @@@ 
      (Import[path, "Table"] /. 
         {"=" -> (## &[]), ".true." -> True, ".false." -> False})]

This code, while somewhat more obscure in concept, has advantages even for those who have V11.1. (Doesn't require the use of Interpreter.) Still requires a version late enough to support associations.

$\endgroup$
  • $\begingroup$ Thank you very much for your answer. However, I still have a couple of questions. 1) I don not exactly understand, what "DataRules" is. Should I use RegisterImport function like in this article? 2) I need to use this variables and their values in the following code. Why do you think, that it is better to use associations? $\endgroup$ – Alex Aug 8 '17 at 11:42
  • $\begingroup$ @Alex. 1) "DataRules" tells Import to represent the imported data as a list of rules. To see what that looks like, evaluate Import[path, "DataRules"] by itself (remember in Mathematic, you can evaluate anything). The .ini file is already known to Import so there no need use RegisterImport. $\endgroup$ – m_goldberg Aug 8 '17 at 18:25
  • $\begingroup$ @Alex. 2) Associations have many advantages over a making a large set of global variables. You don't have to worry about polluting the global name space. You don't have worry about messing up previously assigned variables. Retrieval of values from an association is very quick. Associations can be used pretty much like structs in C or C++. For example, you can retrieve 1234. by writing data["a"] and reassign to it with ``data["a"] = 42.5`, so you really don't need variables. $\endgroup$ – m_goldberg Aug 8 '17 at 18:37
  • $\begingroup$ 1) I asked you about this, because I can not run the code. There is an error "The Import element "DataRules" is not present when importing as "Table" (more information). Sorry, if I did something awkward) $\endgroup$ – Alex Aug 9 '17 at 13:41
  • $\begingroup$ @Alex. What version of Mathematica are you using? Built-in support for .ini files was added to Mathematica in V11.1. $\endgroup$ – m_goldberg Aug 9 '17 at 14:07
2
$\begingroup$

Your code as written will run into a problem because:

  1. First[data[[2]]] = Last[data[[2]]] will attempt to assign a value to the LHS without evaluating it, which will generate an error.
  2. Even if the LHS were evaluated, it would produce a string, and you cannot assign a value to a string.

You could modify this by using Evaluate[ToExpression[First[data[[2]]]]] on the LHS.

Alternatively, if you drop the second argument from the Import command, and you include the file extension, Mathematica will generate an Association from your .ini file, which you can then use to reference the values.

data=Import["file.ini"];
data["abcd"]
(*1234.0*)
data["efgh"]
(*.false.*)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.