У меня есть массив, содержащий имена пользователей. Вот как это выглядит:

dim numberofaccounts as integer
dim username(numberofaccounts) as string

Я хочу где-то хранить эти данные, чтобы при повторном открытии вся информация уже была там. Я устал использовать My.Settings.usernames, но он не может содержать массивы.

Я подумал, что можно было бы использовать текстовый документ для сохранения этой информации. Я знаю, как это написать и как прочитать информацию о слове doc, но он получается как единая информация, например. Дэвид, Дэн, Фред ,. не как 3 бита информации.

Будет около 100 аккаунтов

1
Nathan 29 Окт 2015 в 16:35

2 ответа

Лучший ответ

Как упоминал Плутоникс, существует специальный тип массива строк, который можно использовать с My.Settings. Это называется StringCollection.

См. здесь .

После перехода к свойствам проекта и добавления нового параметра типа StringCollection (оставьте значение пустым).

В вашем коде вы можете создавать и получать доступ к значениям следующим образом:

My.Settings.UserNames = New Specialized.StringCollection()
My.Settings.UserNames.Add("User 1")
My.Settings.Save()

Как уже упоминали другие, это может быть не лучшим способом хранения имен пользователей, особенно если количество пользователей велико.

3
Drarig29 29 Окт 2015 в 21:09

Использование My.Settings в этом случае - не лучшее решение. Хотя да, .NET позаботится о сохранении данных и загрузке их за вас, данные в My.Settings непостоянны. Если ваше приложение компилируется как ManagedCode (что делает почти весь код .NET), элементы My.Settings привязаны к версии приложения Assembly. Если вы измените версию своей сборки, вы потеряете данные, хранящиеся в My.Settings, поскольку код .NET будет рассматривать вашу сборку как совершенно новое приложение. Более того, если файл .exe будет перемещен и запущен с другого пути, настройки также будут потеряны, поскольку .NET будет смотреть на приложение и совершенно другой экземпляр.

Лучшим вариантом было бы сохранить данные самостоятельно. Вы можете сделать это, сериализовав объект и сохранив его в файл. Когда вы десериализуете файл, возвращается тот же самый объект, который был сохранен. Я бы посоветовал создать класс, который является оболочкой для массива или даже лучше List(Of String). Вот пример консольного приложения для справки:

' Always, always, always use these (unless you have a few edge cases, usually reflection)
Option Strict On
Option Explicit On

' Makes for shorter code
Imports System.Runtime

Module Module1
    Sub Main()
        ' File path to save the file, hardcoded here just for an example
        Dim filePath As String = "C:\StackOverflow\usernames.dat"
        ' Set it to Nothing to prove that the below methods work, if they don't you'll get an NRE
        Dim userNames As UsernameWrapper = Nothing

        Console.Write("do you want to read from the file or write to a file? [r / w] ")
        If Console.ReadKey.Key = ConsoleKey.W Then
            Console.WriteLine() : Console.WriteLine("Enter three usernames:")
            ' Create the object that we want to save
            userNames = New UsernameWrapper({Console.ReadLine, Console.ReadLine, Console.ReadLine})
            'Save the object to a file
            userNames.SaveToFile(filePath)
        Else
            ' Get the object from the file
            userNames = UsernameWrapper.ReadFromFile(filePath)
            Console.WriteLine() : Console.WriteLine("Saved usernames loaded from file:")
            ' Output the contents
            userNames.UserNames.ForEach(Sub(x) Console.Write(x & " ")) : Console.WriteLine()
        End If


        Console.WriteLine()
        Console.Write("Run Again? [y / n] ")
        If Console.ReadKey.Key = ConsoleKey.Y Then
            Console.WriteLine() : Console.WriteLine()
            ' Set it to nothing to prove that the above methods are working,
            ' if they didn't work you'd get a NRE on next run
            userNames = Nothing
            ' Call Main() again for a new run
            Main()
        End If

    End Sub

End Module


' This is the key to the whole thing, this attribute is what allows the object to be serialized
<Serializable()>
Public Class UsernameWrapper
    Public Property UserNames As List(Of String)

    ' Just a few ways of instantiating the object
    Public Sub New()
        Me.UserNames = New List(Of String)
    End Sub
    Public Sub New(ByVal usernameArray() As String)
        Me.UserNames = usernameArray.ToList()
    End Sub

    Public Sub New(ByVal userNameList As List(Of String))
        Me.UserNames = userNameList
    End Sub

    ''' <summary>
    ''' Save the current object to a file
    ''' </summary>
    ''' <param name="filePath">Path to save the file to</param>
    ''' <remarks>http://stackoverflow.com/users/2659234</remarks>
    Public Sub SaveToFile(ByVal filePath As String)
        ' Create the formatter that will do the serialization
        Dim formatter As Serialization.IFormatter = New Serialization.Formatters.Binary.BinaryFormatter()
        Using fs As New IO.FileStream(filePath, IO.FileMode.Create, IO.FileAccess.Write)
            ' Serialize the data
            formatter.Serialize(fs, Me)
        End Using
    End Sub

    ''' <summary>
    ''' Load object from file
    ''' </summary>
    ''' <param name="filePath">Path of the file to read from</param>
    ''' <returns>The deseerailized object</returns>
    ''' <remarks>http://stackoverflow.com/users/2659234</remarks>
    Public Shared Function ReadFromFile(ByVal filePath As String) As UsernameWrapper
        ' Create the formatter that will do the serialization
        Dim formatter As Serialization.IFormatter = New Serialization.Formatters.Binary.BinaryFormatter()
        ' The deserialized object will be saved to this
        Dim _usernameWrapper As UsernameWrapper = Nothing

        Using fs As New IO.FileStream(filePath, IO.FileMode.Open, IO.FileAccess.Read)
            ' Deserialize the object and cast it to the correct type
            _usernameWrapper = TryCast(formatter.Deserialize(fs), UsernameWrapper)
        End Using

        ' If the deserializing failed, throw an error
        If IsNothing(_usernameWrapper) Then Throw New Runtime.Serialization.SerializationException(String.Format("Could not deserialize {0}.", filePath))

        Return _usernameWrapper
    End Function
End Class
1
вʀaᴎᴅᴏƞ вєнᴎєƞ 29 Окт 2015 в 15:53