How can I save an ArrayList to a file?
What am I doing wrong?
I have used this SO question to help me with Serializable objects.:
how to serialize ArrayList on android
and I used this SO question on how to write an array list:
Java - How Can I Write My ArrayList to a file, and Read (load) that file to the original ArrayList?
However when I attempt to write the to the file I get the error:
java.io.NotSerializableException: at
java.io.ObjectOutputStream.writeObject at
com.mycompany.MyClass.saveData
Here is MyClass that attempts to save the file
private ArrayList < MyCustomObject > arrayList;
private File dataFile;
private String FILE_NAME = "FILE_DATA.dat";
public void init(final Context context) {
this.appContext = context;
dataFile = new File(appContext.getFilesDir(), FILE_NAME);
if (dataFile.exists()) {
loadData();
} else {
try {
dataFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
arrayList = new ArrayList < MyCustomObject > ();
saveData();
}
}
private void saveData() {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(dataFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fos != null) {
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(fos);
if (oos != null) {
oos.writeObject(arrayList);
}
assert oos != null;
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void loadData() {
FileInputStream fis = null;
try {
fis = new FileInputStream(dataFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fis != null) {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(fis);
if (ois != null) {
try {
arrayList = (ArrayList < MyCustomObject > ) ois.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else {
}
assert ois != null;
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Here is MyCustomObject
public class MyCustomObject implements Serializable {
public String myname = "";
public String someOtherItem = "";
public int aNumber = 0;
public MyCustomObject getCustomObject() {
return this;
}
}
Replace this method
public MyCustomObject MyCustomObject() {
return this;
}
in your MyCustomObject class and your code should work fine. Use something like
public MyCustomObject getMyCustomObject() {
return this;
}
Because the way you name your method is conflicting wit the default constructor that java creates for MyCustomObject class when you do not provide a constructor yourself. I assume that you are using this method to be able to add an instance of MyCustomObject to your array list: you don't really need such a method but with the proper naming you can still use it.
You should also put sample datas in your ArrayList before saving it to the disk by calling the saveData() method.
Here is an illustration from your code that works. I am not sure what your Context object is exactly but your are using it to get access to the file path, so to get things going I just used a particular file path.
public class MyClass {
private ArrayList < MyCustomObject > arrayList;
private File dataFile;
private String FILE_NAME = "FILE_DATA.dat";
public void init(final Context context) {
dataFile = new File("C:\\lompo\\file1.txt");
if (dataFile.exists()) {
loadData();
} else {
try {
dataFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
arrayList = new ArrayList < MyCustomObject > ();
MyCustomObject obj1 = new MyCustomObject();
obj1.aNumber = 125;
obj1.myname = "HIS NAME";
arrayList.add(obj1);
saveData();
}
}
public static void main(String[] args) {
MyClass myClazz = new MyClass();
myClazz.init(null);
System.out.println("Arraylist has " + myClazz.arrayList.size() + " elements");
}
private void saveData() {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(dataFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fos != null) {
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(fos);
if (oos != null) {
oos.writeObject(arrayList);
}
assert oos != null;
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void loadData() {
FileInputStream fis = null;
try {
fis = new FileInputStream(dataFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fis != null) {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(fis);
if (ois != null) {
try {
arrayList = (ArrayList < MyCustomObject > ) ois.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else {
}
assert ois != null;
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
As you can see in the code, the first run of the main method will save the file on disk with an arrayList populated by one object. The second run reads from the file and then I printed the number of elements and the infos that I have saved before: the picture illustrates the result
Related
I have may wifi2.txt file in my assets file directory in Android Studio. However, I keep getting a NULLPointException when I try to access it. My code is below: (Thanks so much in advance)
//CSV FILE READING
File file = null;
try {
FileInputStream is = new FileInputStream(file);
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(getAssets().open("wifi2.txt")));
String line;
Log.e("Reader Stuff",reader.readLine());
while ((line = reader.readLine()) != null) {
Log.e("code",line);
String[] RowData = line.split(",");
LatLng centerXY = new LatLng(Double.valueOf(RowData[1]), Double.valueOf(RowData[2]));
if (RowData.length == 4) {
mMap.addMarker(new MarkerOptions().position(centerXY).title(String.valueOf(RowData[0]) + String.valueOf(RowData[3])).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
}
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//Done with CSV File Reading
In Kotlin, we can achieve this :-
val string = requireContext().assets.open("wifi2.txt").bufferedReader().use {
it.readText()
}
File file = null;
try {
FileInputStream is = new FileInputStream(file);
Actually you are not using FileInputStream anywhere. Just use this piece of code
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(getAssets().open("wifi2.txt")));
String line;
Log.e("Reader Stuff",reader.readLine());
while ((line = reader.readLine()) != null) {
Log.e("code",line);
String[] RowData = line.split(",");
LatLng centerXY = new LatLng(Double.valueOf(RowData[1]), Double.valueOf(RowData[2]));
if (RowData.length == 4) {
mMap.addMarker(new MarkerOptions().position(centerXY).title(String.valueOf(RowData[0]) + String.valueOf(RowData[3])).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
Method to read a file FROM assets:
public static String readFile(AssetManager mgr, String path) {
String contents = "";
InputStream is = null;
BufferedReader reader = null;
try {
is = mgr.open(path);
reader = new BufferedReader(new InputStreamReader(is));
contents = reader.readLine();
String line = null;
while ((line = reader.readLine()) != null) {
contents += '\n' + line;
}
} catch (final Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ignored) {
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException ignored) {
}
}
}
return contents;
}
Usage: String yourData = LoadData("wifi2.txt");
Where wifi2.txt is assumed to reside in assets
public String LoadData(String inFile) {
String tContents = "";
try {
InputStream stream = getAssets().open(inFile);
int size = stream.available();
byte[] buffer = new byte[size];
stream.read(buffer);
stream.close();
tContents = new String(buffer);
} catch (IOException e) {
// Handle exceptions here
}
return tContents;
}
Reference
My solution using kotlin to load text from asset file
object AssetsLoader {
fun loadTextFromAsset(context: Context, file: String): String {
return context.assets.open(file).bufferedReader().use { reader ->
reader.readText()
}
}
}
use it like this:
val text = AssetsLoader.loadTextFromAsset(context, "test.json")
This question already has answers here:
How to write data with FileOutputStream without losing old data?
(2 answers)
Closed 5 years ago.
I am writing to a stream file in Java. I have read if I want to append I need to override WriteStreamHeader. But even after doing so, I am not able to get free from StreamCorruptedException.
class AppendingObjectOutputStream extends ObjectOutputStream {
public AppendingObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
protected void writeStreamHeader() throws IOException {
reset();
}
}
class Student implements Operations,Serializable
{
private static final long serialVersionUID = 1L;
private int studid;
private String sname;
private int sage;
private long contact;
public Student()
{
studid = 0;
sname = null;
sage = 0;
contact = 0;
}
public void add(Scanner sc)
{
System.out.print("Enter student id: ");
studid = Integer.parseInt(sc.nextLine());
System.out.print("Enter student name: ");
sname = sc.nextLine();
System.out.print("Enter student age: ");
sage = Integer.parseInt(sc.nextLine());
System.out.print("Enter student's contact number: ");
contact=Long.parseLong(sc.nextLine());
}
public void show()
{
System.out.println("Student's details:");
System.out.println("Id no: "+studid);
System.out.println("Name :" + sname);
System.out.println("Age :" + sage);
System.out.println("Contact No. :" + contact);
}
}
class Admin
{
public void addstu(Scanner sc)
{
try
{
Student s = new Student();
s.add(sc);
boolean b = true;
FileInputStream fis = null;
try{
fis = new FileInputStream("student.ser");
fis.close();
}
catch (FileNotFoundException e)
{
b = false;
}
FileOutputStream fos = new FileOutputStream("student.ser");
ObjectOutputStream oos =null;
if(b == true)
{
System.out.println("Appending objects");
oos = new AppendingObjectOutputStream(fos);
}
else
{
System.out.println("Writing objects");
oos = new ObjectOutputStream(fos);
}
oos.writeObject(s);
oos.close();
fos.close();
System.out.println("Student successfully inserted");
fis = new FileInputStream("student.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
Student result = (Student) ois.readObject();
result.show();
ois.close();
fis.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void displayallstu()
{
try
{
FileInputStream fis = new FileInputStream("student.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
System.out.println("Student's List");
try{
while(true)
{
Student result = (Student) ois.readObject();
result.show();
}
}
catch (EOFException e) {
System.out.println("!!End of file!!");
}
finally{
ois.close();
fis.close();}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
It is called from main and executes properly when addstu() is called for the first time, but when called for next time, displays Successfully Inserted message, but throws exception while reading.
java.io.StreamCorruptedException: invalid stream header: 79737200
What you first generate is:
stream header
student
Then you are overwriting this with:
reset
student
which cannot be read since you’re missing the stream header. You want the following in the file:
stream header
student
reset
student
To get this, you will need to open the output stream in append mode after the file has been created the first time. Since you already have a Boolean indicating if this is necessary, just pass that to the constructor:
FileOutputStream fos = new FileOutputStream("student.ser", b);
I'm trying to add extra training data to my nl-personTest.bin file with OpenNLP.
Now is my problem that when I run my code to add the extra trainingsdata it removes the already existing data and only add my new data.
How can I just add extra trainingsdata instead of replacing it?
I did use the following code, (got it from Open NLP NER is not properly trained)
public class TrainNames
{
public static void main(String[] args)
{
train("nl", "person", "namen.txt", "nl-ner-personTest.bin");
}
public static String train(String lang, String entity,InputStreamFactory inputStream, FileOutputStream modelStream) {
Charset charset = Charset.forName("UTF-8");
TokenNameFinderModel model = null;
ObjectStream<NameSample> sampleStream = null;
try {
ObjectStream<String> lineStream = new PlainTextByLineStream(inputStream, charset);
sampleStream = new NameSampleDataStream(lineStream);
TokenNameFinderFactory nameFinderFactory = new TokenNameFinderFactory();
model = NameFinderME.train("nl", "person", sampleStream, TrainingParameters.defaultParams(),
nameFinderFactory);
} catch (FileNotFoundException fio) {
} catch (IOException io) {
} finally {
try {
sampleStream.close();
} catch (IOException io) {
}
}
BufferedOutputStream modelOut = null;
try {
modelOut = new BufferedOutputStream(modelStream);
model.serialize(modelOut);
} catch (IOException io) {
} finally {
if (modelOut != null) {
try {
modelOut.close();
} catch (IOException io) {
}
}
}
return "Something goes wrong with training module.";
}
public static String train(String lang, String entity, String taggedCoprusFile,
String modelFile) {
try {
InputStreamFactory inputStream = new InputStreamFactory() {
FileInputStream fileInputStream = new FileInputStream("namen.txt");
public InputStream createInputStream() throws IOException {
return fileInputStream;
}
};
return train(lang, entity, inputStream,
new FileOutputStream(modelFile));
} catch (Exception e) {
e.printStackTrace();
}
return "Something goes wrong with training module.";
} }
Anyone any ideas to solve this problem?
Because If I want to have an accurate trainingset I need to have at least 15K
sentences says the documation.
I think that OpenNLP does not support to expand existing binary NLP models.
If you have all training data available, collect them all and then train them at once. You can use SequenceInputStream. I modified your example to use another InputStreamFactory
public String train(String lang, String entity, InputStreamFactory inputStream, FileOutputStream modelStream) {
// ....
try {
ObjectStream<String> lineStream = new PlainTextByLineStream(trainingDataInputStreamFactory(Arrays.asList(
new File("trainingdata1.txt"),
new File("trainingdata2.txt"),
new File("trainingdata3.txt")
)), charset);
// ...
}
// ...
}
private InputStreamFactory trainingDataInputStreamFactory(List<File> trainingFiles) {
return new InputStreamFactory() {
#Override
public InputStream createInputStream() throws IOException {
List<InputStream> inputStreams = trainingFiles.stream()
.map(f -> {
try {
return new FileInputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
return new SequenceInputStream(new Vector<>(inputStreams).elements());
}
};
}
I'm trying to save user settings to a file, from where I can read the later. But I cant get it to work properly. I've tried reading up on this, but I'm still having problems.
Map<String, String> userSettings = new HashMap<>();
public void updateUserSettings(){
userSettings.clear();
userSettings.put("item0", item0);
userSettings.put("item1", item1);
userSettings.put("item2", item2);
userSettings.put("item3", item3);
userSettings.put("item4", item4);
userSettings.put("item5", item5);
userSettings.put("item6", item6);
userSettings.put("item7", item7);
userSettings.put("i0", Float.toString(i0));
userSettings.put("i1", Float.toString(i1));
userSettings.put("i2", Float.toString(i2));
userSettings.put("i3", Float.toString(i3));
userSettings.put("i4", Float.toString(i4));
userSettings.put("i5", Float.toString(i5));
userSettings.put("i6", Float.toString(i6));
userSettings.put("i7", Float.toString(i7));
userSettings.put("huvudMaskin", huvudMaskin);
userSettings.put("minorMaskin1", minorMaskin1);
userSettings.put("minorMaskin2", minorMaskin2);
userSettings.put("maskinTid", Float.toString(maskinTid));
writeSettings();
}
public void writeSettings() {
try
{
FileOutputStream fos = context.openFileOutput("test.ser", Context.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(userSettings);
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readSetttings() {
try
{
FileInputStream fileInputStream = new FileInputStream(context.getFilesDir()+"test.ser");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
Map myHashMap = (Map)objectInputStream.readObject();
userSettings = null;
userSettings = myHashMap;
}
catch(ClassNotFoundException | IOException | ClassCastException e) {
e.printStackTrace();
}
executeSettings();
}
I have both read and write rights to the app.
Im not getting anything out of this. I've checked the hashmap, and it works as intended. I have also tried a lot of different approaches, and the only thing I managed to get working was saving strings to a .txt file.
private String subFolder = "/userdata";
private String file = "test.ser";
public void writeSettings() {
File cacheDir = null;
File appDirectory = null;
if (android.os.Environment.getExternalStorageState().
equals(android.os.Environment.MEDIA_MOUNTED)) {
cacheDir = getApplicationContext().getExternalCacheDir();
appDirectory = new File(cacheDir + subFolder);
} else {
cacheDir = getApplicationContext().getCacheDir();
String BaseFolder = cacheDir.getAbsolutePath();
appDirectory = new File(BaseFolder + subFolder);
}
if (appDirectory != null && !appDirectory.exists()) {
appDirectory.mkdirs();
}
File fileName = new File(appDirectory, file);
FileOutputStream fos = null;
ObjectOutputStream out = null;
try {
fos = new FileOutputStream(fileName);
out = new ObjectOutputStream(fos);
out.writeObject(userSettings);
} catch (IOException ex) {
ex.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fos != null)
fos.flush();
fos.close();
if (out != null)
out.flush();
out.close();
} catch (Exception e) {
}
}
}
public void readSetttings() {
File cacheDir = null;
File appDirectory = null;
if (android.os.Environment.getExternalStorageState().
equals(android.os.Environment.MEDIA_MOUNTED)) {
cacheDir = getApplicationContext().getExternalCacheDir();
appDirectory = new File(cacheDir + subFolder);
} else {
cacheDir = getApplicationContext().getCacheDir();
String BaseFolder = cacheDir.getAbsolutePath();
appDirectory = new File(BaseFolder + subFolder);
}
if (appDirectory != null && !appDirectory.exists()) return; // File does not exist
File fileName = new File(appDirectory, file);
FileInputStream fis = null;
ObjectInputStream in = null;
try {
fis = new FileInputStream(fileName);
in = new ObjectInputStream(fis);
Map<String, String> myHashMap = (Map<String, String> ) in.readObject();
userSettings = myHashMap;
System.out.println("count of hash map::"+userSettings.size() + " " + userSettings);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(fis != null) {
fis.close();
}
if(in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Your problem is very simple: you are using two different file names when writing the data resp. reading it.
FileOutputStream fos = context.openFileOutput("test.ser", Context.MODE_PRIVATE);
vs.
FileInputStream fileInputStream = new FileInputStream(context.getFilesDir()+"test.ser");
And, most likely, your reading code did throw an IOException at you, telling you something about trying to open a file that doesn't exist.
Thus, the real take-away/answer here: read those exception messages very carefully. Typically, they tell you exactly what the problem is!
Change these lines :
public void readSetttings(){
String path=context.getFilesDir() + File.seprator + "test.ser";
if(! new File(path).exists() ){
//throw NullPointerException ;
//return;
/*
*you can choose one of these
*pay attention : when choose NullPointerException you shold add throws Exceptions on your method
*/
}
try{
FileInputStream fileInputStream =context.openFileInput("test.ser");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
Map myHashMap = (Map)objectInputStream.readObject();
userSettings = myHashMap;
}catch(ClassNotFoundException | IOException | ClassCastException e) {
e.printStackTrace();
}
executeSettings();
}
If it is only primitives that you want to store then you should be using SharedPreferences which Android provides out of the box.
public static final String PREFS = "usersettings";
#Override
protected void onCreate(Bundle b){
.....
// read user settings on start
SharedPreferences settings = getSharedPreferences(PREFS, 0);
int someId = settings.getInteger("someId", 0);
setSomeId(id);
}
#Override
protected void onStop(){
.....
SharedPreferences settings = getSharedPreferences(PREFS, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putInteger("someId", mSomeId);
// commit changes on exit
editor.commit();
}
I have been trying to create a class called TextFileReaderWriter I want to use the getters and setters to read and write to a text file in such a way that I can call the class and the method from anywhere in the program by simply using setfileContents(somestring) and somestring = getfileContents() something like this
example:
TextFileReaderWriter trw = new TextFileReaderWriter();
trw.setfileContents(somestring); //this would write 'somestring' to the text file.
String somestring = trw.getfileContents(); //this would return 'somestring' from the text file.
Here's what I have so far but it writes nothing to the file:
public class TextFileReaderWriter extends Activity{
String fileContents;
Context context;
String TAG = "MYTAG";
public TextFileReaderWriter(String fileContents, Context context) {
this.fileContents = fileContents;
this.context = context;
}
public String getFileContents() {
return fileContents;
}
public void setFileContents(String fileContents) {
this.fileContents = fileContents;
FileOutputStream fos = null;
try {
fos = context.openFileOutput("UserInputStore", Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
OutputStreamWriter osw = new OutputStreamWriter(fos);
try {
osw.write(fileContents);
Log.d(TAG, fileContents);
} catch (IOException e) {
e.printStackTrace();
}
}
}
You don't need the OutputStreamWriter--FileOutputStreamwill do the trick just fine.
//what you had before
FileOutputStream fos = null;
try {
fos = context.openFileOutput(filename, Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//use just the file output stream to write the data
//data here is a String
if (fos != null) {
try {
fos.write(data.getBytes());
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Method to save data on disk :
protected static void saveDataOnDisk(String data) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
ObjectOutput objectOutput = new ObjectOutputStream(byteArrayOutputStream);
objectOutput.writeObject(data);
byte[] buffer = byteArrayOutputStream.toByteArray();
File loginDataFile = (new File(filePath)); // file path where you want to write your data
loginDataFile.createNewFile();
FileOutputStream fileOutputStream = new FileOutputStream(loginDataFile);
fileOutputStream.write(buffer);
fileOutputStream.close();
objectOutput.flush();
objectOutput.close();
byteArrayOutputStream.flush();
byteArrayOutputStream.close();
Log.i(“SAVE”, ”———————-DONE SAVING”);
} catch(IOException ioe) {
Log.i(“SAVE”, “———serializeObject|”+ioe);
}
}
Method to fetch data from disk:
private static Object getDataFromDisk() {
try {
FileInputStream fileInputeStream = new FileInputStream(FilePath);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputeStream);
Object data = (Object) objectInputStream.readObject();
objectInputStream.close();
fileInputeStream.close();
return dataModel;
} catch (Exception error) {
Log.i(“FETCH”, ”—-getDataFromDisk———ERROR while reading|” + error);
}
return null;
}