How to get the overall size of the database? - Flutter - flutter

I'm having a couple of tables in a particular database and so i was hoping to get the size of the database when the data is dumped into the particular tables.
This is how i tried
var db = await openDatabase('dummy.db');
int count = Sqflite.firstIntValue(await db.rawQuery('SELECT COUNT(*) FROM dummyTable1'));
I know this approach is wrong since I'm getting only the number of rows in the particular table but how to get the size of the particular table?

Something like this will tell you the size of your db
final databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'dummy.db');
final file = File(path);
Now you can get the file size with
final size = file.lengthSync();
or
final size = await file.length();
or alternatively if flutter db support it, you can have a look here:
https://www.sqlite.org/pragma.html#pragma_page_count

Related

How to define SharedPreferences from an Object?

I'm using shared_preferences.dart package. When the user login in the App, I load some preferences from an object of Settings named Configuracion that looks like attached.
The way I'm loading _prefs is as follows...
final _prefs = new PreferenciasUsuario();
ConfiguracionModel _configuracion = new ConfiguracionModel();
_configuracion = await configuracionBloc.cargarConfiguracion(_prefs.idEmpresa);
_prefs.idioma = _configuracion.idioma;
_prefs.medidaDistancia = _configuracion.medidaDistancia;
_prefs.medidaOxigeno = _configuracion.medidaOxigeno;
_prefs.medidaPeso = _configuracion.medidaPeso;
_prefs.medidaPesoUnidad = _configuracion.medidaPesoUnidad;
_prefs.medidaTemp = _configuracion.medidaTemp;
//......a large list of more and more ....
Is there a way to reduce the large amount of code?
Something like _prefs... = _configuracion...

Stacking Multiple Rows of Strings in Csv in Flutter

I have this code which should stack multiple rows one on top of another in Flutter with the CSV library.
exportCsv(List<Drink> drinksFeed, List<Alcohol> alcoholFeed
) async {
List<List<dynamic>> rows = List<List<dynamic>>();
for (int i = 0; i < drinksFeed.length; i++) {
List<dynamic> row = List();
row.add(drinksFeed[i].id);
row.add(drinksFeed[i].name);
row.add(drinksFeed[i].description);
row.add(drinksFeed[i].price);
rows.add(row);
setState(() {
drinksFeed = drinkFeedback;
});
}
List<List<dynamic>> alcoholRows = List<List<dynamic>>();
for (int i = 0; i < alcoholFeed.length; i++) {
List<dynamic> row = List();
row.add(alcoholFeed[i].id);
row.add(alcoholFeed[i].name);
row.add(alcoholFeed[i].description);
row.add(alcoholFeed[i].price);
alcoholRows.add(row);
setState(() {
alcoholFeed = alcoholFeedback;
});
}
String drinkCsv = const ListToCsvConverter().convert(rows);
String alcoholCsv = const ListToCsvConverter().convert(alcoholRows);
f.writeAsString(drinkCsv);
f.writeAsString(alcoholCsv);
}
}
As you can see, it takes each element from a list and writes it as a string, but for some reason, it isn't stacking rows on top of one another (drinkCsv and alcoholCsv), it just shows the drinksCsv elements in the CSV file. This isn't the full code, because it's too long and I don't think it's relevant to show CSV export, but this should be enough.
So my question is, is it possible to stack multiple elements one on top of another in 1 csv file (drinkCsv + alcoholCsv in this case).
Maybe awaiting before writing again could solve the problem, also changing the mode to append so it continues writing at the end of the file
await f.writeAsString(drinkCsv);
await f.writeAsString(alcoholCsv, mode: FileMode.append);
the best solution I can come up is combining the 2 lists before doing the convert (I haven't used that ListToCsvConverter().convert() so I'm not sure how does the string result looks like)
String fileCsv = const ListToCsvConverter().convert([...rows, ...alcoholRows]);
await f.writeAsString(fileCsv);
That way maybe the converter do the correct append between the rows when converting to string

SecondaryTile with unicode character in DisplayName

I am using this piece of code to create a SecondaryTile.
public static async Task<bool> PinToStartAsync(Playlist playlist, bool isPlaylist)
{
var tilename = playlist.Name;
var tileid = Uri.EscapeDataString(isPlaylist ? tilename : $"{tilename}+++{playlist.Artist}");
var filename = Uri.EscapeDataString(tilename);
var path = LogoPath;
if (playlist.DisplayItem.Source != null && await (await GetSecondaryTileFolder()).TryGetItemAsync(filename) == null)
{
await (await GetStorageItemThumbnailAsync(playlist.DisplayItem.Source.Path)).SaveAsync(SecondaryTileFolder, filename);
path = $"ms-appdata:///local/SecondaryTiles/{filename}.png";
}
var tile = new SecondaryTile(tileid, tilename, isPlaylist.ToString(), new Uri(path), TileSize.Default);
tile.VisualElements.ShowNameOnSquare150x150Logo = tile.VisualElements.ShowNameOnSquare310x310Logo = tile.VisualElements.ShowNameOnWide310x150Logo = true;
if (SecondaryTile.Exists(tilename)) await tile.RequestDeleteAsync();
else await tile.RequestCreateAsync();
return SecondaryTile.Exists(tilename);
}
This piece of code works fine when the playlist name is like 123 or helloworld. However, when I use unicode in the tilename, it causes problem.
Below is an image of SecondaryTiles that I created. The name of first two has some unicode characters.
So it is not able to display the Thumbnail I stored locally, even though I created those images successfully.
Another problem with unicode character is that, the SecondaryTile.Exists(tilename) will always return false.
I have noticed the problem with unicode so I added Uri.EscapeDataString to tileid and filename so that they are uri safe. However, I do want my tiles to have names with unicode characters.
How should I allow unicode characters in tilename?
---Code Update---
public static async Task<bool> PinToStartAsync(Playlist playlist, bool isPlaylist)
{
var tilename = playlist.Name;
var tileid = WebUtility.UrlEncode(isPlaylist ? tilename : $"{tilename}+++{playlist.Artist}");
var filename = tileid + ".png";
var path = DefaultAlbumCoverPath;
if (playlist.DisplayItem.Source != null && !await (await GetSecondaryTileFolder()).Contains(filename))
{
await (await GetStorageItemThumbnailAsync(playlist.DisplayItem.Source.Path)).SaveAsync(SecondaryTileFolder, tileid);
path = $"ms-appdata:///local/SecondaryTiles/" + filename;
}
var tile = new SecondaryTile(tileid, tilename, isPlaylist.ToString(), new Uri(path), TileSize.Default);
tile.VisualElements.ShowNameOnSquare150x150Logo = tile.VisualElements.ShowNameOnSquare310x310Logo = tile.VisualElements.ShowNameOnWide310x150Logo = true;
if (SecondaryTile.Exists(tileid)) await tile.RequestDeleteAsync();
else await tile.RequestCreateAsync();
return SecondaryTile.Exists(tileid);
}
Since the SecondaryTile accesses the image through the path, the entire URI must be path-safe, which is a prerequisite for the software to successfully access the image.
From this perspective, there is nothing wrong with your handling.
In fact, these images are stored in the application's local storage and are not publicly available. The name doesn't need to be concerned.
But you can translate the image name via `Uri.UnescapeDataString()` when exporting these images or you want to get its name.
Update
As you can see from the picture you gave, the tile can display Chinese text (although it is illegible because it is white background + white text), so your question appears on the image.
You don't have to use Uri.EscapeDataString to change the file name, which will exceed the limit when converting long filenames.
You can save the image as the original name, but you can use the following methods when using the link:
string imagePath = $"ms-appdata:///local/SecondaryTiles/{WebUtility.UrlEncode("测试图片")}.png";
Using WebUtility.UrlEncode() in the link can solve this problem well, and the image will be recognized normally.
Another problem with unicode character is that, the SecondaryTile.Exists(tilename) will always return false.
This has nothing to do with Unicode, the main problem is your code:
if (SecondaryTile.Exists(tilename))
await tile.RequestDeleteAsync();
else
await tile.RequestCreateAsync();
Your code has a key problem. When it detects the Tile with the same id, it only deletes it, but does not create a new Tile, so it naturally returns false when it detects.
Best regards.

Flutter, How to get all the image file name from images folder?

I want to load all the image file names in images/pets/ to List<String> animals. How can I do that?
path_provider you can get the directory the temp and appDir directory
final directory = await getApplicationDocumentsDirectory();
String imagesDirectory = directory + "/images/pets/";
After you can use the listSync method to find files of this Directory
final myDir = new Directory(imagesDirectory);
List<FileSystemEntity> _images;
_images = myDir.listSync(recursive: true, followLinks: false);
I hope that I have helped in some way
Flutter generates a file called AssetManifest.json which you can read up through the default bundle the same way you would read a normal text file from the assets.
var manifestContent = DefaultAssetBundle.of(context).loadString('AssetManifest.json');
Read and parse this file and then create a list from all the properties you need with their paths. Just double check to make sure you have the correct path, this can change in the future. It seems to me like a placeholder.
Pseudo-code for reading AssetManifest.json
var manifestContent = DefaultAssetBundle.of(context).loadString('AssetManifest.json');
var manifestMap = json.decode(manifestContent);
var imagePetPaths = manifestMap.keys.where((key) => key.contains('images/pets/'));
// You can either use the keys and fetch the value from the map,
or just use the key value since it's the same as the one in the pubspec.yaml
Continuing from AdsHan's Answer
final dir = await getApplicationDocumentsDirectory();
final imagesDirectory = Directory(dir.path + "/images/pets/");
List<String> images = [];
final _imagesFile = imagesDirectory.listSync(followLinks: false, recursive: true);
_imagesFile.forEach((img) {
String imgString = img.toString().substring(
img.toString().lastIndexOf('/') + 1,
img.toString().length);
images.add(imgString);
});

MongoDB 3.2 C# driver version 2.2.3.3 Gridfs Download large files more than 2gb

I am uploading files using the following code:
using (var s = File.OpenRead(#"C:\2gbDataTest.zip"))
{
var t = Task.Run<ObjectId>(() =>
{
return fs.UploadFromStreamAsync("2gbDataTest.zip", s);
});
return t.Result;
}
//works for the files below 2gb
var t1 = fs.DownloadAsBytesAsync(id);
Task.WaitAll(t1);
var bytes = t1.Result;
I am getting error
I am new to MongoDb and C#, can any one please show me how to download files greater than 2GB in size?
You are hitting the limit in terms of the size a byte array (kept in memory) download can be, so your only choice is to use a Stream instead like you are doing when you upload, something like (with a valid destination):
IGridFSBucket fs;
ObjectId id;
FileStream destination;
await fs.DownloadToStreamAsync(id, destination);
//Just writing complete code for others, This will work ;
//Thanks to "Adam Comerford"
var fs = new GridFSBucket(database);
using (var newFs = new FileStream(filePathToDownload, FileMode.Create))
{
//id is file objectId
var t1 = fs.DownloadToStreamAsync(id, newFs);
Task.WaitAll(t1);
newFs.Flush();
newFs.Close();
}