Misbehavior with sharedpreferences - java

Before you judge me, I'd like to say I read theese:
Saving a List of Strings in Android with SharedPreferences
Misbehavior when trying to store a string set using SharedPreferences
getString(String key, String defValue) - Reference
But I still can't understand, can't get things work. I get totally misbehavior of my preferences. My code:
public static SharedPreferences sharedAppPreferences;
public static final String AppsListKey = "AppListKey";
public static final String AppsPreferences = "AppsPreferences";
public static ArrayList<String> packageNames;
public void chooseApps(View view) {
sharedAppPreferences = getSharedPreferences(AppsPreferences, Context.MODE_PRIVATE);
if (sharedAppPreferences.contains(AppsListKey)) {
Set<String> buffer = new LinkedHashSet<String>(sharedAppPreferences.getStringSet(AppsListKey, new LinkedHashSet<String>()));
packageNames = new ArrayList<String>(buffer);
} else {
packageNames = new ArrayList<String>();
}
PackageManager packageManager = getPackageManager();
int flags = PackageManager.GET_META_DATA | PackageManager.GET_SHARED_LIBRARY_FILES | PackageManager.GET_UNINSTALLED_PACKAGES;
List<ApplicationInfo> packageList = packageManager.getInstalledApplications(flags);
for (ApplicationInfo pack : packageList) {
if (((pack.flags & ApplicationInfo.FLAG_SYSTEM) == 1) || packageNames.contains(pack.loadLabel(packageManager).toString())) {
// System application or already in array
} else {
// Installed by user and isnt in array
packageNames.add(pack.loadLabel(packageManager).toString());
}
}
Editor editor = sharedAppPreferences.edit();
Set<String> buffer1 = new LinkedHashSet<String> (packageNames);
editor.putStringSet(AppsListKey, buffer1);
editor.commit();
//packageNames.clear();
//buffer1.clear();
buffer1 = new LinkedHashSet<String>(sharedAppPreferences.getStringSet(AppsListKey, new LinkedHashSet<String>()));
packageNames = new ArrayList<String>(buffer1);
AppList appList = new AppList();
appList.show(getSupportFragmentManager(), "AppList");
}
Why first time I run my app I get list like
[Skype, Facebook, Whatsapp, Twitter, Google+]
It's ok as long as app is running... But if I kill my app and restart I get now totally different list like
[Whatsapp, Google+, Skype, Twitter, Facebook]
Could someone explain me please what is here wrong?

The only difference in your list before and after, is the ordering...
To expand on what I have been talking about, I just realised your mistake..
LinkedHashSet is ordered. However, you are storing in
Set<String> buffer
Set<String> is not ordered...
So it jumbles it up again.
You need to store it in parameter of LinkedHashSet like below
LinkedHashSet<String> buffer = new LinkedHashSet<String>(sharedAppPreferences.getStringSet(AppsListKey, new LinkedHashSet<String>()));
(There are two occasions i see this needs to be changed. )
Edit:
One final thing you can do to help, is rather than create a new list, cast the existing one from shared prefs ...
LinkedHashSet<String> buffer = (LinkedHashSet<String>)sharedAppPreferences.getStringSet(AppsListKey, new LinkedHashSet<String>());
There are alternatives to HashSets here

Related

Store String Key-value pair

I am developing an android app, the main work of app is there is a scanner and i have to scan again & again and store result in key value pair.
[
{
"0" : "816444014066",
"1" : "747083010945",
"2" : "816444010969"
}
]
and by API i have to send all the scan result by array.
I am getting scan result by another activity by startActivityForResult.User will scan again and again and by onActivityResult user will get result.i have to store all the result in key value pair and finally there is a button by tap on button by POST request i have to send all the scan result by array like above code.
Can i use here HashMap or i have to use Shared Preferences for storing result.
// Call Back method to get the Message form other Activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// check if the request code is same as what is passed here it is 2
if (requestCode == 2 && data!=null) {
String message = data.getStringExtra(SCAN_RESULT);
// textView1.setText(message);
if(message!= null){
Log.e("SCAN_RESULT", "" + message);
//Adding code will be here
}
}
}
here is the sample code for saving key-values with hashmap :
HashMap<String, String> data = new HashMap<String, String>();
data.put("key", "value");
or if the order matters to you use linkedHashMap :
HashMap<String, String> data = new LinkedHashMap<>();
the usage is the same;)
Data Structure Logic:
Hashmaps are used to access the content via its key.
In this sample, I guess you are scanning 'tuples' one by one and each tuple is different from other, so you won't need to access an old tuple via it's key.
So here, I suggest you to create the model class suitable for the key-value pairs and store them in a list. You can push that list when you are done.
Sample model for tuple:
public class KeyValuePair {
private String key;
private String value;
public KeyValuePair(String key, String value) {
this.key = key;
this.value = value;
}
}
Sample List to store:
List<KeyValuePair> keyValuePairList = new ArrayList<>();
keyValuePairList.add(new KeyValuePair("0", "816444014066"));
keyValuePairList.add(new KeyValuePair("1", "747083010945"));
keyValuePairList.add(new KeyValuePair("2", "816444010969"));
Storing:
If you cannot pass the data between activities, check out SQLite. You can store the data in SQLite and fetch it when needed. It is an offline database works on Android devices. You can delete the data when pushed to upstream.
Edit:
If the keys are the orders, you can simply use a String List like this:
List<String> keyValuePairList = new ArrayList<>();
keyValuePairList.add("816444014066");
keyValuePairList.add("747083010945");
keyValuePairList.add("816444010969");
Use hashmap to store the data and then use Gson to convert HashMap to String and then save it to SharedPrefs
private void hashmaptest()
{
//create test hashmap
HashMap<String, String> testHashMap = new HashMap<String, String>();
testHashMap.put("key1", "value1");
testHashMap.put("key2", "value2");
//convert to string using gson
Gson gson = new Gson();
String hashMapString = gson.toJson(testHashMap);
//save in shared prefs
SharedPreferences prefs = getSharedPreferences("test", MODE_PRIVATE);
prefs.edit().putString("hashString", hashMapString).apply();
//get from shared prefs
String storedHashMapString = prefs.getString("hashString", "oopsDintWork");
java.lang.reflect.Type type = new TypeToken<HashMap<String, String>>(){}.getType();
HashMap<String, String> testHashMap2 = gson.fromJson(storedHashMapString, type);
//use values
String toastString = testHashMap2.get("key1") + " | " + testHashMap2.get("key2");
Toast.makeText(this, toastString, Toast.LENGTH_LONG).show();
}
Source : Saving a hash map into Shared Preferences
Well, if you want to save the stored key-value in case the user closed the app then you will need to use one of: sqllite, file, sharedprefernces. But if the user closed the app and restart it then its gonna be new (key-value)s then you just simply use HashMap something like this:
Map <Integer,String> hashMap = new HashMap<Integer,String>();
After scan result i have created a method in i'm adding in HashMap all the scan results one by one.
LinkedHashMap<String, String> data = new LinkedHashMap<String, String>();
// Call Back method to get the Message form other Activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// check if the request code is same as what is passed here it is 2
if (requestCode == 2 && data!=null) {
String message = data.getStringExtra(SCAN_RESULT);
if(message!= null){
Log.e("SCAN_RESULT", "" + message);
showBarCodeContentDialoig(message);
storeScanValue(scanResult);
}
}
}
out side of onCreate();
private void storeScanValue(String scanResult) {
count++;
data.put(String.valueOf(count), scanResult);
Log.e("Key_Value",""+count);
Log.e("SIZE",""+data.size());
}
For sending result one Activity to another:
Gson gson = new Gson();
String list = gson.toJson(data);
Intent intent = new Intent(AdjustInventoryCount.this, AdjustInventory.class);
intent.putExtra("list", list);
startActivity(intent);
for receiving data from previous activity:
String str= getIntent().getStringExtra("list");
Gson gson = new Gson();
Type entityType = new TypeToken< LinkedHashMap<String, String>>(){}.getType();
data = gson.fromJson(str, entityType);
String jsonList = gson.toJson(data, LinkedHashMap.class);
Log.e("list", ""+jsonList);
Log.e("Size", ""+data.size());
By this way i got original sequence wise result as stored in LinkedHashMap.
For this it's better to use a HashMap to store non-persistent data. You don't need to Shared Preferences since you are posting the results, so no need for persistent storage.
Something like this:
Map <Integer,Integer> myMap = new HashMap<Integer,Integer>();
If you need the scan results somewhere else in your application, I suggest you should use SharedPreferences and put the key value pairs.
Otherwise just use a HashMap.
Suggestion: if you need to keep an order of key value pairs, use LinkedHashMap and iterate over it.
if you are using Integer as key, its better to use SparseArray over HashMap as it stores data using primitive keys and will be faster than hashMap.
SparseArray<String> spa = new SparseArray();
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// check if the request code is same as what is passed here it is 2
if (requestCode == 2 && data!=null) {
String message = data.getStringExtra(SCAN_RESULT);
// textView1.setText(message);
if(message!= null){
//Adding code will be here
spa.put(key,value);
}
}
}
SharedPreferences are used to store small data, so I recommend to you to store it on a File and read it later... (if your data is big)
You first create an Object, for instance a HashMap<String,String> as follows :
HashMap<String, String> data = new HashMap<String, String>();
data.put("0", "816444014066");
...
Now you can create those methods to store the information :
public static synchronized void saveData(Context context, Object object, String filename) {
try {
String tempPath = context.getFilesDir() + "/" + filename+ ".bin";
File file = new File(tempPath);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(object);
oos.flush();
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
And then if you want to read the data, you simply do that :
public static synchronized Object readData(Context context, String filename) {
Object obj = new Object();
try {
String tempPath = context.getFilesDir() + "/" + binFileName + ".bin";
File file = new File(tempPath);
if (file.exists()) {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
obj = ois.readObject();
ois.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}

Implementing save/open with RichTextFX?

Here is my code:
private void save(File file) {
StyledDocument<ParStyle, Either<StyledText<TextStyle>, LinkedImage<TextStyle>>, TextStyle> doc = textarea.getDocument();
// Use the Codec to save the document in a binary format
textarea.getStyleCodecs().ifPresent(codecs -> {
Codec<StyledDocument<ParStyle, Either<StyledText<TextStyle>, LinkedImage<TextStyle>>, TextStyle>> codec
= ReadOnlyStyledDocument.codec(codecs._1, codecs._2, textarea.getSegOps());
try {
FileOutputStream fos = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(fos);
codec.encode(dos, doc);
fos.close();
} catch (IOException fnfe) {
fnfe.printStackTrace();
}
});
}
I am trying to implement the save/loading from the demo from here on the RichTextFX GitHub.
I am getting errors in the following lines:
StyledDocument<ParStyle, Either<StyledText<TextStyle>, LinkedImage<TextStyle>>, TextStyle> doc = textarea.getDocument();
error: incompatible types:
StyledDocument<Collection<String>,StyledText<Collection<String>>,Collection<String>>
cannot be converted to
StyledDocument<ParStyle,Either<StyledText<TextStyle>,LinkedImage<TextStyle>>,TextStyle>
and
= ReadOnlyStyledDocument.codec(codecs._1, codecs._2, textarea.getSegOps());
error: incompatible types: inferred type does not conform to equality
constraint(s) inferred: ParStyle
equality constraints(s): ParStyle,Collection<String>
I have added all the required .java files and imported them into my main code. I thought it would be relatively trivial to implement this demo but it has been nothing but headaches.
If this cannot be resolved, does anyone know an alternative way to save the text with formatting from RichTextFX?
Thank you
This question is quite old, but since i ran into the same problem i figured a solution might be useful to others as well.
In the demo, the code from which you use, ParStyle and TextStyle (Custom Types) are used for defining how information about the style is stored.
The error messages you get pretty much just tell you that your way of storing the information about the style (In your case in a String) is not compatible with the way it is done in the demo.
If you want to store the style in a String, which i did as well, you need to implement some way of serializing and deserializing the information yourself.
You can do that, for example (I used an InlineCssTextArea), in the following way:
public class SerializeManager {
public static final String PAR_REGEX = "#!par!#";
public static final String PAR_CONTENT_REGEX = "#!pcr!#";
public static final String SEG_REGEX = "#!seg!#";
public static final String SEG_CONTENT_REGEX = "#!scr!#";
public static String serialized(InlineCssTextArea textArea) {
StringBuilder builder = new StringBuilder();
textArea.getDocument().getParagraphs().forEach(par -> {
builder.append(par.getParagraphStyle());
builder.append(PAR_CONTENT_REGEX);
par.getStyledSegments().forEach(seg -> builder
.append(
seg.getSegment()
.replaceAll(PAR_REGEX, "")
.replaceAll(PAR_CONTENT_REGEX, "")
.replaceAll(SEG_REGEX, "")
.replaceAll(SEG_CONTENT_REGEX, "")
)
.append(SEG_CONTENT_REGEX)
.append(seg.getStyle())
.append(SEG_REGEX)
);
builder.append(PAR_REGEX);
});
String textAreaSerialized = builder.toString();
return textAreaSerialized;
}
public static InlineCssTextArea fromSerialized(String string) {
InlineCssTextArea textArea = new InlineCssTextArea();
ReadOnlyStyledDocumentBuilder<String, String, String> builder = new ReadOnlyStyledDocumentBuilder<>(
SegmentOps.styledTextOps(),
""
);
if (string.contains(PAR_REGEX)) {
String[] parsSerialized = string.split(PAR_REGEX);
for (int i = 0; i < parsSerialized.length; i++) {
String par = parsSerialized[i];
String[] parContent = par.split(PAR_CONTENT_REGEX);
String parStyle = parContent[0];
List<String> segments = new ArrayList<>();
StyleSpansBuilder<String> spansBuilder = new StyleSpansBuilder<>();
String styleSegments = parContent[1];
Arrays.stream(styleSegments.split(SEG_REGEX)).forEach(seg -> {
String[] segContent = seg.split(SEG_CONTENT_REGEX);
segments.add(segContent[0]);
if (segContent.length > 1) {
spansBuilder.add(segContent[1], segContent[0].length());
} else {
spansBuilder.add("", segContent[0].length());
}
});
StyleSpans<String> spans = spansBuilder.create();
builder.addParagraph(segments, spans, parStyle);
}
textArea.append(builder.build());
}
return textArea;
}
}
You can then take the serialized InlineCssTextArea, write the resulting String to a file, and load and deserialize it.
As you can see in the code, i made up some Strings as regexes which will be removed in the serialization process (We don't want our Serializer to be injectable, do we ;)).
You can change these to whatever you like, just note they will be removed if used in the text of the TextArea, so they should be something users wont miss in their TextArea.
Also note that this solution serializes the Style of the Text, the Text itself and the Paragraph style, BUT not inserted images or parameters of the TextArea (such as width and height), just the text content of the TextArea with its Style.
This issue on github really helped me btw.

Java StreamCorruptedException attempting deserialize the object read from SharedPreferences Android

I'm trying to serialize an object from within it and deserialize it using this answer: Reliably convert any object to String and then back again
But I get StreamCorruptedException while deserializing.
java.io.StreamCorruptedException
W/System.err: at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:2065)
W/System.err: at java.io.ObjectInputStream.<init>(ObjectInputStream.java:371)
W/System.err: at ShoppingCart.load(ShoppingCart.java:154)
Here is the Class :
public class ShoppingCart implements Serializable {
ArrayList<Item> items ;
String token ;
transient Context context ;
public ShoppingCart(Context cntx){
context = cntx ;
items = new ArrayList<Item>();
SharedPreferences preferences = context.getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
token = preferences.getString("login_token", null);
}
public void emptyCart(){
items = new ArrayList<Item>();
store();
System.gc();
}
public boolean addToCart(Item item){
boolean exists = false ;
for(int i = 0 ; i < items.size() ; i++){
if(items.get(i).productID.equals(item.productID)){
exists = true ;
return false ;
}
}
if(!exists)
items.add(item);
store();
return true ;
}
public void removeFromCart(Item item){
items.remove(item);
store();
}
public void store() {
SharedPreferences.Editor editor =
context.getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
// serialize the object
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream so = new ObjectOutputStream(bo);
so.writeObject(this);
so.flush();
String serializedObject = bo.toString();
editor.putString("stored_cart", serializedObject);
editor.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
public ShoppingCart load() {
SharedPreferences preferences = context.getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
String serializedObject = preferences.getString("stored_cart", null);
ShoppingCart newCart = null ;
// deserialize the object
try {
byte b[] = serializedObject.getBytes();
ByteArrayInputStream bi = new ByteArrayInputStream(b);
ObjectInputStream si = new ObjectInputStream(bi);
newCart = (ShoppingCart) si.readObject();
newCart.context = context ;
} catch (Exception e) {
e.printStackTrace();
}
return newCart ;
}
}
I'm calling the load() function like this:
cart = new ShoppingCart(getApplicationContext());
SharedPreferences preferences =
getApplicationContext().getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
if(preferences.getString("stored_cart", null) != null) {
cart = cart.load();
Log.d("AppController","cart loaded");
}
Since the Context is not serilizable, so I made it transient.
What am I doing wrong ?
Firstly, from what I see, you cannot put a serializable into sharedprefs.
I tried saving to a database using a string value and convert it back and to a byte array. (I can store byte arrays as a blob in a database). When I used a String, the byte array got the wrong format which triggered the same exception you have right there: StreamCorrupedException
When I got this error and did research, what I got from it was that a StreamCorruptedException means you do something "bad" with the stream, that screws up the format.
Now, for the solution.
When I tried this, saved as a string and loaded back as a byte array, the different bytes aren't necessarily loaded back in the same format as they are saved. This is when you get the exception. You try to load a byte array from a String, but when you apply the byte array to a class it ends up as a corrupted byte array.
Basically, DO NOT SAVE IT AS A STRING AND CONVERT IT TO A BYTE ARRAY! What I did to be able to save was to actually save it as a byte array, and I use a database and databases support this. But from what I see, shared prefs do not. So basically, you cannot use a String and convert it to a byte array to save and then load. You have to use internal/external storage(basically files) or use a database with mode set to blob. But Shared Prefs simply do not support byte arrays which means when you convert the string to a byte array, it changes the stream and corrupts the data.
So you have three options:
Store as file (internal/external)
Store in database as blob
Save each individual item in the cart as an individual item in the shared prefs.
(ANd make sure item is serializable as well, to prevent exceptions there later).
TL:DR; When you save the serializable class as a String, but convert it back to a byte array will give this error.
TEST CASE
The following test works on both Android and desktop Java. This testing was done using a Gradle project, but you can go to apache commons and find a different dependency depending on your project. The dependency is used for converting back and forth between byte array and class.
Required dependency for testing:
compile 'org.apache.commons:commons-lang3:3.5'
Sample class:
public class Something implements Serializable{
public static final long serialVersionUID = 0L;
int x = 12;
}
Sample test:
Something instance = new Something();
String class_ = SerializationUtils.serialize(instance).toString();
byte[] bytes = class_.getBytes();
instance = (Something) SerializationUtils.deserialize(bytes);
Output:
Exception in thread "main" org.apache.commons.lang3.SerializationException: java.io.StreamCorruptedException: invalid stream header: 5B424036
at org.apache.commons.lang3.SerializationUtils.deserialize(SerializationUtils.java:229)
at org.apache.commons.lang3.SerializationUtils.deserialize(SerializationUtils.java:265)
at com.core.Launcher.main(Launcher.java:22)
Caused by: java.io.StreamCorruptedException: invalid stream header: 5B424036
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:857)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:349)
at org.apache.commons.lang3.SerializationUtils.deserialize(SerializationUtils.java:221)
... 2 more
Process finished with exit code 1
In my testing, this throws StreamCorruptedException, which basically shows one thing: You cannot convert a class to byte a byte array, then to a String and back to byte array
Note: This test case was executed on a WIndows 10 computer and Android 7(S6 edge), and it threw the same error (stacktrace changes because of there being two different projects).
Summary:
Saving and loading a byte array works fine. Where saving and loading a byte array involves a String in the middle, it corrupts the stream.
Solution:
Don't save with a String part to be able to save on an unsupported platform. That platform in this case being Sharedprefs. Use files or a database (with a blob field) are the only ways to save a byte array locally on a device in Android. Transferring data over the internet is an entirely different topic I am not going to cover.
So in order to serialize and deserialize with bytes, you have to save it as a file, or in a database. Converting back and forth between a string is what gives you the problems.
And finally, this error has nothing to do with an unserializable field. That throws a different error(NotSerializableException).

Android - Compare strings from Intent

This has to be a really easy answer. I've been searching and searching on how to compare a variable to a string in Java. I have an Intent and only want to declare some vars if data from the intent matches. Surely this can't be that hard. Java is frustrating to me. :)
I know that type will equal message at some point but it doesn't work.
e.g.
String type = intent.getStringExtra("type");
if(type.equals("message")){
String msg = intent.getStringExtra("message");
String avatar = intent.getStringExtra("photo");
count = Integer.parseInt(intent.getStringExtra("count"));
Bitmap photo = getBitmapFromURL(avatar);
String theMessage = Html.fromHtml(msg).toString().replace("\\", "");
}
EDIT:
I did output type to log as suggested and it does show message like it should. I am trying to us the same variable theMessage and photo but it complains that its not declared so it prompts a fix and puts this at the top. Is this what's causing it not to work? This is a notification by the way.
private static String theMessage = null;
private static Bitmap photo = null;
I try to do this later in the code but it complains about not being declared.
if(type.equals("message")){
notification.setSubText(theMessage);
notification.setLargeIcon(photo);
}
So that is what I have and with the static vars it doesn't work at all even after the error of not being declared goes away.
Try instead
Bundle extras = intent.getExtras();
String type = extras.getString("type");
Log.i("type", type);
if(type.equals("message")){
String msg = extras.getString("message");
String avatar = extras.getString("photo");
count = Integer.parseInt(extras.getString("count"));
Bitmap photo = getBitmapFromURL(avatar);
String theMessage = Html.fromHtml(msg).toString().replace("\\", "");
}
and see the logCat what comes against type.
Hope it helps.

Java CSV Reader/Writer Questions

I have some questions regarding reading and writing to CSV files (or if there is a simpler alternative).
Scenario:
I need to have a simple database of people and some basic information about them. I need to be able to add new entries and search through the file for entries. I also need to be able to find an entry and modify it (i.e change their name or fill in a currently empty field).
Now I'm not sure if a CSV reader/writer is the best route or not? I wouldn't know where to begin with SQL in Java but if anyone knows of a good resource for learning that, that would be great.
Currently I am using SuperCSV, I put together a test project based around some example code:
class ReadingObjects {
// private static UserBean userDB[] = new UserBean[2];
private static ArrayList<UserBean> arrUserDB = new ArrayList<UserBean>();
static final CellProcessor[] userProcessors = new CellProcessor[] {
new StrMinMax(5, 20),
new StrMinMax(8, 35),
new ParseDate("dd/MM/yyyy"),
new Optional(new ParseInt()),
null
};
public static void main(String[] args) throws Exception {
ICsvBeanReader inFile = new CsvBeanReader(new FileReader("foo.csv"), CsvPreference.EXCEL_PREFERENCE);
try {
final String[] header = inFile.getCSVHeader(true);
UserBean user;
int i = 0;
while( (user = inFile.read(UserBean.class, header, userProcessors)) != null) {
UserBean addMe = new UserBean(user.getUsername(), user.getPassword(), user.getTown(), user.getDate(), user.getZip());
arrUserDB.add(addMe);
i++;
}
} finally {
inFile.close();
}
for(UserBean currentUser:arrUserDB){
if (currentUser.getUsername().equals("Klaus")) {
System.out.println("Found Klaus! :D");
}
}
WritingMaps.add();
}
}
And a writer class:
class WritingMaps {
public static void add() throws Exception {
ICsvMapWriter writer = new CsvMapWriter(new FileWriter("foo.csv", true), CsvPreference.EXCEL_PREFERENCE);
try {
final String[] header = new String[] { "username", "password", "date", "zip", "town"};
String test = System.getProperty("line.seperator");
// set up some data to write
final HashMap<String, ? super Object> data1 = new HashMap<String, Object>();
data1.put(header[0], "Karlasa");
data1.put(header[1], "fdsfsdfsdfs");
data1.put(header[2], "17/01/2010");
data1.put(header[3], 1111);
data1.put(header[4], "New York");
System.out.println(data1);
// the actual writing
// writer.writeHeader(header);
writer.write(data1, header);
// writer.write(data2, header);
} finally {
writer.close();
}
}
}
Issues:
I'm struggling to get the writer to add a new line to the CSV file. Purely for human readability purposes, not such a big deal.
I'm not sure how I would add data to an existing record to modify it. (remove and add it again? Not sure how to do this).
Thanks.
Have you considered an embedded database like H2, HSQL or SQLite? They can all persist to the filesystem and you'll discover a more flexible datastore with less code.
The easiest solution is to read the file at application startup into an in-memory structure (list of UserBean, for example), to add, remove, modify beans in this in-memory structure, and to write the whole list of UserBean to the file when the app closes, or when the user chooses to Save.
Regarding newlines when writing, the javadoc seems to indicate that the writer will take care of that. Just call write for each of your user bean, and the writer will automatically insert newlines between each row.

Categories