3

It seems that the user.config file for Properties.Settings can handle an empty string value correctly using a <value /> tag, but a value consisting of one ore more spaces only, (for example "    ") does not get stored as...

    <value>    </value>

but rather as...

     <value>
     </value>

and thus includes a CRLF and 'indentation' spaces.

How do I save a setting of one or more space characters?

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
JDR
  • 51
  • 3

3 Answers3

3

If the white-spaces are important use CDATA:

<value><![CDATA[    ]]></value>
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • Most likely not, because   is an HTML entity and has no meaning in a .NET config file. Even if it would work, it would be a different character than a normal space. – Daniel Hilgarth Jan 22 '13 at 16:25
  • True, it is a HTML entity, but using & for an ampersand works in a .config file :) – Mathew Thompson Jan 22 '13 at 16:27
  • Because that also is an XML entity. – Daniel Hilgarth Jan 22 '13 at 16:27
  • Thanks for these suggestions, but neither solves the issue. Using CDATA means that the next time the property is loaded into the program (eg. string prop = Properties.Settings.Default.MyProp), you get the CDATA string (eg. prop is now "<![CDATA..."). The same thing happens if using  . Incidentally, the P.S.D.Save() auto-converts &, <. and > to &, <, and >. – JDR Jan 23 '13 at 18:21
  • @JDR: That I can't conform. CDATA works for me. The important point is that you have to enter it directly in the user.config, and *not* via the settings tab in the project properties. I have to admit however, that this will be lost as soon as you try to save that value back, i.e. there is no way to create that CDATA node other than by manual editing of the user.config. – Daniel Hilgarth Jan 23 '13 at 18:43
  • All the described behaviour was determined by watching the user.config file in a text editor while a C# program displayed the property setting in a textbox, which could then be edited and the text saved back to the property setting (which is basically how a user would save preferences). – JDR Jan 23 '13 at 22:43
2

Thanks for these suggestions, but neither solves the issue. Using CDATA means that the next time the property is loaded into the program (eg. string prop = Properties.Settings.Default.MyProp), you get the CDATA string (eg. prop is now "<![CDATA..."). The same thing happens if using &nbsp;. Incidentally, the P.S.D.Save() auto-converts &, <, and > to &amp;, &lt;, and &gt; entities.

Basically string (and char) settings are saved and restored correctly if they are EITHER null OR contain at least one non-space character, but a string of one or more spaces (or a char of one space) is NOT saved correctly.

This issue arose with a program which allows the user to set a string to be used as a line-indentation prefix ( eg. "----", " ", etc.). I have since altered the program to avoid this space-string bug, but it seems to me that a string of spaces should still be a perfectly valid "property"!

JDR
  • 51
  • 3
0

For others which will looking for how to save 'SPACE' in config...

You can simple use it's decimal value from ASCII table (http://www.asciitable.com/). So for space character it's value 32. Some examples...:

EXAMPLE 1:

Save single space in App.config

config section:

<setting name="OneSpaceString" serializeAs="String">
    <value>32</value>
</setting>

Application section:

char space = Convert.ToChar(int.Parse(Properties.Settings.Default.OneSpaceString));
string stringSpace = space.ToString();

EXAMPLE 2:

Save multi space string in config (there is a lot of ways how to do it, but for example...)

Config section

<setting name="MultiSpaceString" serializeAs="String">
    <value>32;32;32;32</value>
</setting>

Application section:

char[] spaces = Properties.Settings.Default.MultiSpaceString.GetCharsByDecimal(new char[] { ';' });
string stringSpaces = string.Join(string.Empty, spaces);

//Extension method for getting chars by decimal from our string
public static char[] GetCharsByDecimal(this string inputString, char[] delimiters)
    {
        int[] charsDecimals = inputString.Split(delimiters, StringSplitOptions.RemoveEmptyEntries).Select(s => int.Parse(s)).ToArray();
        char[] resultChars = new char[charsDecimals.Length];

        for (int i = 0; i < charsDecimals.Length; i++)
        {
            resultChars[i] = Convert.ToChar(charsDecimals[i]);
        }

        return resultChars;
    }

//Or safer variant of our extension method
public static char[] GetCharsByDecimal(this string inputString)
    {
        int[] charsDecimals = Regex.Split(inputString, @"\D+").Select(s => int.Parse(s)).ToArray();
        char[] resultChars = new char[charsDecimals.Length];

        for (int i = 0; i < charsDecimals.Length; i++)
        {
            resultChars[i] = Convert.ToChar(charsDecimals[i]);
        }

        return resultChars;
    }

EXAMPLE 3:

Save delimiters (including space) in config

Config section

<setting name="Delimiters" serializeAs="Xml">
                <value>
                    <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                        <string>59</string>
                        <string>44</string>
                        <string>9</string>
                        <string>45</string>
                        <string>124</string>
                        <string>32</string>
                    </ArrayOfString>
                </value>
            </setting>

Application section

char[] delimiters = Properties.Settings.Default.Delimiters.Cast<string>().Select(s => Convert.ToChar(int.Parse(s))).ToArray();
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Blaato
  • 129
  • 10
  • This makes the config file rather hard to configure from a user's perspective and also means you need to create an additional layer of code to read from or write to any string properties. – Sphynx May 12 '21 at 18:28