Ok i was wondering if i could get some ideas or feedback or somthn from my user managment system, there is one part i know i could do better but im not sure how to do it, so some ideas please...
Public Function userAdd(ByVal userName As String, ByVal userAcces As String, ByVal userAddedBy As String) As String
If userName <> "" And userAcces <> "" And userAddedBy <> "" Then
If File.Exists(App_Path() + "/users/" + userName + ".txt") = True Then
'user exists (update user)
Dim oRead As System.IO.StreamReader
Dim oFile As System.IO.File
Dim oWrite As System.IO.StreamWriter = oFile.CreateText(App_Path() + "/users/" + userName + ".txt")
oWrite.WriteLine("Username=" & userName)
oWrite.WriteLine("Acces=" & userAcces)
oWrite.WriteLine("AddedBy=" & userAddedBy)
oWrite.Close()
Return "User updated [ " + userName + " ] added with acces [ " + userAcces + " ]"
Else
'user doesnt exist
Dim fs As New FileStream(App_Path() + "/users/" + userName + ".txt", FileMode.Create, FileAccess.Write)
fs.Close()
Dim oRead As System.IO.StreamReader
Dim oFile As System.IO.File
Dim oWrite As System.IO.StreamWriter = oFile.CreateText(App_Path() + "/users/" + userName + ".txt")
oWrite.WriteLine("Username=" & userName)
oWrite.WriteLine("Acces=" & userAcces)
oWrite.WriteLine("AddedBy=" & userAddedBy)
oWrite.Close()
Return "User [ " + userName + " ] added with acces [ " + userAcces + " ]"
End If
Else
Return "Information In Unacceptable Format. Correct Format: [username] [userlevel]"
End If
End Function
Public Function userDel(ByVal userName As String) As String
If File.Exists(App_Path() + "/users/" + userName + ".txt") = True Then
System.IO.File.Delete(App_Path() + "/users/" + userName + ".txt")
Return "User [ " + userName + " ] removed from database."
Else
Return "User [ " + userName + " ] was not found in the database."
End If
End Function
Public Function userFind(ByVal userName As String) As String
If File.Exists(App_Path() + "/users/" + userName + ".txt") = True Then
Dim oRead As System.IO.StreamReader
Dim oFile As System.IO.File
Dim a() As String
Dim LineIn As String
Dim userAcces As String
Dim userAddedBy As String
oRead = oFile.OpenText(App_Path() + "/users/" + userName + ".txt")
While oRead.Peek <> -1
LineIn = oRead.ReadLine()
a = LineIn.Split("=")
If a(0) = "Username" Then
userName = a(1)
End If
If a(0) = "Acces" Then
userAcces = a(1)
End If
If a(0) = "AddedBy" Then
userAddedBy = a(1)
End If
End While
Return "User [" + userName + "] with acces of [" + userAcces + "], user was added by [" + userAddedBy + "]"
oRead.Close()
Else
Return "User not found in database."
End If
End Function
here is the part i know could be done better (it is in the above code)
'user doesnt exist
Dim fs As New FileStream(App_Path() + "/users/" + userName + ".txt", FileMode.Create, FileAccess.Write)
fs.Close()
Dim oRead As System.IO.StreamReader
Dim oFile As System.IO.File
Dim oWrite As System.IO.StreamWriter = oFile.CreateText(App_Path() + "/users/" + userName + ".txt")
You should store all the info in an array (using a Type declaration), and only access the file at certain times (IE: load on run, save on close, load/save on demand). That would greatly improve the speed (I mean noticeably too, not by .02ms or something).
let me just make sure i am understanding u right so
Program Starts -> Load Users Into Array
-edit question removed, answered on aim
Program Ends -> Save Array Back into Files
also can anyone help me with the save on close part ;D
Quote from: Zer0 on October 05, 2006, 02:26 PM
also can anyone help me with the save on close part ;D
Yes. When the program ends (Form.Closing event of your main Form), do the same thing you do when you have a save-on-demand.
I would have created my user object, created a typed collection for the user object, marked both serializable, and serialized the user collection to file..
Serialization/Deserialization is much cleaner than the code to read - parse - proceed...
Namespace Management
<Serializable()> Public Class User
Public Name As String
Public Password As String
<XmlIgnore()> Public hash As New System.Security.Cryptography.HMACSHA1(System.Text.ASCIIEncoding.ASCII.GetBytes("mykey"))
Public Sub New()
End Sub
Public Sub New(ByVal _Name As String, ByVal _Password As String)
Name = _Name
Password = _Password
End Sub
Public Function Validate(ByVal ClearTextPW As String) As Boolean
Return GetPasswordHash(ClearTextPW).Equals(Password)
End Function
Public Function SetPassword(ByVal CleartextOldPW As String, ByVal CleartextNewPW As String) As Boolean
If Validate(CleartextOldPW) Then
Password = GetPasswordHash(CleartextNewPW)
Return True
End If
Return False
End Function
Private Function GetPasswordHash(ByVal ClearTextPW As String) As String
Return BitConverter.ToString(hash.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(ClearTextPW)))
End Function
End Class
<Serializable()> Public Class UserCollection
Inherits CollectionBase
Private _Serializer As XmlSerializer = New System.Xml.Serialization.XmlSerializer(GetType(UserCollection))
Default Public Property Items(ByVal index As Integer) As User
Get
If index >= 0 And index < list.Count Then Return DirectCast(List(index), User)
End Get
Set(ByVal Value As User)
If index >= 0 And index < list.Count Then list(index) = Value
End Set
End Property
Default Public Property Items(ByVal Name As String) As User
Get
Dim index As Integer = Me.IndexOf(Name)
If Not index < 0 Then Return DirectCast(List(index), User)
End Get
Set(ByVal Value As User)
Dim index As Integer = Me.IndexOf(Name)
If Not index < 0 Then list(index) = Value
End Set
End Property
Public Overloads Function Equals(ByVal Users As UserCollection) As Boolean
If Not Users.Count = list.Count Then Return False
For index As Integer = 0 To List.Count - 1
If Not Users(index).Equals(Me(index)) Then Return False
Next
Return True
End Function
Public Function Add(ByVal Item As User) As Integer
If Not Me.Contains(Item) Then Return list.Add(Item)
End Function
Public Function Contains(ByVal Item As User) As Boolean
Return list.Contains(Item)
End Function
Public Sub CopyTo(ByVal Array As User(), ByVal index As Integer)
list.CopyTo(Array, index)
End Sub
Public Sub CopyTo(ByVal Array As IList, ByVal index As Integer)
For Each item As User In Me.List
Array.Add(item)
Next
End Sub
Public Function IndexOf(ByVal Item As User) As Integer
Return list.IndexOf(Item)
End Function
Public Function IndexOf(ByVal Name As String) As Integer
For index As Integer = 0 To list.Count - 1
If Name.ToLower.Equals(Me(index).Name.ToLower) Then
Return index
End If
Next
Return -1
End Function
Public Sub Insert(ByVal Index As Integer, ByVal Item As User)
list.Insert(Index, Item)
End Sub
Public Sub Remove(ByVal Item As User)
list.Remove(Item)
End Sub
Public Sub Remove(ByVal Name As String)
For index As Integer = 0 To list.Count - 1
If Me(index).Name.Equals(Name) Then
list.RemoveAt(index)
Exit For
End If
Next
End Sub
Public Function Save(ByVal Path As String) As Boolean
Dim fs As IO.FileStream
Try
IO.File.Copy(Path, Path & ".bak")
fs = IO.File.Open(Path, IO.FileMode.Truncate, IO.FileAccess.Write)
_Serializer.Serialize(fs, Me)
IO.File.Delete(Path & ".bak")
fs.Close()
Catch
fs.Close()
IO.File.Delete(Path)
IO.File.Move(Path & ".bak", Path)
End Try
Return True
End Function
Public Sub New(ByVal Path As String)
Dim fs As IO.FileStream
Try
fs = IO.File.Open(Path, IO.FileMode.Open, IO.FileAccess.Read)
Dim lc As UserCollection = _Serializer.Deserialize(fs)
lc.CopyTo(Me.List, 0)
Finally
fs.Close()
End Try
End Sub
Public Sub New()
End Sub
End Class
End Namespace
It's long - but you can edit users, add user, delete users from the UserCollection, and call the save method to save it... [you'd want to update the save routine to meet your specs for the filename etc...] and by calling the overloaded new on UserCollection it will deserialize the file into a collection of your user objects.
XML ftw?
While I don't disagree, you can serialize List<T> into XML as long as you provide a root node name in metadata.... I have to look through my test projects at work, it's possible. Then you just pass the List<User> into the XML serializer.
However, I disagree on the use of the serialization framework. XML is probably not so much an evildoer in this instance, but for sure the binary formatter does not emit version-flexible output. Doing custom serialization as far as custom output or even writing custom XML files is FAR more flexible than trusting it to the serialization framework.
Quote from: MyndFyre[vL] on November 16, 2006, 12:37 AM
However, I disagree on the use of the serialization framework. XML is probably not so much an evildoer in this instance, but for sure the binary formatter does not emit version-flexible output. Doing custom serialization as far as custom output or even writing custom XML files is FAR more flexible than trusting it to the serialization framework.
True, but not as simple, nor as quick. The inability to (de)serialize DateTime objects is the killer - and you have to hack in a timespan and convert it
Quote from: indulgence on November 16, 2006, 11:40 AM
Quote from: MyndFyre[vL] on November 16, 2006, 12:37 AM
However, I disagree on the use of the serialization framework. XML is probably not so much an evildoer in this instance, but for sure the binary formatter does not emit version-flexible output. Doing custom serialization as far as custom output or even writing custom XML files is FAR more flexible than trusting it to the serialization framework.
True, but not as simple, nor as quick. The inability to (de)serialize DateTime objects is the killer - and you have to hack in a timespan and convert it
What? DateTime is serializable.
You can also do custom serialization via using DateTime.FromFileTime and DateTime.ToFileTime().