如何保存数组?

How do I save an array?

我有一个包含用户名的数组。这是它的样子:

dim numberofaccounts as integer
dim username(numberofaccounts) as string

我想将这些数据存储在某个地方,这样当我重新打开它时,所有信息都已经存在了。我已经厌倦了使用 "My.Settings.usernames" 但它不能容纳数组。

我在想也许可以用word文档来保存这些信息。我知道如何编写它以及如何阅读 doc 一词上的信息,但它作为一条信息出现,例如大卫、丹、弗雷德。不是 3 位信息。

将有大约 100 个帐户

正如 Plutonix 提到的,有一种特殊类型的字符串数组可以与 My.Settings 一起使用。它被称为 StringCollection.

参见here

转到项目属性并添加 StringCollection 类型的新设置后(将值留空)。

在您的代码中,您可以按如下方式创建和访问值:

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

正如其他人所提到的,这可能不是存储用户名的好方法,尤其是在用户数量很大的情况下。

在这种情况下使用 My.Settings 不是最佳解决方案。是的,.NET 会负责保存数据并为您加载数据,My.Settings 中的数据是易变的。如果您的应用程序编译为 ManagedCode(大多数 .NET 代码都这样做),则 My.Settings 项与应用程序的程序集版本相关联。如果您更改程序集的版本,您将丢失存储在 My.Settings 中的数据,因为 .NET 代码会将您的程序集视为一个全新的应用程序。此外,如果 .exe 文件从不同的路径移动和执行,设置也将丢失,因为 .NET 将查看应用程序和一个完全不同的实例。

更好的选择是自己保存数据。您可以通过序列化对象并将其保存到文件中来实现。当您反序列化文件时,return 将与保存的对象完全相同。我建议创建一个 class 作为数组的包装器,甚至更好的是 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:\Whosebug\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://whosebug.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://whosebug.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