Measurement Computing   Easy to Use | Easy to Integrate | Easy to Support catalog banner

Creating and appending data to a text file using the .NET...

Expand / Collapse
 

Creating and appending data to a text file using the .NET StreamWriter class


If you are using Visual Studio to acquire data with a Measurement Computing (MCC) data acquisition device supported by the Universal Library, you may want to save the data for further analysis.

Microsoft Visual Studio includes two methods for writing data to file; StreamWriter and BinaryWriter.

BinaryWriter writes primitive types in binary to a stream which cannot be easily read.  Alternatively, StreamWriter writes data as strings to a file, with the formatting you create or choose.

This  article will focus on StreamWriter.  In particular, creating a file if it doesn’t exist, or append to the file if it does, and using the Open File dialog box as a user option.

A little background

This application will not teach you everything you want or need to know about file writing, nor is that its intention.

We will be using Microsoft Visual Basic.NET 2010, MCC Universal Library, and a USB-1608G for data collection (though you can use any MCC device supported by the Universal Library).

We will start with an example program that is attached at the bottom of this article. I contains the basics for finding the MCC device, and allow the analog inputs to be configured for Single Ended or Differential.  A button, alternating clicks to enable or disable a timer event. The timer event is set to acquire data from 2 channels at 2 samples per second and displays the data on the screen. 

Run the default program and make sure it works for you.  It is designed to work with any USB-1608G series device.  If you don’t have one of those, it’s no problem, just change the search string in the Form1_Load event to what you have.  For example, the default syntax is:

If Daqboard.BoardName.Contains("1608G")Then

 Examples to change it to:

If Daqboard.BoardName.Contains("20")Then   ‘if you have a USB-200 series device

If Daqboard.BoardName.Contains("1208")Then ‘will find any USB-1208LS, ‘FS, ‘FS-PLUS, or USB-1208HS series

If Daqboard.BoardName.Contains("23")Then   ‘if you have a USB-230 series

 Or, you can enter the entire name such as USB-1616HS-2.  Keep in mind MCC device names are case sensitive.  

On for Form View, there is a button with the text “Differential.”  The function of this button is to allow you or your user to programmatically change the analog input configuration from Single Ended to Differential.  For information on analog input configuration, please see Measurement Computing Guide to DAQ Signal Connections (http://www.mccdaq.com/pdfs/DAQ-Signal-Connections.pdf).

Adding the ability to write to file:

The first step is to add an import for System.IO to the top of the Form.vb code view, above Public Class Form1 like this:

 Imports System.IO

 This adds the class library for StreamWriter.

We will need to create two global declarations.  Place the following 2 lines at the top, but just below Dim ulstat As MccDaq.ErrorInfo :

 

'File writing variables:

Dim swOutputFile As IO.StreamWriter

Dim sFilename As String

 

Let’s save the data in a sub-folder of the system’s “MyDocuments” folder.  And, let’s let the application create the file name based upon the current date and time.  The .NET library includes an easy way to retrieve the path to the user’s MyDocuments folder, and to create a new path.

This section of syntax will be inserted in the btnAinStartStop_Click event, below the 2 StripChart.Resets

'Create a file path and filename to user's "MyDocuments\Measurement Computing\MCC\"

Dim pathstring As String = My.Computer.FileSystem.SpecialDirectories.MyDocuments

pathstring = pathstring + "\MeasurementComputing\MCC\"

System.IO.Directory.CreateDirectory(pathstring)

 

'Create a file name based upon today's date and time right now.

Dim CurrentDateAndTime As Date = Now

sFilename = pathstring + CurrentDateAndTime.Year.ToString _

    + "_" + CurrentDateAndTime.Month.ToString _

    + "_" + CurrentDateAndTime.Day.ToString _

    + "_" + CurrentDateAndTime.Hour.ToString _

    + "_" + CurrentDateAndTime.Minute.ToString _

    + "_" + CurrentDateAndTime.Second.ToString + ".csv"

 

It also includes easy ways to read and parse the current date and time making it simple to create the file name as part of the pathstring.

About the .CSV file extension

What makes the .CSV important is that Microsoft Excel knows how to read a file with this extension.  A CSV file is a file where all the fields are separated by commas.  The extension ‘CSV’ is an abbreviation for Comma Separated Values, and Excel knows it can open this file.

If you want it to be a text file, then instead of using the extension .csv, use .txt.  The .txt extension makes it so the file can be opened by Notepad, WordPad, MS Word, or any text editor.  It can still be opened in Excel, assuming the internal file format does really have the values separated by commas, but it would need to be imported as opposed to just double clicking on it and Excel taking it from there.

We could add the syntax to open the file here since we have just created the folder and file name and the next step in the program is to enable the Timer.  Once the Timer is running, it makes sense to read in the data, then immediately write it to the file, and repeat each time the Timer Ticks, and stay that way until the Start/Stop button is again clicked.  But the problem is that the file is opened and left open.  If computer power is interrupted (power loss or glitch) or the PC crashes unexpectedly, all the data may be lost because the file was left open.   A better plan is to repeatedly open and close the file each time the Timer ticks and new data is acquired.  If there is a power loss or the PC crashes, the only data lost will be that of the last readings.  So let’s have a look at how to open – write -and close the file dynamically.

Here is our Timer’s click event:

Private Sub tmrAnalogIn_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrAnalogIn.Tick

        Dim VInVolts(1) As Double

        Dim AInRange AsMccDaq.Range = MccDaq.Range.Bip10Volts

 

        ulstat = Daqboard.VIn32(0, AInRange, VInVolts(0), MccDaq.VInOptions.Default)

        If ulstat.Value <> MccDaq.ErrorInfo.ErrorCode.NoErrorsThen

            errhandler(ulstat)

            Exit Sub

        End If

        lblChan0Value.Text = VInVolts(0).ToString("#0.000")

        StripChart1.AddValue(VInVolts(0))

 

        ulstat = Daqboard.VIn32(1, AInRange, VInVolts(1), MccDaq.VInOptions.Default)

        If ulstat.Value <> MccDaq.ErrorInfo.ErrorCode.NoErrorsThen

            errhandler(ulstat)

            Exit Sub

        End If

        lblChan1Value.Text = VInVolts(1).ToString("#0.000")

        StripChart2.AddValue(VInVolts(1))

 

 End Sub

 

We will need to create a string variable and set the string so that the data is comma delimited.  Formatted so that first, there is a date and time stamp so we know when the data was collected, a comma, a Channel 0 value, a comma, then a channel 1 value.  Open the file and write the string out to our .CSV file. And then finally, close the file. Here is the syntax

Dim DataSet As String = Now.Date + "" + Now.TimeOfDay.ToString + "," + VInVolts(0).ToString("#0.0000") + ", " + VInVolts(1).ToString("##0.0000")

Using swOutputFile As New StreamWriter(File.Open(sFilename, FileMode.Append))

    swOutputFile.WriteLine(DataSet)

    swOutputFile.Close()

End Using

 

Then, wait for the next Timer tick and repeat.

This syntax is inserted just above the ‘End Sub’ of the tmrAnalogIn_Tick event shown above.

That’s it. You now have the basics for writing your data to a file. A few notes:

A comma is not necessarily the only delimiter.  Some prefer to use a semi colon or tab instead of a comma.  In fact, you could use any character you want. It’s just that in the US, a comma is the standard.

Also, .CSV and .TXT are not the only file extensions you can use.  You can use any 3 letters and/or numbers as a file extension. It can be less or none at all as long as you know the extension and preferably it doesn’t clash with another known extension.  For example, you would not want to use .vb or .cs as these are file extensions of visual basic and C sharp (C#).

Here are a few lines from our the logged file, opened with Notepad:

Test Log file for USB-1608G series
Channels: 2
Update Rate: 2Hz
Start time:10/19/2016 10:08:24.6467838
Time, Channel 0, Channel 1
10/19/2016 10:08:25.1678359, 0.0128, 0.2026
10/19/2016 10:08:25.6788870, 0.0128, 0.0128
10/19/2016 10:08:26.1939385, 0.0137, 0.0131
10/19/2016 10:08:26.6929884, 0.0137, 0.0128
10/19/2016 10:08:27.2080399, 0.0137, 0.0128
10/19/2016 10:08:27.7130904, 0.0134, 0.0128
10/19/2016 10:08:28.2221413, 0.0140, 0.0131

 As you can see, our file header is present (see below for more), and all the data is separated by commas.  But it is a bit hard to read.  Here is the same file, opened by Excel:


Nice, but with a bit of column spacing and reformatting of the Column A's data, the time stamp, to:  m/d/yyyy h:mm:ss.0 AM/PM, our spreadsheet now looks like this:

We can now read the date and time clearly to the .1 second, and channels 0 and 1 are easy to read as well.

For more information on cell formatting, please see Knowledgebase article 50616

 

But Wait! There’s more…

Adding a File Header

Common practice in data log files is to insert a header.  A file header is nothing more than a few lines of text explaining some relevant information about the data collected.

Here is our completed btnStartStop_Click() event.

Private Sub btnStartStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) HandlesbtnStartStop.Click

    If sender.Text = "Start"Then

        sender.Text = "Stop"

        lblAIMode.Text = "Running"

        StripChart1.Reset()

        StripChart2.Reset()

 

        'Create a file path and filename to user's"MyDocuments\Measurement Computing\FileWrite\"

        Dim pathstring As String = My.Computer.FileSystem.SpecialDirectories.MyDocuments

        pathstring = pathstring + "\MeasurementComputing\FileWrite\"

        System.IO.Directory.CreateDirectory(pathstring)

 

        'Create a file name based upon today's date and time righ tnow.

        Dim CurrentDateAndTime As Date = Now

        sFilename = pathstring + CurrentDateAndTime.Year.ToString _

            +"_" + CurrentDateAndTime.Month.ToString _

            +"_" + CurrentDateAndTime.Day.ToString _

            +"_" + CurrentDateAndTime.Hour.ToString _

            +"_" + CurrentDateAndTime.Minute.ToString _

            +"_" + CurrentDateAndTime.Second.ToString + ".csv"

         tmrAnalogIn.Enabled = True

     Else

        sender.Text = "Start"

        lblAIMode.Text = "Idle"

        tmrAnalogIn.Enabled = False

    End If

End Sub

 Just above tmrAnalogIn.Enabled = True insert the following:

swOutputFile = New StreamWriter(sFilename)

swOutputFile.WriteLine("TestLog file for USB-1608G series")

swOutputFile.WriteLine("Channels: 2")

swOutputFile.WriteLine("UpdateRate: 2Hz")

swOutputFile.WriteLine("Start time:  " + Now.Date + " " + Now.TimeOfDay.ToString)

swOutputFile.WriteLine(" ")

swOutputFile.WriteLine("Time,Channel 0, Channel 1")

swOutputFile.Close()  'Close the file

The first line opens the file.  The difference between this method of opening the file:  swOutputFile = New StreamWriter(sFilename)

And the one we used previously in tmrAnalogIn_Tick event:  Using swOutputFile As New StreamWriter(File.Open(sFilename, FileMode.Append))

When the operator presses Start, we are assuming there is no existing file already with this name which is definitely true.  Since we are creating the name of the file based upon the current date and time, it is not possible for that file to already be created.  The method used earlier opens the file for appending if it is not already in created.

Adding a file dialog box.

If you do not want to create the file name dynamically via programming, you can let the user choose the name and location of the file.  You do this by using the OpenFileDialog object.

Double click or Drag it from the Visual Studio Toolbox, and onto the form or Component tray.  For our project, it is added to the Component tray, and placed next to the Timer object.

For our needs, there are two properties needing to be set from the Properties window:

Set CheckFileExists to False.

To set FileName property, just clear any text from the textbox making it blank.

To our App, we will add some appropriate syntax to:

  •       Define the types of file extensions,
  •       Set a default file extension so the operator just has to enter a name,
  •       Set an initial directory for the file, for our use it is c:\Users\MyDocuments\Measurement Computing\FileWrite\,
  •       Show the dialog box.  If OK is clicked and there is a file name entered, return the file name and use it.  If no file name is entered and OK is clicked, do nothing, wait until a file name is entered and OK is again clicked.  If Cancel is clicked, close the dialog box and return to the main form of the program, do not start logging.

Here is the entire btnStartStop_Click() routine including the file header:

Private Sub btnStartStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStartStop.Click

    If sender.Text = "Start" Then

        sender.Text = "Stop"

 

        StripChart1.Reset() 'reset/clear the stripcharts

        StripChart2.Reset()

 

        'Create a file path and filename to user's "MyDocuments\Measurement Computing\FileWrite\"

        Dim pathstring As String = My.Computer.FileSystem.SpecialDirectories.MyDocuments

        pathstring = pathstring + "\MeasurementComputing\FileWrite\"

        System.IO.Directory.CreateDirectory(pathstring)

 

        'Use the OpenFileDialog object:

        OpenFileDialog1.Filter = "CSV (*.csv)|*.csv|Text (*.txt)|*.txt|All Files (*.*)|*.*"

        OpenFileDialog1.DefaultExt = ("CSV(*.csv)|*.csv")

        OpenFileDialog1.InitialDirectory = pathstring

        If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then

             sFilename = OpenFileDialog1.FileName

         Else

            sender.Text = "Start"

            Exit Sub

        End If

 

        swOutputFile = New StreamWriter(sFilename)

        swOutputFile.WriteLine("Test Log file for USB-1608G series")

        swOutputFile.WriteLine("Channels: 2")

        swOutputFile.WriteLine("Update Rate: 2Hz")

        swOutputFile.WriteLine("Start time:  " + Now.Date + " " + Now.TimeOfDay.ToString)

        swOutputFile.WriteLine(" ")

        swOutputFile.WriteLine("Time, Channel 0, Channel 1")

        swOutputFile.Close()  'Close the file

 

        lblAIMode.Text = "Running"

        tmrAnalogIn.Enabled = True

    Else

        sender.Text = "Start"

        lblAIMode.Text = "Idle"

        tmrAnalogIn.Enabled = False

    End If

End Sub

 

AnalogIn_SW_Timed.zip is the basic example, prior to add additional code for file writing.  If you want to build this along with the article, start with this project.

AnalogIn_toFile_SW_Timed.zip includes the syntax for both automatic file naming and operator selected file naming. The operator selected method is commented out so that the automatic method is used.  To set it to operator method, comment out the automatic method, and un-comment the other.

For questions and comments regarding this knowledgebase article, please direct them to Measurement Computing’s Application Engineering:

http://www.mccdaq.com/support/emailus.aspx

Email:  info@mccdaq.com

Phone: 508-946-5100, select option 2.

Toll free:800-234-4232

Disclaimer:

The attached Examples are provided 'As Is.'  

They have not been tested or validated as a product, for use in a deployed application or system, or for use in hazardous environments.  

You assume all risks for use of these Examples or any part of the syntax contained herein.



Rate this Article:

Attachments


AnalogIn_SW_Timed.zip AnalogIn_SW_Timed.zip (47.28 KB, 486 views)

AnalogIn_toFile_SW_Timed.zip AnalogIn_toFile_SW_Timed.zip (49.54 KB, 433 views)

Add Your Comments


For comments email TechSupport@mccdaq.com.

Details
Article ID: 50622

Last Modified:10/19/2016 2:41:53 PM

Article has been viewed 7,855 times.

Options