You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Developers sometimes run into a set of common problems when using the **Write** methods of the [**FileIO**](/uwp/api/Windows.Storage.FileIO) and [**PathIO**](/uwp/api/windows.storage.pathio) classes to perform file system I/O operations. For example, common problems include:
16
+
Developers sometimes run into a set of common problems when using the Write methods of the [FileIO](/uwp/api/Windows.Storage.FileIO) and [PathIO](/uwp/api/windows.storage.pathio) classes to perform file system I/O operations. For example, common problems include:
17
17
18
18
* A file is partially written.
19
19
* The app receives an exception when calling one of the methods.
20
20
* The operations leave behind .TMP files with a file name similar to the target file name.
21
21
22
-
The **Write** methods of the [**FileIO**](/uwp/api/Windows.Storage.FileIO) and [**PathIO**](/uwp/api/windows.storage.pathio) classes include the following:
22
+
The Write methods of the [FileIO](/uwp/api/Windows.Storage.FileIO) and [PathIO](/uwp/api/windows.storage.pathio) classes include the following:
23
23
24
-
***WriteBufferAsync**
25
-
***WriteBytesAsync**
26
-
***WriteLinesAsync**
27
-
***WriteTextAsync**
24
+
* WriteBufferAsync
25
+
* WriteBytesAsync
26
+
* WriteLinesAsync
27
+
* WriteTextAsync
28
28
29
29
This article provides details about how these methods work so developers understand better when and how to use them. This article provides guidelines and does not attempt to provide a solution for all possible file I/O problems.
30
30
31
31
> [!NOTE]
32
-
> This article focuses on the **FileIO** methods in examples and discussions. However, the **PathIO** methods follow a similar pattern and most of the guidance in this article applies to those methods too.
32
+
> This article focuses on the FileIO methods in examples and discussions. However, the PathIO methods follow a similar pattern and most of the guidance in this article applies to those methods too.
33
33
34
34
## Convenience vs. control
35
35
36
-
A [**StorageFile**](/uwp/api/windows.storage.storagefile) object is not a file handle like the native Win32 programming model. Instead, a [**StorageFile**](/uwp/api/windows.storage.storagefile) is a representation of a file with methods to manipulate its contents.
36
+
A [StorageFile](/uwp/api/windows.storage.storagefile) object is not a file handle like the native Win32 programming model. Instead, a [StorageFile](/uwp/api/windows.storage.storagefile) is a representation of a file with methods to manipulate its contents.
37
37
38
-
Understanding this concept is useful when performing I/O with a **StorageFile**. For example, the [Writing to a file](create-read-write-files.md#writing-to-a-file) section presents three ways to write to a file:
38
+
Understanding this concept is useful when performing I/O with a StorageFile. For example, the [Writing to a file](create-read-write-files.md#writing-to-a-file) section presents three ways to write to a file:
39
39
40
-
* Using the [**FileIO.WriteTextAsync**](/uwp/api/windows.storage.fileio.writetextasync) method.
41
-
* By creating a buffer and then calling the [**FileIO.WriteBufferAsync**](/uwp/api/windows.storage.fileio.writebufferasync) method.
40
+
* Using the [FileIO.WriteTextAsync](/uwp/api/windows.storage.fileio.writetextasync) method.
41
+
* By creating a buffer and then calling the [FileIO.WriteBufferAsync](/uwp/api/windows.storage.fileio.writebufferasync) method.
42
42
* The four-step model using a stream:
43
43
1.[Open](/uwp/api/windows.storage.storagefile.openasync) the file to get a stream.
44
44
2.[Get](/uwp/api/windows.storage.streams.irandomaccessstream.getoutputstreamat) an output stream.
45
-
3. Create a [**DataWriter**](/uwp/api/windows.storage.streams.datawriter) object and call the corresponding **Write** method.
45
+
3. Create a [DataWriter](/uwp/api/windows.storage.streams.datawriter) object and call the corresponding Write method.
46
46
4.[Commit](/uwp/api/windows.storage.streams.datawriter.storeasync) the data in the data writer and [flush](/uwp/api/windows.storage.streams.ioutputstream.flushasync) the output stream.
47
47
48
48
The first two scenarios are the ones most commonly used by apps. Writing to the file in a single operation is easier to code and maintain, and it also removes the responsibility of the app from dealing with many of the complexities of file I/O. However, this convenience comes at a cost: the loss of control over the entire operation and the ability to catch errors at specific points.
49
49
50
50
## The transactional model
51
51
52
-
The **Write** methods of the [**FileIO**](/uwp/api/Windows.Storage.FileIO) and [**PathIO**](/uwp/api/windows.storage.pathio) classes wrap the steps on the third write model described above, with an added layer. This layer is encapsulated in a storage transaction.
52
+
The Write methods of the [FileIO](/uwp/api/Windows.Storage.FileIO) and [PathIO](/uwp/api/windows.storage.pathio) classes wrap the steps on the third write model described above, with an added layer. This layer is encapsulated in a storage transaction.
53
53
54
-
To protect the integrity of the original file in case something goes wrong while writing the data, the **Write** methods use a transactional model by opening the file using [**OpenTransactedWriteAsync**](/uwp/api/windows.storage.storagefile.opentransactedwriteasync). This process creates a [**StorageStreamTransaction**](/uwp/api/windows.storage.storagestreamtransaction) object. After this transaction object is created, the APIs write the data following a similar fashion to the [File Access](https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/FileAccess) sample or the code example in the [**StorageStreamTransaction**](/uwp/api/windows.storage.storagestreamtransaction) article.
54
+
To protect the integrity of the original file in case something goes wrong while writing the data, the Write methods use a transactional model by opening the file using [OpenTransactedWriteAsync](/uwp/api/windows.storage.storagefile.opentransactedwriteasync). This process creates a [StorageStreamTransaction](/uwp/api/windows.storage.storagestreamtransaction) object. After this transaction object is created, the APIs write the data following a similar fashion to the [File Access](https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/FileAccess) sample or the code example in the [StorageStreamTransaction](/uwp/api/windows.storage.storagestreamtransaction) article.
55
55
56
-
The following diagram illustrates the underlying tasks performed by the **WriteTextAsync** method in a successful write operation. This illustration provides a simplified view of the operation. For example, it skips steps such as text encoding and async completion on different threads.
56
+
The following diagram illustrates the underlying tasks performed by the WriteTextAsync method in a successful write operation. This illustration provides a simplified view of the operation. For example, it skips steps such as text encoding and async completion on different threads.
57
57
58
58

59
59
60
-
The advantages of using the **Write** methods of the [**FileIO**](/uwp/api/Windows.Storage.FileIO) and [**PathIO**](/uwp/api/windows.storage.pathio) classes instead of the more complex four-step model using a stream are:
60
+
The advantages of using the Write methods of the [FileIO](/uwp/api/Windows.Storage.FileIO) and [PathIO](/uwp/api/windows.storage.pathio) classes instead of the more complex four-step model using a stream are:
61
61
62
62
* One API call to handle all the intermediate steps, including errors.
63
63
* The original file is kept if something goes wrong.
64
64
* The system state will try to be kept as clean as possible.
65
65
66
-
However, with so many possible intermediate points of failure, there’s an increased chance of failure. When an error occurs it may be difficult to understand where the process failed. The following sections present some of the failures you might encounter when using the **Write** methods and provide possible solutions.
66
+
However, with so many possible intermediate points of failure, there’s an increased chance of failure. When an error occurs it may be difficult to understand where the process failed. The following sections present some of the failures you might encounter when using the Write methods and provide possible solutions.
67
67
68
68
## Common error codes for Write methods of the FileIO and PathIO classes
69
69
70
-
This table presents common error codes that app developers encounter when using the **Write** methods. The steps in the table correspond to steps in the previous diagram.
70
+
This table presents common error codes that app developers encounter when using the Write methods. The steps in the table correspond to steps in the previous diagram.
@@ -80,23 +80,23 @@ This table presents common error codes that app developers encounter when using
80
80
81
81
## Other considerations for file states that might lead to errors
82
82
83
-
Apart from errors returned by the **Write** methods, here are some guidelines on what an app can expect when writing to a file.
83
+
Apart from errors returned by the Write methods, here are some guidelines on what an app can expect when writing to a file.
84
84
85
85
### Data was written to the file if and only if operation completed
86
86
87
87
Your app should not make any assumption about data in the file while a write operation is in progress. Trying to access the file before an operation completes might lead to inconsistent data. Your app should be responsible of tracking outstanding I/Os.
88
88
89
89
### Readers
90
90
91
-
If the file that being written to is also being used by a polite reader (that is, opened with [**FileAccessMode.Read**](/uwp/api/Windows.Storage.FileAccessMode), subsequent reads will fail with an error ERROR_OPLOCK_HANDLE_CLOSED (0x80070323). Sometimes apps retry opening the file for read again while the **Write** operation is ongoing. This might result in a race condition on which the **Write** ultimately fails when trying to overwrite the original file because it cannot be replaced.
91
+
If the file that being written to is also being used by a polite reader (that is, opened with [FileAccessMode.Read](/uwp/api/Windows.Storage.FileAccessMode), subsequent reads will fail with an error ERROR_OPLOCK_HANDLE_CLOSED (0x80070323). Sometimes apps retry opening the file for read again while the Write operation is ongoing. This might result in a race condition on which the Write ultimately fails when trying to overwrite the original file because it cannot be replaced.
92
92
93
93
### Files from KnownFolders
94
94
95
-
Your app might not be the only app that is trying to access a file that resides on any of the [**KnownFolders**](/uwp/api/Windows.Storage.KnownFolders). There’s no guarantee that if the operation is successful, the contents an app wrote to the file will remain constant the next time it tries to read the file. Also, sharing or access denied errors become more common under this scenario.
95
+
Your app might not be the only app that is trying to access a file that resides on any of the [KnownFolders](/uwp/api/Windows.Storage.KnownFolders). There’s no guarantee that if the operation is successful, the contents an app wrote to the file will remain constant the next time it tries to read the file. Also, sharing or access denied errors become more common under this scenario.
96
96
97
97
### Conflicting I/O
98
98
99
-
The chances of concurrency errors can be lowered if our app uses the **Write** methods for files in its local data, but some caution is still required. If multiple **Write** operations are being sent concurrently to the file, there’s no guarantee about what data ends up in the file. To mitigate this, we recommend that your app serializes **Write** operations to the file.
99
+
The chances of concurrency errors can be lowered if our app uses the Write methods for files in its local data, but some caution is still required. If multiple Write operations are being sent concurrently to the file, there’s no guarantee about what data ends up in the file. To mitigate this, we recommend that your app serializes Write operations to the file.
100
100
101
101
### ~TMP files
102
102
@@ -108,7 +108,7 @@ Some errors can become more prevalent depending on the type of files, the freque
108
108
109
109
* Files created and edited by the user in your app's local data folder. These are created and edited only while using your app, and they exist only within the app.
110
110
* App metadata. Your app uses these files to keep track of its own state.
111
-
* Other files in locations of the file system where your app has declared capabilities to access. These are most commonly located in one of the [**KnownFolders**](/uwp/api/Windows.Storage.KnownFolders).
111
+
* Other files in locations of the file system where your app has declared capabilities to access. These are most commonly located in one of the [KnownFolders](/uwp/api/Windows.Storage.KnownFolders).
112
112
113
113
Your app has full control on the first two categories of files, because they’re part of your app's package files and are accessed by your app exclusively. For files in the last category, your app must be aware that other apps and OS services may be accessing the files concurrently.
114
114
@@ -118,7 +118,7 @@ Depending on the app, access to the files can vary on frequency:
118
118
* Low. These are files that the user is specifically taking an action on (such as save or load).
119
119
* Medium or high. These are files in which the app must constantly update data (for example, autosave features or constant metadata tracking).
120
120
121
-
For file size, consider the performance data in the following chart for the **WriteBytesAsync** method. This chart compares the time to complete an operation vs file size, over an average performance of 10000 operations per file size in a controlled environment.
121
+
For file size, consider the performance data in the following chart for the WriteBytesAsync method. This chart compares the time to complete an operation vs file size, over an average performance of 10000 operations per file size in a controlled environment.
@@ -135,9 +135,9 @@ Unless the OS grants extended execution to your app, when your app is suspended
135
135
136
136
* Try to keep I/O to a minimum to avoid race conditions caused by flushing and release operations.
137
137
* Avoid writing files that require hundreds of milliseconds or more to write.
138
-
* If your app uses the **Write** methods, keep in mind all the intermediate steps that these methods require.
138
+
* If your app uses the Write methods, keep in mind all the intermediate steps that these methods require.
139
139
140
-
If your app operates on a small amount of state data during suspension, in most cases you can use the **Write** methods to flush the data. However, if your app uses a large amount of state data, consider using streams to directly store your data. This can help reduce the delay introduced by the transactional model of the **Write** methods.
140
+
If your app operates on a small amount of state data during suspension, in most cases you can use the Write methods to flush the data. However, if your app uses a large amount of state data, consider using streams to directly store your data. This can help reduce the delay introduced by the transactional model of the Write methods.
141
141
142
142
For an example, see the [BasicSuspension](https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/BasicSuspension) sample.
0 commit comments