# Persisting Preferences Data
## When to Use
The **Preferences** module provides APIs for processing data in the form of key-value (KV) pairs, including querying, modifying, and persisting KV pairs. You can use **Preferences** when you want a unique storage for global data.
**Preferences** caches data in the memory, which allows fast access when the data is required. If you want to persist data, you can use **flush()** to save the data to a file. **Preferences** is recommended for storing small amount of data, such as personalized settings (font size and whether to enable the night mode) of applications.
## Working Principles
User applications call **Preference** through the ArkTS interface to read and write data files. You can load the data of a **Preferences** persistence file to a **Preferences** instance. Each file uniquely corresponds to an instance. The system stores the instance in memory through a static container until the instance is removed from the memory or the file is deleted. The following figure illustrates how **Preference** works.
The preference persistent file of an application is stored in the application sandbox. You can use **context** to obtain the file path. For details, see [Obtaining Application File Paths](../application-models/application-context-stage.md#obtaining-application-file-paths).
**Figure 1** Preferences working mechanism

## Constraints
- The key in a KV pair must be a string and cannot be empty or exceed 80 bytes.
- If the value is of the string type, use the UTF-8 encoding format. It can be empty or a string not longer than 8192 bytes.
- The memory usage increases with the amount of **Preferences** data. The maximum number of data records recommended is 10,000. Otherwise, high memory overheads will be caused.
## Available APIs
The following table lists the APIs used for persisting user preference data. For more information about the APIs, see [User Preferences](../reference/apis-arkdata/js-apis-data-preferences.md).
| API | Description |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| getPreferencesSync(context: Context, options: Options): Preferences | Obtains a **Preferences** instance. This API returns the result synchronously.
An asynchronous API is also provided. |
| putSync(key: string, value: ValueType): void | Writes data to the **Preferences** instance. This API returns the result synchronously. An asynchronous API is also provided.
You can use **flush()** to persist the **Preferences** instance data. |
| hasSync(key: string): void | Checks whether the **Preferences** instance contains a KV pair with the given key. The key cannot be empty. This API returns the result synchronously.
An asynchronous API is also provided.|
| getSync(key: string, defValue: ValueType): void | Obtains the value of the specified key. If the value is null or not of the default value type, **defValue** is returned. This API returns the result synchronously.
An asynchronous API is also provided.|
| deleteSync(key: string): void | Deletes a KV pair with the given key from the **Preferences** instance. This API returns the result synchronously.
An asynchronous API is also provided.|
| flush(callback: AsyncCallback<void>): void | Flushes the data of this **Preferences** instance to a file for data persistence.|
| on(type: 'change', callback: Callback<string>): void | Subscribes to data changes of the specified key. When the value of the specified key is changed and saved by **flush()**, a callback will be invoked to return the new data.|
| off(type: 'change', callback?: Callback<string>): void | Unsubscribes from data changes. |
| deletePreferences(context: Context, options: Options, callback: AsyncCallback<void>): void | Deletes a **Preferences** instance from memory. If the **Preferences** instance has a persistent file, this API also deletes the persistent file.|
## How to Develop
1. Import the **@ohos.data.preferences** module.
```ts
import dataPreferences from '@ohos.data.preferences';
```
2. Obtain a **Preferences** instance. Read data from a file and load the data to a **Preferences** instance for data operations.
Stage model:
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import { BusinessError } from '@ohos.base';
import window from '@ohos.window';
let preferences: dataPreferences.Preferences | null = null;
class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage) {
let options: dataPreferences.Options = { name: 'myStore' };
preferences = dataPreferences.getPreferencesSync(this.context, options);
}
}
```
FA model:
```ts
// Obtain the context.
import featureAbility from '@ohos.ability.featureAbility';
import { BusinessError } from '@ohos.base';
let context = featureAbility.getContext();
let options: dataPreferences.Options = { name: 'myStore' };
let preferences: dataPreferences.Preferences = dataPreferences.getPreferencesSync(context, options);
```
3. Write data.
Use **putSync()** to save data to the cached **Preferences** instance. After data is written, you can use **flush()** to persist the **Preferences** instance data to a file if necessary.
> **NOTE**
>
> If the specified key already exists, the **putSync()** method changes the value. You can use **hasSync()** to check whether the KV pair exists.
Example:
```ts
import util from '@ohos.util';
if (preferences.hasSync('startup')) {
console.info("The key 'startup' is contained.");
} else {
console.info("The key 'startup' does not contain.");
// Add a KV pair.
preferences.putSync('startup', 'auto');
// If the string contains special characters, convert the string into a Uint8Array before storing it.
let uInt8Array = new util.TextEncoder().encodeInto("~! @#¥%......&* () --+? ");
preferences.putSync('uInt8', uInt8Array);
}
```
3. Read data.
Use **getSync()** to obtain the value of the specified key. If the value is null or is not of the default value type, the default data is returned.
Example:
```ts
import util from '@ohos.util';
let val = preferences.getSync('startup', 'default');
console.info("The 'startup' value is " + val);
// If the value is a string containing special characters, it is stored in the Uint8Array format. Conver the obtained Uint8Array into a string.
let uInt8Array : dataPreferences.ValueType = preferences.getSync('uInt8', new Uint8Array(0));
let textDecoder = util.TextDecoder.create('utf-8');
val = textDecoder.decodeWithStream(uInt8Array as Uint8Array);
console.info("The 'uInt8' value is " + val);
```
4. Delete data.
Use **deleteSync()** to delete a KV pair.
Example:
```ts
preferences.deleteSync('startup');
```
6. Persist data.
You can use **flush()** to persist the data held in a **Preferences** instance to a file.
Example:
```ts
preferences.flush((err: BusinessError) => {
if (err) {
console.error(`Failed to flush. Code:${err.code}, message:${err.message}`);
return;
}
console.info('Succeeded in flushing.');
})
```
7. Subscribe to data changes.
Specify an observer as the callback to return the data changes for an application. When the value of the subscribed key is changed and saved by **flush()**, the observer callback will be invoked to return the new data.
Example:
```ts
let observer = (key: string) => {
console.info('The key' + key + 'changed.');
}
preferences.on('change', observer);
// The data is changed from 'auto' to 'manual'.
preferences.put('startup', 'manual', (err: BusinessError) => {
if (err) {
console.error(`Failed to put the value of 'startup'. Code:${err.code},message:${err.message}`);
return;
}
console.info("Succeeded in putting the value of 'startup'.");
if (preferences !== null) {
preferences.flush((err: BusinessError) => {
if (err) {
console.error(`Failed to flush. Code:${err.code}, message:${err.message}`);
return;
}
console.info('Succeeded in flushing.');
})
}
})
```
8. Delete a **Preferences** instance from the memory.
Use **deletePreferences()** to delete a **Preferences** instance from the memory. If the **Preferences** instance has a persistent file, the persistent file and its backup and corrupted files will also be deleted.
> **NOTE**
>
> - The deleted **Preferences** instance cannot be used for data operations. Otherwise, data inconsistency will be caused.
>
> - The deleted data and files cannot be restored.
Example:
```ts
let options: dataPreferences.Options = { name: 'myStore' };
dataPreferences.deletePreferences(this.context, options, (err: BusinessError) => {
if (err) {
console.error(`Failed to delete preferences. Code:${err.code}, message:${err.message}`);
return;
}
console.info('Succeeded in deleting preferences.');
})
```