# Class Storage

java.lang.Object
com.codename1.io.Storage

public class Storage extends Object

Abstracts the underlying application specific storage system, unlike the `com.codename1.io.FileSystemStorage` this class is a higher level abstraction. The `Storage` class is designed to be very portable and as such it has no support for staple file system capabilities such as hierarchies.

Check out a more thorough discussion of this API `here`.

The sample code below shows a simple storage browser tool in action:

    public void showForm() {
        Toolbar.setGlobalToolbar(true);
        Form hi = new Form("Storage", new BoxLayout(BoxLayout.Y_AXIS));
        hi.getToolbar().addCommandToRightBar("+", null, (e) -> {
            TextField tf = new TextField("", "File Name", 20, TextField.ANY);
            TextArea body = new TextArea(5, 20);
            body.setHint("File Body");
            Command ok = new Command("OK");
            Command cancel = new Command("Cancel");
            Command result = Dialog.show("File Name", BorderLayout.north(tf).add(BorderLayout.CENTER, body), ok, cancel);
            if(ok == result) {
                try(OutputStream os = Storage.getInstance().createOutputStream(tf.getText())) {
                    os.write(body.getText().getBytes("UTF-8"));
                    createFileEntry(hi, tf.getText());
                    hi.getContentPane().animateLayout(250);
                } catch(IOException err) {
                    Log.e(err);
                }
            }
        });

        for(String file : Storage.getInstance().listEntries()) {
            createFileEntry(hi, file);
        }
        hi.show();
    }

    private void createFileEntry(Form hi, String file) {
       Label fileField = new Label(file);
       Button delete = new Button();
       Button view = new Button();
       FontImage.setMaterialIcon(delete, FontImage.MATERIAL_DELETE);
       FontImage.setMaterialIcon(view, FontImage.MATERIAL_OPEN_IN_NEW);
       Container content = BorderLayout.center(fileField);
       int size = Storage.getInstance().entrySize(file);
       content.add(BorderLayout.EAST, BoxLayout.encloseX(new Label(size + "bytes"), delete, view));
       delete.addActionListener((e) -> {
           Storage.getInstance().deleteStorageFile(file);
           content.setY(hi.getWidth());
           hi.getContentPane().animateUnlayoutAndWait(150, 255);
           hi.removeComponent(content);
           hi.getContentPane().animateLayout(150);
       });
       view.addActionListener((e) -> {
           try(InputStream is = Storage.getInstance().createInputStream(file)) {
               String s = Util.readToString(is, "UTF-8");
               Dialog.show(file, s, "OK", null);
           } catch(IOException err) {
               Log.e(err);
           }
       });
       hi.add(content);
    }

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `Storage()`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `clearCache()`
  Storage is cached for faster access, however this might cause a problem with refreshing objects since they are not cloned.
  `void`
  `clearStorage()`
  Deletes all the files in the application storage
  `java.io.InputStream`
  `createInputStream(String name)`
  Creates an input stream to the given storage source file
  `java.io.OutputStream`
  `createOutputStream(String name)`
  Creates an output stream to the storage with the given name
  `void`
  `deleteStorageFile(String name)`
  Deletes the given file name from the storage
  `int`
  `entrySize(String name)`
  Returns the size in bytes of the given entry
  `boolean`
  `exists(String name)`
  Returns true if the given storage file exists
  `void`
  `flushStorageCache()`
  Flush the storage cache allowing implementations that cache storage objects to store
  `static Storage`
  `getInstance()`
  Returns the storage instance or null if the storage wasn't initialized using a call to init(String) first.
  `static boolean`
  `isInitialized()`
  Returns true if the storage is initialized
  `boolean`
  `isNormalizeNames()`
  Indicates whether characters that are typically illegal in filesystems should be sanitized and replaced with underscore
  `String[]`
  `listEntries()`
  Lists the names of the storage files
  `Object`
  `readObject(String name)`
  Reads the object from the storage, returns null if the object isn't there
  `Object`
  `readObject(String name, boolean includeLogging)`
  Reads the object from the storage, returns null if the object isn't there
  `void`
  `setHardCacheSize(int size)`
  Indicates the caching size, storage can be pretty slow
  `void`
  `setNormalizeNames(boolean normalizeNames)`
  Indicates whether characters that are typically illegal in filesystems should be sanitized and replaced with underscore
  `static void`
  `setStorageInstance(Storage s)`
  Allows installing a custom storage instance to provide functionality such as seamless encryption
  `boolean`
  `writeObject(String name, Object o)`
  Writes the given object to storage assuming it is an externalizable type or one of the supported types.
  `boolean`
  `writeObject(String name, Object o, boolean includeLogging)`
  Writes the given object to storage assuming it is an externalizable type or one of the supported types.

  ### Methods inherited from class Object

  `clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Constructor Details

  - ### Storage

    public Storage()

- ## Method Details

  - ### isInitialized

    public static boolean isInitialized()

    Returns true if the storage is initialized

    ###### Returns

    true if the storage is initialized

  - ### getInstance

    public static Storage getInstance()

    Returns the storage instance or null if the storage wasn't initialized using a call to init(String) first.

    ###### Returns

    storage instance

  - ### setStorageInstance

    public static void setStorageInstance(Storage s)

    Allows installing a custom storage instance to provide functionality such as seamless encryption

    ###### Parameters

    - `s`: the storage instance

  - ### setHardCacheSize

    public void setHardCacheSize(int size)

    Indicates the caching size, storage can be pretty slow

    ###### Parameters

    - `size`: size in elements (not kb!)

  - ### clearCache

    public void clearCache()
    Storage is cached for faster access, however this might cause a problem with refreshing objects since they are not cloned. Clearing the cache allows to actually reload from the storage file.

  - ### flushStorageCache

    public void flushStorageCache()
    Flush the storage cache allowing implementations that cache storage objects to store

  - ### deleteStorageFile

    public void deleteStorageFile(String name)

    Deletes the given file name from the storage

    ###### Parameters

    - `name`: the name of the storage file

  - ### clearStorage

    public void clearStorage()
    Deletes all the files in the application storage

  - ### createOutputStream

    public java.io.OutputStream createOutputStream(String name) throws java.io.IOException

    Creates an output stream to the storage with the given name

    ###### Parameters

    - `name`: the storage file name

    ###### Returns

    an output stream of limited capacity

    Throws:
      `java.io.IOException`

  - ### createInputStream

    public java.io.InputStream createInputStream(String name) throws java.io.IOException

    Creates an input stream to the given storage source file

    ###### Parameters

    - `name`: the name of the source file

    ###### Returns

    the input stream

    Throws:
      `java.io.IOException`

  - ### exists

    public boolean exists(String name)

    Returns true if the given storage file exists

    ###### Parameters

    - `name`: the storage file name

    ###### Returns

    true if it exists

  - ### listEntries

    public String[] listEntries()

    Lists the names of the storage files

    ###### Returns

    the names of all the storage files

  - ### entrySize

    public int entrySize(String name)

    Returns the size in bytes of the given entry

    ###### Parameters

    - `name`: the name of the entry

    ###### Returns

    the size in bytes

  - ### writeObject

    public boolean writeObject(String name, Object o)

    Writes the given object to storage assuming it is an externalizable type or one of the supported types.

    The sample below demonstrates the usage and registration of the `com.codename1.io.Externalizable` interface:

        // File: Main.java
        public class Main {
          public void init(Object o) {
            theme = UIManager.initFirstTheme("/theme");

            // IMPORTANT: Notice we don't use MyClass.class.getName()! This won't work due to obfuscation!
            Util.register("MyClass", MyClass.class);
          }

          public void start() {
            //...
          }

          public void stop() {
            //...
          }

          public void destroy() {
            //...
          }
        }

        // File: MyClass.java
        public class MyClass implements Externalizable {
          // allows us to manipulate the version, in this case we are demonstrating a data change between the initial release
          // and the current state of object data
          private static final int VERSION = 2;

          private String name;
          private Map data;

          // this field was added after version 1
          private Date startedAt;

          public int getVersion() {
            return VERSION;
          }

          public void externalize(DataOutputStream out) throws IOException {
            Util.writeUTF(name, out);
            Util.writeObject(data, out);
            if(startedAt != null) {
                out.writeBoolean(true);
                out.writeLong(startedAt.getTime());
            } else {
                out.writeBoolean(false);
            }
          }
          public void internalize(int version, DataInputStream in) throws IOException {
            name = Util.readUTF(in);
            data = (Map)Util.readObject(in);
            if(version > 1) {
                boolean hasDate = in.readBoolean();
                if(hasDate) {
                    startedAt = new Date(in.readLong());
                }
            }
          }
          public String getObjectId() {
            // IMPORTANT: Notice we don't use getClass().getName()! This won't work due to obfuscation!
            return "MyClass";
          }
        }

        // File: ReadAndWrite.java
        // will read the file or return null if failed
        MyClass object = (MyClass)Storage.getInstance().readObject("NameOfFile");

        // write the object back to storage
        Storage.getInstance().writeObject("NameOfFile", object);

    ###### Parameters

    - `name`: store name

    - `o`: object to store

    ###### Returns

    true for success, false for failure

  - ### writeObject

    public boolean writeObject(String name, Object o, boolean includeLogging)

    Writes the given object to storage assuming it is an externalizable type or one of the supported types.

    The sample below demonstrates the usage and registration of the `com.codename1.io.Externalizable` interface:

        // File: Main.java
        public class Main {
          public void init(Object o) {
            theme = UIManager.initFirstTheme("/theme");

            // IMPORTANT: Notice we don't use MyClass.class.getName()! This won't work due to obfuscation!
            Util.register("MyClass", MyClass.class);
          }

          public void start() {
            //...
          }

          public void stop() {
            //...
          }

          public void destroy() {
            //...
          }
        }

        // File: MyClass.java
        public class MyClass implements Externalizable {
          // allows us to manipulate the version, in this case we are demonstrating a data change between the initial release
          // and the current state of object data
          private static final int VERSION = 2;

          private String name;
          private Map data;

          // this field was added after version 1
          private Date startedAt;

          public int getVersion() {
            return VERSION;
          }

          public void externalize(DataOutputStream out) throws IOException {
            Util.writeUTF(name, out);
            Util.writeObject(data, out);
            if(startedAt != null) {
                out.writeBoolean(true);
                out.writeLong(startedAt.getTime());
            } else {
                out.writeBoolean(false);
            }
          }
          public void internalize(int version, DataInputStream in) throws IOException {
            name = Util.readUTF(in);
            data = (Map)Util.readObject(in);
            if(version > 1) {
                boolean hasDate = in.readBoolean();
                if(hasDate) {
                    startedAt = new Date(in.readLong());
                }
            }
          }
          public String getObjectId() {
            // IMPORTANT: Notice we don't use getClass().getName()! This won't work due to obfuscation!
            return "MyClass";
          }
        }

        // File: ReadAndWrite.java
        // will read the file or return null if failed
        MyClass object = (MyClass)Storage.getInstance().readObject("NameOfFile");

        // write the object back to storage
        Storage.getInstance().writeObject("NameOfFile", object);

    ###### Parameters

    - `name`: store name

    - `o`: object to store

    - `includeLogging`: During app initialization, the logging on error might impact the apps stability

    ###### Returns

    true for success, false for failure

  - ### readObject

    public Object readObject(String name)

    Reads the object from the storage, returns null if the object isn't there

    The sample below demonstrates the usage and registration of the `com.codename1.io.Externalizable` interface:

        // File: Main.java
        public class Main {
          public void init(Object o) {
            theme = UIManager.initFirstTheme("/theme");

            // IMPORTANT: Notice we don't use MyClass.class.getName()! This won't work due to obfuscation!
            Util.register("MyClass", MyClass.class);
          }

          public void start() {
            //...
          }

          public void stop() {
            //...
          }

          public void destroy() {
            //...
          }
        }

        // File: MyClass.java
        public class MyClass implements Externalizable {
          // allows us to manipulate the version, in this case we are demonstrating a data change between the initial release
          // and the current state of object data
          private static final int VERSION = 2;

          private String name;
          private Map data;

          // this field was added after version 1
          private Date startedAt;

          public int getVersion() {
            return VERSION;
          }

          public void externalize(DataOutputStream out) throws IOException {
            Util.writeUTF(name, out);
            Util.writeObject(data, out);
            if(startedAt != null) {
                out.writeBoolean(true);
                out.writeLong(startedAt.getTime());
            } else {
                out.writeBoolean(false);
            }
          }
          public void internalize(int version, DataInputStream in) throws IOException {
            name = Util.readUTF(in);
            data = (Map)Util.readObject(in);
            if(version > 1) {
                boolean hasDate = in.readBoolean();
                if(hasDate) {
                    startedAt = new Date(in.readLong());
                }
            }
          }
          public String getObjectId() {
            // IMPORTANT: Notice we don't use getClass().getName()! This won't work due to obfuscation!
            return "MyClass";
          }
        }

        // File: ReadAndWrite.java
        // will read the file or return null if failed
        MyClass object = (MyClass)Storage.getInstance().readObject("NameOfFile");

        // write the object back to storage
        Storage.getInstance().writeObject("NameOfFile", object);

    ###### Parameters

    - `name`: name of the store

    ###### Returns

    object stored under that name

  - ### readObject

    public Object readObject(String name, boolean includeLogging)

    Reads the object from the storage, returns null if the object isn't there

    The sample below demonstrates the usage and registration of the `com.codename1.io.Externalizable` interface:

        // File: Main.java
        public class Main {
          public void init(Object o) {
            theme = UIManager.initFirstTheme("/theme");

            // IMPORTANT: Notice we don't use MyClass.class.getName()! This won't work due to obfuscation!
            Util.register("MyClass", MyClass.class);
          }

          public void start() {
            //...
          }

          public void stop() {
            //...
          }

          public void destroy() {
            //...
          }
        }

        // File: MyClass.java
        public class MyClass implements Externalizable {
          // allows us to manipulate the version, in this case we are demonstrating a data change between the initial release
          // and the current state of object data
          private static final int VERSION = 2;

          private String name;
          private Map data;

          // this field was added after version 1
          private Date startedAt;

          public int getVersion() {
            return VERSION;
          }

          public void externalize(DataOutputStream out) throws IOException {
            Util.writeUTF(name, out);
            Util.writeObject(data, out);
            if(startedAt != null) {
                out.writeBoolean(true);
                out.writeLong(startedAt.getTime());
            } else {
                out.writeBoolean(false);
            }
          }
          public void internalize(int version, DataInputStream in) throws IOException {
            name = Util.readUTF(in);
            data = (Map)Util.readObject(in);
            if(version > 1) {
                boolean hasDate = in.readBoolean();
                if(hasDate) {
                    startedAt = new Date(in.readLong());
                }
            }
          }
          public String getObjectId() {
            // IMPORTANT: Notice we don't use getClass().getName()! This won't work due to obfuscation!
            return "MyClass";
          }
        }

        // File: ReadAndWrite.java
        // will read the file or return null if failed
        MyClass object = (MyClass)Storage.getInstance().readObject("NameOfFile");

        // write the object back to storage
        Storage.getInstance().writeObject("NameOfFile", object);

    ###### Parameters

    - `name`: name of the store

    - `includeLogging`: During app initialization, the logging on error might impact the apps stability

    ###### Returns

    object stored under that name

  - ### isNormalizeNames

    public boolean isNormalizeNames()

    Indicates whether characters that are typically illegal in filesystems should be sanitized and replaced with underscore

    ###### Returns

    the normalizeNames

  - ### setNormalizeNames

    public void setNormalizeNames(boolean normalizeNames)

    Indicates whether characters that are typically illegal in filesystems should be sanitized and replaced with underscore

    ###### Parameters

    - `normalizeNames`: the normalizeNames to set