Home > Articles > Programming > Windows Programming

This chapter is from the book

Reading and Writing to Files and Streams

As programmers, we often have to write directly to a file or data stream. If you've communicated with disparate systems, you are undoubtedly familiar with writing out CSV or XML files as a means of exchanging data. The .NET Framework gives us a group of classes and methods inside the System.IO namespace that allows us to access data streams and files both synchronously and asynchronously.

This section will define the AppendText, CreateText, Open, OpenRead, and OpenWrite methods of the FileInfo class.

File and data streams are essentially the same thing. They both are a type of stream. Their differences lie in their backing store. Backing store refers to a storage medium, such as a disk, tape, memory, network, and so on. Every backing store implements its own stream type as a version of the Stream class. This allows each stream type to read and write bytes to and from its own backing store. These streams that connect directly to backing stores are called base streams in .NET. An example of a base stream is the FileStream class. This class gives us access to files stored on disk inside of directories.

Reading and Writing Files

To read data to and from files using the System.IO namespace, we primarily use two classes: FileInfo and FileStream. The FileInfo class exposes a number of methods that allow us access to stream-related functions based on a file. These methods simply use the FileStream and related classes to expose this functionality. However, they are useful as you often already have an instance of FileInfo that is specific to a given file. You can then call these methods to return and write to the contents of this file. Table 7.11 lists these methods and their associated return types.

TABLE 7.11 FileInfo Streaming Methods

Member

Description

AppendText

The AppendText method creates an instance of the StreamWriter class that allows us to append text to a file. The StreamWriter class implements a TextWriter instance to output the characters in a specific encoding.

CreateText

The CreateText method creates an instance of the StreamWriter class that creates a new text file to which to write.

Open

The Open method opens a file and returns it to us as a FileStream object. The method has three constructors that allow us to specify the open mode (open, create, append, and so on), the file access (read, write, read and write), and how we want the file to be shared by other FileStream objects.

OpenText

The OpenText method creates a StreamReader object based on the associated text file.

OpenRead

The OpenRead method creates a FileStream object that is read only.

OpenWrite

The OpenWrite method creates a FileStream object that is both read and write.


You can see that the FileInfo class makes extensive use of the FileStream, StreamWriter, and StreamReader classes. These classes expose the necessary functionality to read and write to files in .NET. As you might have guessed, these objects are designed to work with persisted text files. They are based on the TextWriter and TextReader classes.

The FileStream class can be created explicitly. You've already seen that FileInfo uses this class to expose reading and writing to files. Table 7.12 lists the version of the FileStream constructors that can be used to create a FileStream object.

TABLE 7.12 FileStream Constructors

New FileStream (ByVal handle as IntPtr, ByVal access as FileAccess)

handle: A valid handle to a file.

access: A member of the FileAccess enumeration (Read, ReadWrite, Write).

Note: Use this constructor when you have a valid file pointer and need to specify the read/write permissions.

New FileStream (ByVal path as String, ByVal mode as FileMode)

path: A valid path to the file that the FileStream object will represent.

mode: A member of the FileMode enumeration (Append, Create, CreateNew, Open, OpenOrCreate, Truncate) that specifies how the file should be opened.

Note: Use this constructor when you know the file's path and wish to specify how the file is opened.

New FileStream (ByVal handle as IntPtr, ByVal access as FileAccess, _ByVal ownsHandle as Boolean)

handle: A valid handle to a file.

access: A member of the FileAccess enumeration (Read, ReadWrite, Write).

ownsHandle: Indicates if the file's handle will be owned by the given instance of the

FileStreamObject.

Note: Use this constructor when you have a valid file pointer, need to specify the read/write permissions, and wish to own (or pass off) the file's handle. If the FileStream object owns the file's handle, a call to the Close method will also close the file's handle and thus decrement its handle count by one.

New FileStream (ByVal path as String, ByVal mode as FileMode, _ByVal access as FileAccess)

path: A valid path to the file that the FileStream object will represent.

mode: A member of the FileMode enumeration (Append, Create, CreateNew, Open,

OpenOrCreate, Truncate) that specifies how the file should be opened.

access: A member of the FileAccess enumeration (Read, ReadWrite, Write).

Note: Use this constructor when you know the file's path, wish to specify how the file is opened, and need to specify the read/write permissions on the file.

New FileStream (ByVal handle as IntPtr, ByVal access as FileAccess, _ByVal ownsHandle as Boolean, ByVal bufferSize as Integer)

handle: A valid handle to a file.

access: A member of the FileAccess enumeration (Read, ReadWrite, Write).

ownsHandle: Indicates if the file's handle will be owned by the given instance of the

FileStreamObject.

bufferSize: Indicates the size of the buffer in bytes.

Note: Use this constructor when you have a valid file pointer, need to specify the read/write permissions, with to own the file's handle, and need to set the stream's buffer size.

New FileStream (ByVal path as String, ByVal mode as FileMode, _ByVal access as FileAccess, ByVal share as FileShare)

path: A valid path to the file that the FileStream object will represent.

mode: A member of the FileMode enumeration (Append, Create, CreateNew, Open,

OpenOrCreate, Truncate) that specifies how the file should be opened.

access: A member of the FileAccess enumeration (Read, ReadWrite, Write).

share: A member of the FileShare enumeration that indicates how the file will be shared.

FileShare controls how other FileStream objects can access the same file. Values include:

Inheritable, None, Read, ReadWrite, and Write.

Note: Use this constructor when you know the file's path, wish to specify how the file is opened, and need to specify the read/write permissions on the file.

New FileStream (ByVal handle as IntPtr, ByVal access as FileAccess, _ByVal ownsHandle as Boolean, ByVal bufferSize as Integer, _ByVal isAsync as Boolean)

handle: A valid handle to a file.

access: A member of the FileAccess enumeration (Read, ReadWrite, Write).

ownsHandle: Indicates if the file's handle will be owned by the given instance of the

FileStreamObject.

bufferSize: Indicates the size of the buffer in bytes. isAsync: Indicates if the file should be opened asynchronously.

Note: Use this constructor when you have a valid file pointer, need to specify the read/write permissions, wish to own (or pass off) the file's handle, need to set the buffer size, and wish to indicate the file should be opened asynchronously.

New FileStream (ByVal path as String, ByVal mode as FileMode, _ByVal access as FileAccess, ByVal share as FileShare, _ByVal bufferSize as Integer)

path: A valid path to the file that the FileStream object will represent.

mode: A member of the FileMode enumeration (Append, Create, CreateNew, Open,

OpenOrCreate, Truncate) that specifies how the file should be opened.

access: A member of the FileAccess enumeration (Read, ReadWrite, Write).

share: A member of the FileShare enumeration that indicates how the file will be shared. FileShare controls how other FileStream objects can access the same file. Values include:

Inheritable, None, Read, ReadWrite, and Write.

bufferSize: Indicates the size of the buffer in bytes.

Note: Use this constructor when you know the file's path, wish to specify how the file is opened, need to specify the read/write permissions on the file, and need to set the stream's buffer size.

New FileStream (ByVal path as String, ByVal mode as FileMode, _ByVal access as FileAccess, ByVal share as FileShare, _ByVal bufferSize as Integer, ByVal useAsynch as Boolean)

path: A valid path to the file that the FileStream object will represent.

mode: A member of the FileMode enumeration (Append, Create, CreateNew, Open,

OpenOrCreate, Truncate) that specifies how the file should be opened.

access: A member of the FileAccess enumeration (Read, ReadWrite, Write).

share: A member of the FileShare enumeration that indicates how the file will be shared.

FileShare controls how other FileStream objects can access the same file. Values include:

Inheritable, None, Read, ReadWrite, and Write.

bufferSize: Indicates the size of the buffer in bytes. useAsync: Indicates if the file should be opened asynchronously.

Note: Use this constructor when you know the file's path, wish to specify how the file is opened, need to specify the read/write permissions on the file, need to set the stream's buffer size, and need to indicate if the file is being opened for asynchronous read/write.


Listing 7.5 provides an example of the FileStream, StreamWriter, and StreamReader classes. This example is a simple, console-based application. It creates a new FileStream object based on a physical file. It then creates a StreamWriter instance based on the FileStream class. It calls the WritLine method of StreamWriter to output a line of text to the file. After it closes the StreamWriter instance, it creates a StreamReader instance based on a FileStream object. Finally, it loops through the lines in the file and outputs them to the console for your viewing.

LISTING 7.5 FileStream, StreamWriter, and StreamReader

Imports System.IO 

Module Module1 

   Sub Main() 

     'purpose: open a file and append infromation to its end 

     'local scope 
     Dim fileStream As FileStream 
     Dim streamWriter As StreamWriter 
     Dim streamReader As StreamReader 

     'create a new instance of the file stream object 
     'note:  if the file does not exist, the constructor create it 
     fileStream = New     fileStream(path:="c:\test.txt", _ 
        mode:=FileMode.OpenOrCreate, access:=FileAccess.Write) 

     'create an instance of a character writer 
     streamWriter = New StreamWriter(stream:=fileStream) 

     'set the file pointer to the end of the file 
     streamWriter.BaseStream.Seek(offset:=0, origin:=SeekOrigin.End) 

     'write a line of text to the end of the file 
     streamWriter.WriteLine(value:="This is a test") 
 
     'apply the update to the file 
     streamWriter.Flush() 

     'close the stream writer 
     streamWriter.Close() 

     'close the file stream object 
     fileStream.Close() 

     'create a new instance of file stream to read the file back 
     fileStream = New fileStream(path:="c:\test.txt", _ 
        mode:=FileMode.OpenOrCreate, access:=FileAccess.Read) 

     'create a stream reader instance 
     streamReader = New StreamReader(stream:=fileStream) 

     'set the file pointer to the start of the file
     streamReader.BaseStream.Seek(offset:=0, _ 
        origin:=SeekOrigin.Begin) 

     'loop through the file and write to console until the 
     ' end of file reached 
     Do While streamReader.Peek > -1 
          Console.WriteLine(value:=streamReader.ReadLine()) 
      Loop 

      'close the stream reader 
      streamReader.Close() 

      'wait for the user to stop the console application 
      Console.WriteLine("Press 's' to stop the application.") 

      'loop until users presses s key 
      Do While Console.ReadLine <> "s" : Loop 
   End Sub 
End Module 

Asynchronous Reading and Writing

As stated earlier, streaming with the .NET Framework classes can be done both synchronously and asynchronously. Synchronous reading and writing blocks methods from continuing until the operation is complete. For instance, suppose your application takes orders in the form of text files written to a queue. When a file is placed in the queue (or directory), your application reads the contents of the file and processes the order(s) accordingly. Each file can represent one order, or can contain a batch of orders. If your application is set up to handle each order from start to finish as it comes in (synchronously), then a long order will block your application from continuing to process orders while simply reading the file.

For a more efficient use of your resources, you will want to read orders asynchronously. That is, as an order comes in, you will tell a version of the Stream object to start reading the file and to let you know when it is done. This way, once you fire the BeginRead method, you can continue executing other program logic including responding to and processing additional orders.

With asynchronous file I/O, the main thread of your application continues to execute code while the I/O process finishes. In fact, multiple asynchronous IO requests can process simultaneously. Generally, an asynchronous design offers your application better performance. The tradeoff to this performance is that a greater coding effort is required.

The FileStream class provides us the BeginRead method for asynchronous file input and the BeginWrite method for asynchronous file output. As a parameter to each, we pass the name of the method we wish to have called when the operation is complete (userCallback as AsynchCallback). In VB .NET, the syntax looks like this:

New AsyncCallback(AddressOf myCallbackMethod) 

Where myCallbackMethod is the name of the method you wish to have intercept and process the completed operation notification. From within this callback method, you should call EndRead or EndWrite as the case dictates. These methods end their respective operations. EndRead returns the number of bytes that were read during the operation. Both methods take a reference to the pending asynchronous I/O operation (AsynchResult as IAsynchResult). This object comes to us as a parameter to our custom callback method. The code in Listing 7.6 further illustrates these concepts.

The application's Sub Main simply controls the calls to the read operation. You can see in Listing 7.6 that we execute three separate read requests on three different files. The remaining bits of functionality are nicely encapsulated and thus, should be easy to reuse.

LISTING 7.6 Asynchronous File Reading

Imports System.IO 

Module Module1 

   Sub Main() 
     'purpose: provide example code of asynch. file I/O 
     'steps:    1. start asynch. read and processing of 3 files of 
     '           varying lengths 
     '          2. wait for callback and display to screen 

     'local scope 
     Dim myFiles(3) As String 
     Dim i As Int16 

     myFiles(0) = "c:\file1.txt" 
     myFiles(1) = "c:\file2.txt" 
     myFiles(2) = "c:\file3.txt" 

     'call each asynch. read 
     For i = 0 To 2 
        Console.WriteLine("Starting file read: " & myFiles(i)) 
        Call asynchRead(filePath:=myFiles(i)) 
     Next 

     'NOTE: now that file reads have started, our application can 
     '       continue processing other information and await a callback 
     '       from the read operation indicating read is complete 

     'wait for the user to stop the console application 
     Console.WriteLine("******** Enter 's' to stop the application.") 

     'loop until user presses s key 
     Do While Console.ReadLine <> "s" : Loop 

End Sub 

The procedure asynchRead sets up the asynchronous file input. The class StateObject is a simple state object that allows us to maintain file input information, in the form of properties, across read requests.

Notice that when calling BeginRead, in addition to indicating a callback method, we must specify both a byte array (array() as Byte) and the total number of bytes (numBytes as Integer) we wish to have read. To store the bytes, we dimension an array of type byte inside our state object. We pass byteArraySize in the object's constructor. We get its size by reading the file size from the FileInfo object's Length property. This allows us to create an array of the exact size we need. Similarly, when we set the number of bytes to read, we use FileInfo.Length again to indicate we want to read the entire file.

   Private Sub asynchRead(ByVal filePath As String) 

      'purpose: execute an asynch. read against a given file 
      '        throw an exception if the file is not found 

      'local scope 
      Dim fileStream As FileStream 
      Dim state As StateObject 
      Dim fileInfo As FileInfo 

      'check to see if the file exists 
      If Not File.Exists(path:=filePath) Then 

         'file does not exist = throw an exception 
         Throw New Exception(message:="File not found.") 

      End If 

      'file exists = create an open instance of the file 
      fileStream = New FileStream(path:=filePath, mode:=FileMode.Open) 

      'determine size of the file to set the number of bytes 
      fileInfo = New FileInfo(fileName:=filePath) 
      Console.WriteLine("File length: " & fileInfo.Length) 

       'create a state object 
       state = New StateObject(filePath:=filePath, _ 
          byteArraySize:=fileInfo.Length) 

       'set fileStream prop (useful for callback) 
       state.FileStream = fileStream 

       'begin the file read 
       fileStream.BeginRead(array:=state.ByteArray, offset:=0, _ 
         numBytes:=fileInfo.Length, _ 
         userCallback:=New AsyncCallback(AddressOf fileRead), _ 
         stateObject:=state) 

   End Sub 

The fileRead method is the application's callback implementation. This method receives notification when a BeginRead has completed for a given file.

   Private Sub fileRead(ByVal asyncResult As IAsyncResult) 

     'purpose: provide a callback method for asynch reads 
 
     'local scope 
     Dim state As StateObject 
     Dim bytesRead As Integer 

     'set the state object = to the one returned by the asynch results 
     state = asyncResult.AsyncState 

     'write out the path of the object read 
     Console.WriteLine(state.FilePath) 

     'indicate that the file was read asynch. 
     If asyncResult.CompletedSynchronously Then 
        Console.WriteLine("File was read synchronously.") 
     Else 
        Console.WriteLine("File was read asynchronously.") 
     End If 

     'determine the number of bytes read by calling EndRead 
     bytesRead = state.FileStream.EndRead(asyncResult) 

     'write out bytes read 
     Console.WriteLine("Bytes read: " & bytesRead) 

     'close the file stream 
     state.FileStream.Close() 

   End Sub 

End Module 

Public Class StateObject 

   'purpose: maintain state information across asynch calls 

   'class-level scope 
   Private localFilePath As String 
   Private localByteArray() As Byte 

   'public properties 
   Public FileStream As FileStream 

   Public Property ByteArray() As Byte() 
     'purpose: get and set ByteArray property 

     Get 
        Return localByteArray 
     End Get 

     Set(ByVal Value() As Byte) 
        localByteArray = Value 
     End Set
 
     End Property
 
   Public Property FilePath() As String 

     'purpose: get and set FilePath prop. 

     Get 
        Return localFilePath 
     End Get 

     Set(ByVal Value As String) 
        localFilePath = Value 
     End Set 

   End Property 

   Sub New(ByVal filePath As String, ByVal byteArraySize As Integer) 

      'purpose:  constructor, allows setting of file path info. 
      '         and byte array size info. 

      'set local file path info 
      localFilePath = filePath 

      'dimension the size of the byte array 
      ReDim localByteArray(byteArraySize) 

  End Sub 
End Class 

Figure 7.2 represents the output of the code listing. Notice that in this case, each file was read in the same order the request was made. However, there is no guarantee of processing order due to the asynchronous nature of the request and additional factors like file size and processor availability. Also notice that after the first (and subsequent) read requests were made, our code did not stop executing. Rather, it made additional requests, and ultimately, waited on user input to stop the application. Finally, as each read completed, the notification was sent to our readFile method and the results of the operation were written to the console.

Figure 7.2 Output of asynchronous example.

Binary Reading and Writing

Thus far, we've dealt primarily with text files. While it is true that text files make up the majority of business programming I/O tasks, you will often need to read and write files of a proprietary type. To do so, you will access them at the binary level. Suppose that you need to accept an Excel file streaming across the wire, chances are you will want to persist it to disk using a binary reader and writer. Or suppose you want to read image files and store them in your database. Again, a binary reader will make this operation go smoothly.

We have a number of options open to us for file I/O at the binary level. The principal ones include using the BinaryReader, BinaryWriter, and FileStream classes. The best thing is that, for the most part, you already know how to use these objects. BinaryReader and BinaryWriter are similar to StreamReader and StreamWriter, respectively. Like these classes, BinaryReader and BinaryWriter take an instance of a valid Stream object as a parameter of their constructor. The Stream object represents the backing store that is being read from or written to.

The BinaryReader class provides a number of read methods that allow us to access primitive data types from our file streams. Each read method returns the given data from the stream and advances the current position in the stream ahead of the returned data. The reader you're likely to use most often is ReadByte. This returns one byte of data from the stream and advances the current stream position to the next byte. When the end of the stream is reached, the exception, EndOfStreamException, is thrown by the method. Other read methods include ReadBytes, ReadString, ReadDecimal, and ReadBoolean to name a few.

Similarly, BinaryWriter provides a number of write methods for writing primitive data to a stream. Unlike BinaryReader, BinaryWriter exposes only one method, WriteByte, for executing binary writes. However, this method has a number of overloads that allow us to specify whether we are writing byte data or string, decimal, and so on. Calls to WriteByte write out the given data to the stream and advance its current position by the length of the data. Again, WriteByte(value as Byte) will be the most commonly used method.

The FileStream class also exposes the basic binary methods, ReadByte and WriteByte. ReadByte and WriteByte behave in the exact same manner as BinaryReader.ReadByte and BinaryWriter.WriteByte(value as Byte). It is often easier to simply use FileStream for all your basic needs; this is why it exists. Should you need additional functionality, then you will want to implement one or more of the binary classes.

Listing 7.7 provides an example of the BinaryReader and BinaryWriter classes. In the example, we use BinaryReader to read the contents of a bitmap file, one byte at a time. At the same time, we write each byte out to another file using BinaryWriter. The result is two identical files. Notice that to create both the reader and the writer we must first create a valid FileStream (or similar Stream derivation) for the instances to use as their backing.

LISTING 7.7 Binary Reading and Writing

Imports System.IO 

Module Module1 

   Sub Main() 

     'purpose: read a binary file and write contents to diff. file 

     'local scope 
     Dim fsRead As FileStream 
     Dim fsWrite As FileStream 
     Dim bRead As BinaryReader 
     Dim b As Byte 
     Dim bWrite As BinaryWriter 

     'check if read file exists 
     If Not File.Exists(path:="c:\test.bmp") Then 

        Console.WriteLine("File, test.bmp, not found") 

        'waite for user input 
        Console.WriteLine("Enter 's' to stop the application.") 
        Do While Console.ReadLine <> "s" : Loop 

        End 

     End If 

     'create a fileStream instance to pass to BinaryReader object 
     fsRead = New FileStream(path:="c:\test.bmp", mode:=FileMode.Open) 

     'check if write file exists 
     If File.Exists(path:="c:\test2.bmp") Then 

        'delete file 
        File.Delete(path:="c:\test2.bmp") 

     End If 

      'create a fileStream instance to pass to BinaryWriter object 
      fsWrite = New FileStream(path:="c:\test2.bmp", _ 
          mode:=FileMode.CreateNew, access:=FileAccess.Write) 

      'create binary writer instance 
      bWrite = New BinaryWriter(output:=fsWrite) 

      'create instance of binary reader 
      bRead = New BinaryReader(Input:=fsRead) 

      'set the file pointer to the start of the file 
      bRead.BaseStream.Seek(offset:=0, _ 
          origin:=SeekOrigin.Begin) 

      'loop until can no longer read bytes from file 
      Do While True 

         Try 

            'read next byte and advance reader 
            b = bRead.ReadByte 

         Catch 
            Exit Do 
         End Try 

         'write byte out 
         bWrite.Write(value:=b) 

      Loop 
 
      'close the reader 
      bRead.Close() 

      'close the writer 
      bWrite.Close() 

      'close the file streams 
      fsRead.Close() 
      fsWrite.Close() 

      'wait for the user to stop the console application 
      Console.WriteLine("Operation complete.") 
      Console.WriteLine("Enter 's' to stop the application.") 

      'loop until user presses s key 
      Do While Console.ReadLine <> "s" : Loop 
   End Sub 
End Module 

Suggestions for Further Exploration

  • To create a stream whose backing is memory (and not disk), check out the MemoryStream class. This class is useful in that it can reduce your need for direct file I/O inside your application and provide you with a temporary buffer.

  • Depending on your application, you can sometimes garner additional performance by implementing the BufferedStream class. Note that FileStream has internal buffering of its own and is often sufficient. Programming with BufferedStream is similar to the other stream classes we've discussed.

  • To store data using isolated stores, check out the namespace System.IO.IsolatedStorage. Isolated stores are secure data compartments that are only accessible by the given user or code assembly. Data can also be isolated at the domain level and user data can travel with them using roaming profiles. For more information, check out the MSDN chapter at: Visual Studio .NET/.NET Framework/Programming with the .NET Framework/Working with I/O/Performing Isolated Storage Tasks.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020