Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrieve the total size of the data stored in Async Storage #336

Open
ziyaddin opened this issue Apr 17, 2020 · 7 comments
Open

Retrieve the total size of the data stored in Async Storage #336

ziyaddin opened this issue Apr 17, 2020 · 7 comments
Labels
enhancement New feature or request help wanted :octocat:

Comments

@ziyaddin
Copy link

ziyaddin commented Apr 17, 2020

Motivation

In some cases, it is important to know the current total size of the data stored in Async Storage. It would help to predict possible storage issues beforehand due to the storage limit set by React Native authors.

Description

Described in "Motivation" section.

New feature implementation

Possible methods in my mind:

  1. Natively (Android API/iOS API) calculate and retrieve the size;
  2. Iteratively (via JS) calculate the size of all keys and corresponding values and find the sum.
@tido64 tido64 added the enhancement New feature or request label Oct 14, 2020
@gusilveiramp
Copy link

gusilveiramp commented Jan 25, 2021

It would be great.
Is there already a way to get this information?

@github-actions
Copy link

This issue has been marked as stale due to inactivity. Please respond or otherwise resolve the issue within 7 days or it will be closed.

@isidoro98
Copy link

isidoro98 commented Jun 27, 2021

@ziyaddin @gusilveiramp I wanted to know the size of storage I was using on iOS, in case you still want to know the code below does the job, you'll just need to expose the native method. It returns the amount of storage used in Bytes

-(NSString *)_getSize
{
    NSString* directory = RCTGetStorageDirectory();
    NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directory error:nil];
    NSEnumerator *contentsEnumurator = [contents objectEnumerator];

    NSString *file;
    unsigned long long int folderSize = 0;

    while (file = [contentsEnumurator nextObject]) {
        NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[directory stringByAppendingPathComponent:file] error:nil];
        folderSize += [[fileAttributes objectForKey:NSFileSize] intValue];
    }

    NSString *sizeStr = [NSString stringWithFormat:@"%llu", folderSize];
    
    return sizeStr;
}

EDIT:

Also find the code below for Android, as above it returns the storage used in bytes:

File f = new File(mReactDatabaseSupplier.get().getPath());
long dbSize = f.length();

@ferasabufares
Copy link

@isidoro98

is there a way to get total size of the data for android ???

@isidoro98
Copy link

@isidoro98

is there a way to get total size of the data for android ???

This should do it, based of this SO answer: https://stackoverflow.com/questions/6364577/how-to-get-the-current-sqlite-database-size-or-package-size-in-android/52191503

File f = new File(mReactDatabaseSupplier.get().getPath());
long dbSize = f.length();

@isaachinman
Copy link

Anyone have a handy way to do this from the JS side of things?

@krestaino
Copy link

@isaachinman I put this together while searching for an answer to this question. It seems to be working well enough.

import AsyncStorage from "@react-native-async-storage/async-storage";
import { Buffer } from "buffer";

function byteLength(obj) {
  return Buffer.byteLength(JSON.stringify(obj));
}

function formatBytes(bytes, decimals = 2) {
  if (!+bytes) return "0 Bytes";

  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ["Bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];

  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
}

export async function clearStorage() {
  await AsyncStorage.clear();
}

export async function calculateSizes() {
  const keys = await AsyncStorage.getAllKeys();
  console.info("Total keys in AsyncStorage:", keys.length);

  let totalSizeInBytes = 0;

  for (const key of keys) {
    try {
      const item = await AsyncStorage.getItem(key);
      if (item) {
        const sizeInBytes = byteLength(JSON.parse(item));
        console.info(`${key} (${formatBytes(sizeInBytes)})`);
        totalSizeInBytes += sizeInBytes;
      }
    } catch (error) {
      console.error(`Error reading '${key}' from AsyncStorage: ${error.message}`);
    }
  }

  console.info(`Total size of all keys: ${formatBytes(totalSizeInBytes)}`);
}

And then in your root component:

import { registerRootComponent } from "expo";
import App from "./App";

import { calculateSizes, clearStorage } from "./utilities/asyncStorage";

calculateSizes();
// clearStorage(); // https://react-native-async-storage.github.io/async-storage/docs/api/#clear

export default registerRootComponent(App);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted :octocat:
Projects
None yet
Development

No branches or pull requests

7 participants