คำถาม Saving items in listbox to INI

  • 13 เมษายน 2555 13:36
     
      มีโค้ด

    Am using this INI Reader from CodeProject. I have a listbox with some items in it. I wanted to save the items in listbox to my ini file. I used the following code but the problem is, it only saves the final item.

    Dim INI As New IniFile
            INI.Load(Application.StartupPath & "\Config.ini", True)
            For i As Integer = 0 To List.Items.Count - 1
                ini.GetSection("Initiate").AddKey("Part1").Value = List.Items.Item(i)
            Next
            INI.Save(Application.StartupPath & "\Config.ini")

    My Listbox contains the following items:

    ExEffects1

    ExEffects2

    ExEffects3

    What i get:
    
    [Initiate]
    Part1=ExEffects3
    
    What i want:
    
    [Initiate]
    Part1=ExEffects1
    Part1=ExEffects2
    Part1=ExEffects3


ตอบทั้งหมด

  • 13 เมษายน 2555 15:11
     
     

    IIRC you cannot have more than one entry with same key and different values. That's what is meant by a key.

    You could change the AddKey() to be AddKey("Part" & i.ToString())


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

  • 13 เมษายน 2555 15:14
     
     

    Have you create the IniFile class, like its there? 

    If you would "copy" all the code it sure would work.

    Check again, you sure missed something.


    Mitja

  • 14 เมษายน 2555 6:39
     
     

    @Riced: Ouch, thats bad news. Do you know any other way of writing/modifying INI files like i said?

    @Mitja Bonca: Yes i have IniFile class. Am using a dll file from that link i posted.

  • 14 เมษายน 2555 6:56
     
     

    I could be wrong - not used .INI files for over a decade, so you would have to check. It's just that in general a key has one value only and I'd expect that to be the case in a .INI.

    A quick google seems to confirm that is the case.So it looks like you have to use distinct keys or do a roll your own ini type file.


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

  • 14 เมษายน 2555 7:09
     
     

    Is there any reason you want to use that vintage ini file, it is currently completely replaces by XML style files?

    (Like the standard ProgramName.Config in .Net programs)


    Success
    Cor

  • 14 เมษายน 2555 8:18
     
      มีโค้ด

    Is there any reason you want to use that vintage ini file, it is currently completely replaces by XML style files?

    (Like the standard ProgramName.Config in .Net programs)


    Success
    Cor

    haha :) i like that "vintage ini file". But i must stick to ini file :(

    This is the original AddKey function:

    ' Adds a key to the IniSection object, returns a IniKey object to the new or existing object
            Public Function AddKey(ByVal sKey As String) As IniKey
                sKey = sKey.Trim()
                Dim k As IniSection.IniKey = Nothing
                If sKey.Length <> 0 Then
                    If m_keys.ContainsKey(sKey) Then
                        k = DirectCast(m_keys(sKey), IniKey)
                    Else
                        k = New IniSection.IniKey(Me, sKey)
                        m_keys(sKey) = k
                    End If
                End If
                Return k
            End Function

    I changed like this assuming it will write all the items, but still it only writes the last item in my listbox.

    Public Function AddKey(ByVal sKey As String) As IniKey 
        Dim iniKey As IniKey
        sKey = sKey.Trim()
        Dim iniKey2 As IniKey = Nothing
        If (sKey.Length = 0 OrElse Me.m_keys.ContainsKey(sKey)) Then
            iniKey2 = New IniKey(Me, sKey)
            Me.m_keys.Item = sKey
        End If
        Return iniKey2
    End Function

  • 14 เมษายน 2555 8:31
     
     

    Suppose you got it working with multiple Part1 keys. When you retrieve the key what do expect for the value? How would you know which is applicable, or are they all applicable?

    Maybe the solution is to concatenate the list items (perhaps using | as separator) before adding the key. When the key is retrieved you can then split the list and deal with items as required.

    "Thoughts of a dry brain in a dry season." Eliot, Gerontion.


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

  • 14 เมษายน 2555 9:24
     
     

    Suppose you got it working with multiple Part1 keys. When you retrieve the key what do expect for the value? How would you know which is applicable, or are they all applicable?

    Maybe the solution is to concatenate the list items (perhaps using | as separator) before adding the key. When the key is retrieved you can then split the list and deal with items as required.

    "Thoughts of a dry brain in a dry season." Eliot, Gerontion.

    They are all applicable. I just want it to write the keys no matter if it exists or not. Will you please take a look if i give you the source of IniFile?
  • 14 เมษายน 2555 9:56
     
     

    I've had a quick look at the VB code from the CodeProject download.

    It uses a HashTable to store sections and within sections uses a HashTable to store keys. So it looks like to achieve what you want you would have to change the type of keys so that it is a Dictionary(Of string, List(Of string)) rather than a single value. That might mean modifying the methods in the IniSection class. Alternatively you might be able to modify the IniKey class so that the value field (m_sValue) is a ListOf(string) rather than a string.

    Without checking the code more carefully that's all I can suggest.

    Might comments earlier referred to the old DOS/Windows .INI files rather than this particular implementation. It looks, however, that they still apply.


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

  • 14 เมษายน 2555 13:16
     
     

    I've had a quick look at the VB code from the CodeProject download.

    It uses a HashTable to store sections and within sections uses a HashTable to store keys. So it looks like to achieve what you want you would have to change the type of keys so that it is a Dictionary(Of string, List(Of string)) rather than a single value. That might mean modifying the methods in the IniSection class. Alternatively you might be able to modify the IniKey class so that the value field (m_sValue) is a ListOf(string) rather than a string.

    Without checking the code more carefully that's all I can suggest.

    Might comments earlier referred to the old DOS/Windows .INI files rather than this particular implementation. It looks, however, that they still apply.

    So can you please make the changes.
  • 14 เมษายน 2555 14:43
     
     

    Not prepared to meet para 3.d of the license - too much work to document the changes.

    I do not think the file you want to produce is an .ini file, as the term is usually understood, and that's why IniFile does not do what you want.

    However, if you can describe the contents of the file it may be possible to knock up a bespoke class that deals with that specific layout. It can be a lot simpler than IniFile because it deals with a general .ini file. And that may be less work than hacking IniFile to meet what you want.

    Is there any specific reason for having the key occur multiple times? I'd guess that the easiest way is to concatenate the list box items (with a separator) before writing and split them on reading. This would mean no changes to IniFile which might cause problems in other parts of you program.


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

  • 14 เมษายน 2555 15:07
     
     

    Not prepared to meet para 3.d of the license - too much work to document the changes.

    I do not think the file you want to produce is an .ini file, as the term is usually understood, and that's why IniFile does not do what you want.

    However, if you can describe the contents of the file it may be possible to knock up a bespoke class that deals with that specific layout. It can be a lot simpler than IniFile because it deals with a general .ini file. And that may be less work than hacking IniFile to meet what you want.

    Is there any specific reason for having the key occur multiple times? I'd guess that the easiest way is to concatenate the list box items (with a separator) before writing and split them on reading. This would mean no changes to IniFile which might cause problems in other parts of you program.

    Ok I'll describe. What i have is a listbox with a button (Browse button) which adds items to the listbox. So when my client clicks Save Button i want it to add the items in the listbox in a section called "Initiate" under key name "Part1". I simply want to add more "Part1" Key names with different values. Thats all i want with my program. It will be a great help if you can write a Iniclass that does this. Oh and one more thing. This INI that am talking about has other entries in it and already has Initiate section with Part1 Key name. I just want to add more, without messing anything else. And there is a reason for that key occuring multiple times :)


    • แก้ไขโดย theronnie 14 เมษายน 2555 15:08
    •  
  • 14 เมษายน 2555 15:46
     
     

    there is a reason for that key occuring multiple times

    So what's the reason? It's highly unusual for a key to have multiple values (especially in .ini files). And when it does the easiest way to deal with it is to concatenate the vales and extract them after reading the key. Is there a good reason that cannot be done?

    Consider this: suppose you have a file with multiple copies of a key. A call is made to read the key. Which copy  does it return? The first, the second, the third,..., all of them? If a routine was written that added multiple copies of a key, how would the program determine which copy to use when reading the key? Is that another IniFile hack that needs to be made?

    This INI that am talking about has other entries in it and already has Initiate section with Part1 Key name.

    So is it not only a case of multiplies values for a given key, but multiple section with the same name? That makes it a somewhat different problem. And the same point about reading it applies. Given the section name, which copy should be returned.

    If the questions seem to be obtuse, remember I know nothing about the application other than what you have posted. And that amounts to: it has a list box that you want to save in a text file that can be processed using IniFile, and  with all items having the same key value (which IniFile cannot do).


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

  • 14 เมษายน 2555 17:25
     
     

    there is a reason for that key occuring multiple times

    So what's the reason? It's highly unusual for a key to have multiple values (especially in .ini files). And when it does the easiest way to deal with it is to concatenate the vales and extract them after reading the key. Is there a good reason that cannot be done?

    Consider this: suppose you have a file with multiple copies of a key. A call is made to read the key. Which copy  does it return? The first, the second, the third,..., all of them? If a routine was written that added multiple copies of a key, how would the program determine which copy to use when reading the key? Is that another IniFile hack that needs to be made?

    This INI that am talking about has other entries in it and already has Initiate section with Part1 Key name.

    So is it not only a case of multiplies values for a given key, but multiple section with the same name? That makes it a somewhat different problem. And the same point about reading it applies. Given the section name, which copy should be returned.

    If the questions seem to be obtuse, remember I know nothing about the application other than what you have posted. And that amounts to: it has a list box that you want to save in a text file that can be processed using IniFile, and  with all items having the same key value (which IniFile cannot do).

    Ok Riced. This app is more like a extension to the original application. This one is implemented with that app. I cannot give you much details about it. But your doubt is genuine about "Which call to make". Well the app gets the values randomly. So if the INI file contains multiple values with the same key inside the section, it will call them randomly.

    And there is no multiple section with the same name. The ini file already have Initiate section with Part1 Key and i DONT want to add Initiate section . All i want is to ADD more KEYS with the name "Part1" to that INI Section (Initiate).

  • 14 เมษายน 2555 23:14
     
     

    I still don't grasp the reason for having multiple copies of a key. Nor how it is supposed to get the values (I assume from the ini) randomly. It would have to know how many there are (that may be fixed you don't say if it is).

    Here's how I would do wha I think you want to do.

    To save multiple values to same key
       Dim INI As New IniFile
       INI.Load(Application.StartupPath & "\Config.ini", True)
        Dim temp As String = List.Items.Item(0)
       For i As Integer = 1 To List.Items.Count - 1
           temp = temp & "|" & List.Items.Item(i)
       Next
        INI.GetSection("Initiate").AddKey("Part1").Value = temp
       INI.Save(Application.StartupPath & "\Config.ini")


    'Assuming INI exists and has been loaded
       Dim part1Values() as String = INI.GetKeyValue("Initiate", "Part1").Split(New [Char]() {""|"c})
        'At this point part1Values contains the values from the List
        'so you can do what you want - select one at random, populate a listbox whatever.

    No need to change the IniFile code in any way. Unless there is a specific reason the ini file has to have a separate line for each value I cannot see why you do not do this.


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

  • 15 เมษายน 2555 6:58
     
      มีโค้ด

    I still don't grasp the reason for having multiple copies of a key. Nor how it is supposed to get the values (I assume from the ini) randomly. It would have to know how many there are (that may be fixed you don't say if it is).

    Here's how I would do wha I think you want to do.

    To save multiple values to same key
       Dim INI As New IniFile
       INI.Load(Application.StartupPath & "\Config.ini", True)
        Dim temp As String = List.Items.Item(0)
       For i As Integer = 1 To List.Items.Count - 1
           temp = temp & "|" & List.Items.Item(i)
       Next
        INI.GetSection("Initiate").AddKey("Part1").Value = temp
       INI.Save(Application.StartupPath & "\Config.ini")


    'Assuming INI exists and has been loaded
       Dim part1Values() as String = INI.GetKeyValue("Initiate", "Part1").Split(New [Char]() {""|"c})
        'At this point part1Values contains the values from the List
        'so you can do what you want - select one at random, populate a listbox whatever.

    No need to change the IniFile code in any way. Unless there is a specific reason the ini file has to have a separate line for each value I cannot see why you do not do this.

    I copy/pasted that code and this is what i get:

    [Initiate]
    Part1=ExEffects1|ExEffects2|ExEffects3

    Am getting this error in part1Values() as String part.

    Error    3    Character is not valid. --> {""|"c}

    So i changed the line to this: Dim part1Values As String = INI.GetKeyValue("Initiate", "Part1").Split(New [Char]() {"|"c}) and this Dim part1Values As String = INI.GetKeyValue("Initiate", "Part1").Split(New Char() {"|"c}). Both of these shows the below error message.

    Value of type '1-dimensional array of String' cannot be converted to 'String'.

    One quick question. I can see that now part1Values has all the values i want. That is:

    ExEffects1
    ExEffects2
    ExEffects3
    But still i dont get how to save 'em like i want. Because if i use "For i as Integer..." loop, it will still only save the last entry. Right?
  • 15 เมษายน 2555 7:44
     
     

    Dim part1Values As String() = INI.GetKeyValue("Initiate", "Part1").Split(New [Char]() {"|"c})

    will return a string array, asuming your saved string looks like
         ExEffects1|ExEffects2|ExEffects3
    A string array can be placed in a list box using AddRange.

    To create a string that looks like that, use the Join method with a string array:
    http://msdn.microsoft.com/en-us/library/system.string.join(v=vs.100).aspx
    http://msdn.microsoft.com/en-us/library/57a79xd0.aspx

  • 15 เมษายน 2555 8:31
     
     

    Apologies for syntax errors - just typed it in without checking in VS. But they should be easy to fix - if you still have a problem post the code and I'll check it.

    If you look at the code it loops around concatenating the items to the string. When the loop completes the key is added to the ini so the ini contains a key that has all the values not just the last one. You cannot save them like you want (i.e. multiple lines for the key with one value per line) unless IniFile is modified to do that. And that means modifying it quite a bit.

    Acamar's solution with the Join() would replace the loop. It's a neater way of doing it, I just copied and edited your code from a previous post (thought it might be easier to see what was happening).


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

  • 15 เมษายน 2555 9:57
     
     

    Thanks Riced. What you said was right. To get what i want the IniFile needs to be modified which i have no idea what to do. Guess i have to drop this :(

    Thanks everyone for the help. Really appreciated. Gracias a todos.