2013-06-05 3 views
0

Я создаю простую программу, которая может использоваться для сохранения контактов и информации о ее контакте. У меня есть проблемы с функциями сохранения/загрузки и всего количества вставленных контактов. Большинство кода взяты из учебника «TheNewBoston», и поскольку мне понравилось, я пытаюсь добавить дополнительные функции. Вот исходный код:vb.net Сохранить/Загрузить файл и другие проблемы

Public Class Form1 

    Dim myCustomers As New ArrayList 
    Dim FILE_NAME As String = "C:\test.txt" 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
     AddCustomer("Sam", "Bond", "[email protected]", "9541032163") 
     AddCustomer("Merry", "Jackson", "[email protected]", "8872101103") 
     AddCustomer("Rachel", "Smith", "[email protected]", "4839078565") 
     'DOESN'T WORK'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 
     If System.IO.File.Exists(FILE_NAME) = True Then 
      'AddCustomer.System.IO.StreamReader(FILE_NAME) 
      'or 
      AddCustomer(System.IO.StreamReader(FILE_NAME)) 
     Else 
      MessageBox.Show("File does not exist.") 
     End If 
    End Sub 

    'Public variables 
    Private Structure Customer 
     Public FirstName As String 
     Public LastName As String 
     Public Email As String 
     Public Phone As Decimal 

     'Does Name = First&Last Name 
     Public ReadOnly Property Name() As String 
      Get 
       Return FirstName & " " & LastName 
      End Get 
     End Property 

     'Shows the customers in the listbox properly overriding the default ToString function 
     Public Overrides Function ToString() As String 
      Return Name 
     End Function 

    End Structure 

    'Declaring and connecting to type Customer 
    Private objCustomer As Customer 
    Private objNewCustomer As Customer 

    'Makes customer format 
    Private Sub AddCustomer(ByVal firstName As String, ByVal lastName As String, ByVal email As String, ByVal phone As Decimal) 
     'declares objNewCustomer with the type of customer for use 
     Dim objNewCustomer As Customer 

     'Connects the Customer's 4 things to objNewCustomer 
     objNewCustomer.FirstName = firstName 
     objNewCustomer.LastName = lastName 
     objNewCustomer.Email = email 
     objNewCustomer.Phone = phone 

     'Adds to myCustomers array list the objNewCustomer 
     myCustomers.Add(objNewCustomer) 
     'Adds customer Name to list 
     listCustomers.Items.Add(objNewCustomer.ToString()) 
    End Sub 

    'Avoids customer select error 
    Private ReadOnly Property SelectedCustomer() As Customer 
     Get 
      If listCustomers.SelectedIndex <> -1 Then 
       Return CType(myCustomers(listCustomers.SelectedIndex), Customer) 
      End If 
     End Get 
    End Property 

    'Enables select customer 
    Private Sub listCustomers_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles listCustomers.SelectedIndexChanged 
     DisplayCustomer(SelectedCustomer) 
    End Sub 


    'Loads the customers' information 
    Private Sub DisplayCustomer(ByVal cust As Customer) 
     txtName.Text = cust.Name 
     txtFirstName.Text = cust.FirstName 
     txtLastName.Text = cust.LastName 
     txtEmail.Text = cust.Email 
     txtPhone.Text = cust.Phone 
    End Sub 


    'Add User (pops up new window) 
    Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click 
     Form2.Show() 
     'System.IO.File.WriteAllText("C:\test.txt", Textbox1.Text) 
    End Sub 

    'WORKS 
    Private Sub btnTotal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTotal.Click 
     txtTotal.Text = myCustomers.Count.ToString() 
    End Sub 

    'Private Total2 As Integer 
    'experimenting 
    'Private Sub DisTotal(ByVal Total As Integer) 
    ' Do 
    '  'total2 = myCustomers.Count.ToString() 
    '  'txtTotal.Text = total2 
    '  txtTotal.Text = Total 
    '  System.Threading.Thread.Sleep(5000) 
    ' Loop 
    'End Sub 

    Private Sub listTotal_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) 
     Total = myCustomers.Count 
     'DOESN'T WORK'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 
     Do 
      'total2 = myCustomers.Count.ToString() 
      'txtTotal.Text = total2 
      txtTotal.Text = myCustomers.Count.ToString() 
      System.Threading.Thread.Sleep(5000) 
     Loop 
    End Sub 

    Private Total As Integer 
    'DOESN'T WORK'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 
    Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click 
     Dim writer As New IO.StreamWriter(FILE_NAME) 

     Try 
      writer.Write("") 
      writer.Close() 
     Catch ex As Exception 
      MessageBox.Show(ex.Message) 
     Finally 
      writer.Close() 
     End Try 
    End Sub End Class 

Любая помощь/намек оценил, а также, если вы разместите исправлены блоки коды, пожалуйста, объясните, как это работает/что было неправильно тоже, спасибо.

+0

Что exectly не работает? Какая ошибка отображается в окне сообщения? Вместо использования создателя потока вы можете проверить [текстовый редактор] (http://msdn.microsoft.com/en-us/library/system.io.textwriter.aspx), он выглядит так, как вы пытаетесь сделать , –

+0

Во-первых, «клиенты» не должны быть жестко закодированы, поэтому я пытаюсь сохранить их в .txt и загрузить их в начале приложения. Во-вторых, мне удалось отобразить общее количество «клиентов», нажав кнопку, но я пытаюсь отобразить их без кнопки в начале приложения. Ошибок пока нет. – Jim

ответ

2

Вы пытаетесь использовать средство чтения потоков в качестве аргументов для своей функции AddCustomer - это не сработает. На самом деле, вы не можете использовать в порядке, вы объявляете его вообще в StreamReader - вы должны самостоятельно создать так:

Dim sr as New StreamReader 
Dim line as String 
line = sr.ReadLine() 

и так далее. См. documentation для более подробной информации.

В любом случае, если вы пытаетесь прочитать данные о клиентах из разделенных запятыми файла, например, как это:

C: \ test.text --- содержит:

Sam, Bond, [email protected], 9541032163 
Merry, Jackson, [email protected], 8872101103 
Rachel, Smith, [email protected], 4839078565 

Тогда вы должны сделать что-то вроде этого, чтобы прочитать значение - обратите внимание, что мы должны передать аргументы AddCustomer в том, что функция объявлена ​​(то есть: четыре строки):

If System.IO.File.Exists(FILE_NAME) Then 
    'Using creates an instance and disposes it for you when you leave the block 
    Using Rdr As New Microsoft.VisualBasic.FileIO.TextFieldParser(FILE_NAME) 
     'Indicates the values are delimited (separated by a special character) 
     Rdr.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited 
     'Defines the array of special characters that separate fields 
     Rdr.Delimiters = New String() {","} 
     'Declare a string array to hold the data from each line 
     Dim currentRow As String() 
     'Read lines until you reach the end of the file 
     While (Not Rdr.EndOfData) 
      'For each line, read and parse the data 
      currentRow = Rdr.ReadFields() 
      'Data are stored with zero-based index 
      Dim firstName As String = currentRow(0) 
      Dim lastName As String = currentRow(1) 
      Dim emailAdd As String = currentRow(2) 
      Dim phNum As String = currentRow(3) 
      AddCustomer(firstName, lastName, emailAdd, phNum) 
     End While 
    End Using 
Else 
    MessageBox.Show("File does not exist.") 
End If 

Анализатор текстового поля считывает строковый массив и автоматически разделяет значения на столбцы массивов. Если данные TAB разделены, то вы бы просто изменить разделитель, как в

Rdr.Delimiters = New String() {"vbTab"} 

Это параметр массива, так что вы можете даже сделать смесь пробелов, табуляции, запятые и т.д. Просто добавьте их к список как Rdr.Delimiters = New String() {"vbTab", " ", ","}.

Использование синтаксического анализа текстового поля является приятным, потому что оно может считывать значения в виде табуляции или запятой, генерируемые чем-то вроде Excel. Следите за тем, чтобы в приведенном выше коде не было обработок исключений. Это, вероятно, целесообразно обернуть некоторые из этих разделов в Try/за исключением блоков в том случае, если файл не правильно отформатированные, не может быть прочитан и т.д.

см: TextFieldParser (MSDN) для получения дополнительной информации

EDIT

Я вижу, что я пропустил вторую часть этого вопроса. Во-первых, я хотел бы предложить использовать дженерики для списка клиентов

Dim myCustomers As New List(Of Customer) 

Это намного лучше по многим причинам (читать на дженериков/коллекции для получения дополнительной информации). Первостепенное значение они придают вам безопасность типов. Также вы получаете много других положительных героев с точки зрения поиска и сортировки и т. Д.

Как для цикла:

Do 
    'total2 = myCustomers.Count.ToString() 
    'txtTotal.Text = total2 
    txtTotal.Text = myCustomers.Count.ToString() 
    System.Threading.Thread.Sleep(5000) 
Loop 

Это никогда не прекращается (нет условия на Do части, так что это будет просто держать зацикливания!). Обычно Do петли сделаны как

Do while x < 10 
    x = x + 1 
    DoSomething() 
Loop 

В вашем случае это никогда не закончится. Звонок на Sleep также совершенно не нужен. Вы никогда не должны никогда спать в потоке пользовательского интерфейса! Все, что вам нужно сделать, это:

txtTotal.Text = myCustomers.Count.ToString() 

Вот оно - нет Do/Loop, не спать. Работа выполнена.

Смотрите также: Do..Loop (MSDN)

+0

Хмм, мне придется поиграть с этим, спасибо. Мой вопрос: Какова цель «Пока (Not Rdr.EndOfData)»? - ответил. – Jim

+0

@Jim - Rdr - это объект, выполняющий чтение файла. Когда вы создаете его, у него есть указатель на файл в начале файла (это его текущее местоположение в файле). Когда вы вызываете 'Rdr.ReadFields()', он считывает одну строку файла и продвигает указатель на эту позицию. После того, как вы проанализировали данные из этой строки, он вернется в начало цикла «While» и проверяет, достиг ли указатель файла к концу файла. Если нет, он продолжается и читает следующую строку, повторяя операции и т. Д., Пока вы не достигнете конца файла ('EndOfData'). –

+0

Ага, я понимаю. О "Do txtTotal.Text = myCustomers.Count.ToString() System.Threading.Thread.Sleep (5000) Loop" Есть ли у вас какие-либо идеи, почему это не работает? Также спасибо за ссылки. – Jim

Смежные вопросы