Methods of Data Storage - Opinion - java

I have been working on an app and have encountered some limitations relating to my lack of experience in Java IO and data persistence. Basically I need to store information on a few Spinner objects. So far I have saved information on each Spinner into a text file using the format of:
//Blank Line
Name //the first drop-down entry of the spinner
Type //an enum value
Entries //a semicolon-separated list of the drop-down entry String values
//Blank line
And then, assuming this rigid syntax is followed always, I've extracted this information from the saved .txt whenever the app is started. But things such as editing these entries and working with certain aspects of the Scanner have been an absolute nightmare. If anything is off by even one line or space of blankness BAM! everything is ruined. There must be a better way to store information for easy access, something with some search-eability, something that won't be erased the moment the app closes and that isn't completely laxed in its layout to the extent that the most minor of changes destroys everything.
Any recommendations for how to save a simple String, a simple int, and an array of String outside the app? I am looking for a recommendation from an experienced developer here. I have seen the storage options, but am unsure which would be best for just a few simple things. Everything I need could be represented in a 3 X n table wherein n is the number of spinners.

Since your requirements are so minimal, I think the shared preferences approach is probably the best option. If your requirements were more complicated, then a using a database would start to make more sense.
Using shared preferences for simple data like yours really is as simple as the example shown on the storage options page.

Related

How do I store objects if I want to search them by multiple attributes later?

I want to code a simple project in java in order to keep track of my watched/owned tv shows, movies, books, etc.
Searching and retrieving the metadata from an API (themovieDB, Google Books) is already working.
How would I store some of this metadata together with user-input (like progress or rating)?
I'm planning on displaying the data in a table like form (example). Users should also be able to search the local data with multiple attributes. Is there any easy way to do this? I already thought about a database since it seemed that was the easiest solution.
Any suggestions?
Thanks in advance!
You can use lightweight database as H2, HSQLDB or SqlLite. These databases can be embedded in the Java app itself and does not require extra server.
If your data is less, you can also save it in XML or Json by using any XMLParser or JsonParser (e.g. Gson()).
Your DB table will have various attributes which are fetched from API as well as user inputs. You can write query on the top of these DBs to fetch and show the various results.
Either write everything to files, or store everything on a database. It depends on what you want though.
If you choose to write everything to files, you'll have to implement both the writing and the reading to suit your needs. You'll also have to deal with read/write bugs and performance issues yourself.
If you choose a database, you'll just have to implement the high level read and write methods, i.e., the methods that format the data and store it on the appropriate tables. The actual reading and writing is already implemented and optimized for performance.
Overall, databases are usually the smart choice. Although, be careful of which one you choose. Some types might be better for reading, while others are better for writting. You should carefully evaluate what's best, given your problem's domain.
There are many ways to accomplish this but as another user posted, a database is the clear choice.
However, if you're looking to make a program to learn with or something simple for personal use, you could also use a multi dimensional array of strings to hold the name of the program, as well as any other metadata fields and treat the array like a table in excel. This is not the best way to do it, but you can get away with it with very simple code. To search you would only need to loop through the array elements and check that the name of the program (i.e. movieArray[x][0] matches the search string. Once located you can perform actions or edit the other array indexes pertaining to that movie.
For a little more versatility, you would create a class to hold the movie information with fields to hold any metadata. The advantage here is that the metadata fields can be different types rather than having to conform to the array type, and their packaged together in the instance of the class. If you're getting the info from an API then you can update or create the classes from the API response. These objects can be stored in an ArrayList and searched with a loop that checks for a certain value i.e.
for (Movie M : movieArrayList){
if(m.getTitle().equals("Arrival")){
return m;
}
}
Alternatively of course for large scale, a database would be the best answer but it all depends what this is really for and what it's needs will be in the real world.

Extracting keywords from text in Android

Let us say, a user is typing text in an EditText. Now, as the user is typing, I want to extract the keywords from those texts.
For example, if user types- "I am having headache". It should extract "headache" as a keyword.
Please let me know how I can do this efficiently in Android.
Update: I do not know what the keywords are. They have to be extracted from the text which user enters.
First of all you should define what you will consider as keywords.
a. A limited list of words which are the keywords.
Or b. A limited list of words which are not the keywords.
That list can be in an ArrayList<String> in your code.
When the user changes the text in the EditText (see EditText.addTextChangedListener(new TextWatcher(){...}), you get the text and split() it into a String [] using space character as a delimiter. Next search each word in the array in your list (a or b options on top) either to check if they are or not there. When you get a hit you have found a keyword entered by the user.
The resulting keywords can be kept temporarily in another ArrayList<String> for you to use them after finishing the scanning of the input.
Note: I have proposed an ArrayList, to keep the list, considering that it won't be a long list. Fo more complex scenarios the list can be kept in HashMap or a TreeMap in the lines of what #Deepakkaku commented for the search to be quicker.
There can be two approaches to this problem:
Hardcoding the keywords or non-keywords you are interested in. #Juan's answer is the way to go here.
Second option is using some machine learnt model, which is what you are looking at, I guess given your machine-learning tag.
Option 1 requires a set of keywords defined ahead of time, which you say you don't have in your question. So this won't work in such a case. So here's a solution for Option 2.
Create a model.
You have to create a dataset of labeled examples.
You have to define a vocabulary for your entire dataset.
You have to define and train a model. If you have enough data, you can start from scratch. Otherwise, it is recommended to use transfer learning. For example, you can look up NLP models such as word2vec or sentiment analysis online and look up transfer learning. TF Hub makes it easy to do transfer learning.
Once you have trained the model, you have to workout how to convert that model so as to run efficiently on Android for inference. You have choices in Tensorflow-lite, Caffe2, etc. If you use Tensorflow, it is recommended that you convert to Tensorflow Lite for inference for efficiency.
You have to build your Android app with the appropriate runtime (TFLite, Caffe2, etc.) and bundle the model in. You can use ML Kit to take care of the download for you if you don't want to bundle.
Add the hooks to model in your activity by listening to changes in your EditText and calling the model inference. You likely want the model interpreter to be loaded ahead of time before the first inference call for efficiency.

Java save simple Data

i need to save data from an java desktop application. The main part of the Data are the texts of around 50 labels. Which are spread over 5 Java GUI-classes. The Rest are some simple application settings.
Now i am quit unsure about how to safe these data. A friend told me to use Random access Data and to write some kind of "serializable" object. At the moment i am using a .txt and a fileReader/writer. But this seemes impractical for 50-100 Data if your want to search the position in the .txt by every update. This is my same problem with random access data.
i thought about using some kind of embedded DB like "h2" but i dont now if this is to much and too complicated for such a small programm.
An other question is how do i put the text of all labels at the programm start. one way i am thinking about is to have a big list of all labels with determind positions and after reading the data from whatever to go over this list and set the labes. An other way would be to give every Label an id.
But maybe there is a much better way. But i dont now how to access the labels by names read from the data.
For saving serializable objects. Can i safe all the gui-object or do i need to combine se data in one class?
maybe someone could give a nice advise =)
For such a small number of labels, I would just keep all data in memory. On app initialization load the file and on every edit write the entire file from scratch
(If you are concerned about reliability in the face of power loss and random crashes during write you need to be careful here. For example, write the new data to a different file, fsync() then atomically rename the new file to the desired filename.)
I'm not sure I understand your serialization problem -- but it seems like you have some sort of language translation layer that tells the gui elements what to display. If so, then yes - I would store the labels in a central class (say LablesMap) and have the other classes refer to data in that class using some constant keys. E.g.,
myButton.setText(labelsMap.get(CANCEL_BUTTON_LABEL)
where CANCEL_BUTTON_LABEL is some constant or enum value.

Organizing many texts by swapping instances

I am planning to develop an adventure-like game.
For that I am going to have a lot of instances of classes with different texts (basicly strings).
I dont want to hardcode this many texts, so i am looking for a way to do it better.
The guy in this video ( https://www.youtube.com/watch?v=8CDePunJlck ) is using json to write text files for each class instance manually and parse them automatically into instances. That goes into the right direction.
I´m looking for more information on that, so how is this procedure called?
Its said in the video that this also works with databases?
Is there a way to design a little bit more complex stuff with things like this?
E.g. I have the case that I would like to output different texts if e.g. a local or global variable is over a treshold etc. Can I do this without hardcoding and write an own class for each of my proposed instances?
Thank you!
Your question is quite broad, and it is hard to give a definitive answer. Here are some thoughts - hope you find it helpful.
You are right that you don't want to hardcode strings. The alternative to this is storing strings as external resources, and loading them into your game at start. There are numerous ways the resource can be organized; the choice depends on your programming platform, game architecture etc. For example, you can use simple name-value approach:
AREA_1_DESCRIPTION: You stand next o a small white house.
ITEM_22_DESTRUCTION: The nasty snake disappears with a loud "Bang!"
Using JSON or XML will give you more structured storage, which can be of great help, since you can organize your texts so that it is easier to use them in the code:
<item id="375" name="Great Sword">
<short_description>A Great Sword of Darkness</short_description>
<long_description>The sword has almost black blade with some unknown runes engraved</long_description>
</item>
If your programming system can access a database, then you can do something similar and store texts in the tables; this, however, might make it more difficult to edit texts later. If you want to go this way, I would still recommend using XML or JSON to store the texts, and making the game import texts in DB on the first run.
You probably will also need some sort of simple template-handling engine to be able to re-use some strings. You can start with creating your version of Java String.format() method. Your method might take as a first argument an ID of a string in your string catalog, and use some simple placeholders for the parameters. Suppose you have the following entry in your catalog:
FIRE_GEM_ACTION: "The Fire Gem touches %% and in %% seconds it turns into ashes."
Then you can write a method that will do something like this:
int delaySeconds = 5;
String message = MyTemplateProcessor.process(FIRE_GEM_ACTION, "old map", delaySeconds);
The function will take the string from the catalog, search for the occurrences of the placeholders (%%) and replace them sequentially with the parameters, so in the message you will get: The Fire Gem touches old map and in 5 seconds it turns into ashes.
In general, I would recommend you to have a look at some systems specially designed for creation of adventure games. Inform 7 will be a good starting place: http://inform7.com/learn/

sharing savegames between a demo and a full version in Android

I am currently developing an Android Game and my goal is to create a free/demo version of the game, so that the users can try it out. But I also want that the savegames from the demo are automatically imported in the full version.
The savegames I store in the applications private storage and they are basically JSON strings mapping several Java Objects. The user can create as many "new games" as he wants and there is an "auto save" and a "manual save" file for each game he started. To keep track of all the files, I have a list containing the filenames and some additional information (like the players name etc).
So basically there are quite a lot of small files handling the savegames. This may not be the most elegant approach, but it works quite well.
So here is my question: Lets say the user has started a game in the demo version (so there will be 3 files saved in the private storage of the demo version). How can I now access these files from within the full version?
The two versions won't be much different. They are actually the same, despite the limitations of the demo version. But I would be using the same code base.
I know there has been quite some questions about this issue in this forum and elsewhere, but I was not able to find a suitable solution. All I could find involved either:
storing the files in a world readable storage (like the SD-card) or
using the SharedPreferences
But I neither want the user to be able to read the savegames (or even alter it – because this could mess up the game) – so no sd-card, nor can I use the SharedPreferences, because each single savegame has approx. 200 lines of code (many many java objects translated into JSON) and mapping all those values and objects into some kind of key-value structure used for the SharedPreferences seems quite impossible to me.
Is this all messed up, or does anyone have an idea?
Thank you for taking the time, looking forward to hear your ideas!
Christoph
So I see just 2 Solutions:
The first is a WorldReadable SharedPreferences. You said, that you store JsonStrings, so there is no need to map them any further down, if you can make Objects out of your json-strings (I like to use Gson for this kind of work), you can simply store these
Strings inside SharedPreferences.
The second Way is to bother with ContentProviders and implement a ContentResolver interface. This is the safest way I can imagine for your use-case, but you have to implement a lot for it
What you can't avoid
There are two things that you can't avoid:
If the user decides to root the phone, you can't prevent a user from accessing it, doesn't matter what you do to make it harder.
If you want a second app to access the same data (the saved games) in a non rooted device, there would always be a away for user access it from outside your apps.
What can you do to make it harder
You can encrypt (i.e. using device IMEI) the data before store it in a file or shared preferences (together with a hash to prevent changes)
You can store the data in a SQLite database (would require more knowledge to change it), and encrypt before store it (even harder).
You can use SQLCipher to store it in a ciphered database (encryption will be transparent).
Regards.
You can use a shared Content Provider (here the general documentation about ContentProviders http://developer.android.com/guide/topics/providers/content-providers.html)
you then have to declare it as exportable using the flag: android:exported="true" in the manifest
example:
<provider android:name="[yourpackage_here].SavegameProvider"
android:authorities="[yourpackage_here].SavegameProvider"
android:exported="true" />
you will be able to open it within your new app.

Categories