Skip to content

How-to guide

Read and write files

Access the file nodes of a server: read and append content, open files as a stream, check permissions, and handle errors.

This content was machine translated and may contain errors. Read in German

How-to guide

Read and write files ​

Types usedOpcClientOpcNodeIdOpcFileOpcFileModeOpcFileStreamOpcFileInfoOpcFileMethodsSafeOpcFileHandle

According to the OPC UA specification, nodes of the FileType type have defined properties (property nodes) and methods (method nodes). Through them, the client accesses a data stream the same way as a file in the file system. The node only provides information about the content of the logical or physical file. According to the specification, it does not provide a path to the file, even if one exists. The client accesses the file itself through the methods Open, Close, Read, Write, GetPosition, and SetPosition. These methods always process the data as binary. As on any other platform, in OPC UA you pass a mode when you call Open. The mode defines the kind of file access you intend. You can also request exclusive access to a file in OPC UA. After calling Open, the client receives a numeric key for further file access, the file handle. You always pass this handle to the methods Read, Write, GetPosition, and SetPosition. Close an open file with Close as soon as you no longer need it.

You can access nodes of the FileType type manually with the ReadNode and CallMethod methods of the OpcClient class. Alternatively, the OPC UA .NET SDK offers numerous other classes that implement access to such nodes, some of them modeled on .NET. The NodeId defines which file node the client accesses.

Choose the right class ​

Class.NET counterpartSuitable for
OpcFileSystem.IO.Filereading or appending entire content in one call (ReadAllText, ReadAllLines, ReadAllBytes, AppendAllText, AppendAllLines) and opening streams (Open, OpenRead, OpenWrite, OpenText, AppendText)
OpcFileInfo (namespace Opc.UaFx.Client)System.IO.FileInfoquerying the properties of a file (Exists, Length, Name, MimeType, CanWrite, CanUserWrite) and opening the file
OpcFileStreamSystem.IO.FileStreamreading, writing, and positioning through the Stream interface, also together with StreamReader, StreamWriter, or CopyTo
OpcFileMethodsnonecalling the methods of the file node (Open, Read, Write, GetPosition, SetPosition, Close) one by one

OpcFileMode defines the mode for opening: Read, Write, ReadWrite, EraseExisting, and Truncate (write after emptying the file). OpcFile offers no methods that overwrite an entire file in one call (like File.WriteAllText). To write, use a stream opened with OpenWrite or Open.

Read and write entire files ​

Read the entire content of a text file:

csharp
string reportText = OpcFile.ReadAllText(client, "ns=2;s=Machine/Report");
vbnet
Dim reportText As String = OpcFile.ReadAllText(client, "ns=2;s=Machine/Report")

Append more text to a text file:

csharp
OpcFile.AppendAllText(client, "ns=2;s=Machine/Report", "Lorem ipsum");
vbnet
OpcFile.AppendAllText(client, "ns=2;s=Machine/Report", "Lorem ipsum")

Open and read a file with OpcFileStream:

csharp
using (var stream = OpcFile.OpenRead(client, "ns=2;s=Machine/Report")) {
    var reader = new StreamReader(stream);
 
    while (!reader.EndOfStream)
        Console.WriteLine(reader.ReadLine());
}
vbnet
Using stream = OpcFile.OpenRead(client, "ns=2;s=Machine/Report")
    Dim reader = New StreamReader(stream)

    While Not reader.EndOfStream
        Console.WriteLine(reader.ReadLine())
    End While
End Using

Open and write a file with OpcFileStream:

csharp
using (var stream = OpcFile.OpenWrite(client, "ns=2;s=Machine/Report")) {
    var writer = new StreamWriter(stream);
 
    writer.WriteLine("Lorem ipsum");
    writer.WriteLine("dolor sit");
    // ...
}
vbnet
Using stream = OpcFile.OpenWrite(client, "ns=2;s=Machine/Report")
    Dim writer = New StreamWriter(stream)

    writer.WriteLine("Lorem ipsum")
    writer.WriteLine("dolor sit")
    '...
End Using

Read the entire content as lines or as bytes:

csharp
string[] lines = OpcFile.ReadAllLines(client, "ns=2;s=Machine/Recipe");
byte[] content = OpcFile.ReadAllBytes(client, "ns=2;s=Machine/Snapshot");
vbnet
Dim lines As String() = OpcFile.ReadAllLines(client, "ns=2;s=Machine/Recipe")
Dim content As Byte() = OpcFile.ReadAllBytes(client, "ns=2;s=Machine/Snapshot")

Get file information and open files ​

The OpcFileInfo class of the Opc.UaFx.Client namespace describes a single file. The Opc.UaFx namespace also contains a class named OpcFileInfo. For this reason, the following examples use the fully qualified type name:

Create an instance of OpcFileInfo:

csharp
// The type name is qualified, because the Opc.UaFx namespace declares an OpcFileInfo too.
var file = new Opc.UaFx.Client.OpcFileInfo(client, "ns=2;s=Machine/Report");
vbnet
'The type name is qualified, because the Opc.UaFx namespace declares an OpcFileInfo too.
Dim file = New Opc.UaFx.Client.OpcFileInfo(client, "ns=2;s=Machine/Report")

Work with the instance of OpcFileInfo:

csharp
if (file.Exists) {
    Console.WriteLine("File Length: {0}", file.Length);
 
    if (file.CanUserWrite) {
        using (var stream = file.OpenWrite()) {
            // Your code to write via stream.
        }
    }
    else {
        using (var stream = file.OpenRead()) {
            // Your code to read via stream.
        }
    }
}
vbnet
If file.Exists Then
    Console.WriteLine("File Length: {0}", file.Length)

    If file.CanUserWrite Then
        Using stream = file.OpenWrite()
            'Your code to write via stream.
        End Using
    Else
        Using stream = file.OpenRead()
            'Your code to read via stream.
        End Using
    End If
End If

Query properties and write only if the user is allowed to: CanWrite indicates whether the file is writable at all. CanUserWrite indicates whether the logged-on user is allowed to write it. An OpcFileStream opened for writing takes both into account. Its CanWrite property is true only if both apply:

csharp
var file = new Opc.UaFx.Client.OpcFileInfo(client, "ns=2;s=Machine/Recipe");
 
Console.WriteLine(
        "{0}: {1} bytes, {2}",
        file.Name,
        file.Length,
        file.MimeType);
 
if (file.Exists && file.CanUserWrite) {
    using (var stream = file.OpenWrite())
    using (var writer = new StreamWriter(stream)) {
        writer.Write("Speed=1200");
    }
}
vbnet
Dim file = New Opc.UaFx.Client.OpcFileInfo(client, "ns=2;s=Machine/Recipe")

Console.WriteLine( _
        "{0}: {1} bytes, {2}", _
        file.Name, _
        file.Length, _
        file.MimeType)

If file.Exists AndAlso file.CanUserWrite Then
    Using stream = file.OpenWrite()
        Using writer = New StreamWriter(stream)
            writer.Write("Speed=1200")
        End Using
    End Using
End If

Process large files as a stream ​

Copy large files: Because OpcFileStream derives from Stream, you copy a file of the server to a local file with CopyTo. The stream reads the content in chunks:

csharp
using (var source = OpcFile.OpenRead(client, "ns=2;s=Machine/Snapshot"))
using (var target = File.Create("snapshot.bin")) {
    source.CopyTo(target);
}
vbnet
Using source = OpcFile.OpenRead(client, "ns=2;s=Machine/Snapshot")
    Using target = IO.File.Create("snapshot.bin")
        source.CopyTo(target)
    End Using
End Using

Write at a specific position: With Seek, you set the position within the file, for example to the end to append an entry:

csharp
using (var stream = OpcFile.Open(client, "ns=2;s=Machine/Log", OpcFileMode.ReadWrite)) {
    stream.Seek(0, SeekOrigin.End);
 
    byte[] entry = Encoding.UTF8.GetBytes("Job started" + Environment.NewLine);
    stream.Write(entry, 0, entry.Length);
}
vbnet
Using stream = OpcFile.Open(client, "ns=2;s=Machine/Log", OpcFileMode.ReadWrite)
    stream.Seek(0, SeekOrigin.End)

    Dim entry As Byte() = Encoding.UTF8.GetBytes("Job started" & Environment.NewLine)
    stream.Write(entry, 0, entry.Length)
End Using

Call file methods directly ​

Through the .NET concept SafeHandle (class SafeOpcFileHandle):

csharp
using (var handle = OpcFileMethods.SecureOpen(client, "ns=2;s=Machine/Report", OpcFileMode.ReadWrite)) {
    byte[] data = OpcFileMethods.SecureRead(handle, 100);
 
    long position = OpcFileMethods.SecureGetPosition(handle);
    OpcFileMethods.SecureSetPosition(handle, position + data[data.Length - 1]);
 
    OpcFileMethods.SecureWrite(handle, new byte[] { 1, 2, 3 });
}
vbnet
Using handle = OpcFileMethods.SecureOpen(client, "ns=2;s=Machine/Report", OpcFileMode.ReadWrite)
    Dim data As Byte() = OpcFileMethods.SecureRead(handle, 100)

    Dim position As Long = OpcFileMethods.SecureGetPosition(handle)
    OpcFileMethods.SecureSetPosition(handle, position + data(data.Length - 1))

    OpcFileMethods.SecureWrite(handle, New Byte() {1, 2, 3})
End Using

Through a numeric file handle:

csharp
uint handle = OpcFileMethods.Open(client, "ns=2;s=Machine/Report", OpcFileMode.ReadWrite);
 
try {
    byte[] data = OpcFileMethods.Read(client, "ns=2;s=Machine/Report", handle, 100);
 
    ulong position = OpcFileMethods.GetPosition(client, "ns=2;s=Machine/Report", handle);
    OpcFileMethods.SetPosition(client, "ns=2;s=Machine/Report", handle, position + data[data.Length - 1]);
 
    OpcFileMethods.Write(client, "ns=2;s=Machine/Report", handle, new byte[] { 1, 2, 3 });
}
finally {
    OpcFileMethods.Close(client, "ns=2;s=Machine/Report", handle);
}
vbnet
Dim handle As UInteger = OpcFileMethods.Open(client, "ns=2;s=Machine/Report", OpcFileMode.ReadWrite)

Try
    Dim data As Byte() = OpcFileMethods.Read(client, "ns=2;s=Machine/Report", handle, 100)

    Dim position As ULong = OpcFileMethods.GetPosition(client, "ns=2;s=Machine/Report", handle)
    OpcFileMethods.SetPosition(client, "ns=2;s=Machine/Report", handle, position + data(data.Length - 1))

    OpcFileMethods.Write(client, "ns=2;s=Machine/Report", handle, New Byte() {1, 2, 3})
Finally
    OpcFileMethods.Close(client, "ns=2;s=Machine/Report", handle)
End Try

Only file access through OpcFile, OpcFileInfo, OpcFileStream, and SafeOpcFileHandle guarantees that an open file is released even if the Close method is never called. In that case, the OpcClient closes all open files automatically, at the latest when the connection to the server closes. This does not apply if you use the methods of the OpcFileMethods class without the Secure prefix.

The OPC UA specification defines no way to recognize a node as a node of the FileType type and thus as a file node. For this reason, the SDK can identify a file node by its node structure:

csharp
if (OpcFileMethods.IsFileNode(client, "ns=2;s=Machine/Report")) {
    // Your code to operate on the file node.
}
vbnet
If OpcFileMethods.IsFileNode(client, "ns=2;s=Machine/Report") Then
    'Your code to operate on the file node.
End If

Handle errors ​

If the specified node does not exist or is not a file node, the methods of OpcFile, OpcFileInfo, and OpcFileMethods throw an InvalidOperationException. If the server rejects a method call, the method throws an OpcException with the status of the server. This is the case, for example, if the user is not allowed to write the file or the file is already open for exclusive access. For operations that the mode of the stream does not allow (for example, writing to a stream opened for reading), OpcFileStream throws a NotSupportedException:

csharp
try {
    string recipe = OpcFile.ReadAllText(client, "ns=2;s=Machine/Recipe");
}
catch (InvalidOperationException) {
    // The node does not exist or is not a file node.
}
catch (OpcException ex) {
    // The server rejected a file method, e.g. with BadUserAccessDenied.
    Console.WriteLine("{0}: {1}", ex.Code, ex.Message);
}
vbnet
Try
    Dim recipe As String = OpcFile.ReadAllText(client, "ns=2;s=Machine/Recipe")
Catch ex As InvalidOperationException
    'The node does not exist or is not a file node.
Catch ex As OpcException
    'The server rejected a file method, e.g. with BadUserAccessDenied.
    Console.WriteLine("{0}: {1}", ex.Code, ex.Message)
End Try

Security ​

Treat content you read from a server like external input. For example, do not use file names or paths from a file you read for access to the local file system without checking them. Limit the size (Length property) before you read a file into memory completely. Check the CanUserWrite property before you write.

Scope ​

  • The OpcNodeStream class reads large binary values that a server provides not as a file but as the value of a variable (see Large binary values as a stream).
  • The page Node types in the server chapter describes how a server provides file nodes itself.