I have a dialog with spinners and an OK button. I also have an arraylist that is populated by the user selecting items in the spinners. I want the app to save the arraylist to a file and load it at every launch (because without saving the arraylist is always empty at launch).
So here is the code i am using. The saving should be okay, at least i get the Toast message saying Saving OK. This code is the OKbtn listener so when user clicks ok, an item is added to the arraylist and there comes this code:
if (assignArr.size() > 0)
{
String filename = "file.txt";
ArrayList<String> report = new ArrayList<String>();
for (int i=0; i<assignArr.size(); i++)
{
report.add(assignArr.get(i));
}
FileOutputStream fos;
try {
fos = openFileOutput(filename,Context.MODE_PRIVATE);
ObjectOutputStream out = new ObjectOutputStream(fos);
out.writeObject(report);
out.close();
Toast.makeText(MainActivity.this, "Saving OK", Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I put the loading part to the beginning of the code, but i don't think it matters:
words = new ArrayList<String>(50);
try {
InputStream is = getResources().getAssets().open("file.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
while((line = br.readLine()) != null)
{
words.add(line);
}
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
if (words.size() > 0)
{
for (int i=0; i<words.size(); i++)
{
assignArr.add(words.get(i));
Toast.makeText(MainActivity.this, "Loading OK", Toast.LENGTH_LONG).show();
}
}
In this case i never get the toast message.
One problem can be that where is the file created? Where in the emulator and where on the phone? And regarding the phone, is it created on the sd card or the phone memory?
I hope this is the right code to save and load an arraylist.
What is wrong with the code?
Update:
I replaced InputStream is = getResources().getAssets().open("file.txt"); withInputStream is = openFileInput("file.txt");
Now something happens. I write out the result of the saving and the loading into a toast message, which is weird:
Toast.makeText(MainActivity.this, "Saving OK + " + report, Toast.LENGTH_LONG).show();
Please take a look at it. The words on the bottom are partly hungarian names. So maybe the saving an arraylist to a file is the problem.
The file you create via openFileOutput is written into your app's private directory, which you can get using Context#getFilesDir() (usually it's /data/data/<your-app-package>/).
This directory has nothing to do with the assets folder.
Related
so im trying to write data that I recieve from a socket into text file and then read those data.
I have these 2 methods in my MainActivity (just tests to see how read and write from/into a file works) :
public void WriteBtn() {
// add-write text into file
try {
FileOutputStream fileout=openFileOutput("mytextfile.txt", MODE_PRIVATE);
OutputStreamWriter outputWriter=new OutputStreamWriter(fileout);
outputWriter.write("Test");
outputWriter.close();
//display file saved message
Toast.makeText(getBaseContext(), "File saved successfully!",
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
public void ReadBtn() {
//reading text from file
try {
FileInputStream fileIn=openFileInput("mytextfile.txt");
InputStreamReader InputRead= new InputStreamReader(fileIn);
char[] inputBuffer= new char[256];
String s="";
int charRead;
while ((charRead=InputRead.read(inputBuffer))>0) {
// char to string conversion
String readstring=String.copyValueOf(inputBuffer,0,charRead);
s +=readstring;
}
InputRead.close();
Toast.makeText(getBaseContext(), s,Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
I call them with buttons but I was wondering, where does it save my "mytextfile.txt" ???
Take a look at Context.getExternalFilesDir() and pass it Environment.DIRECTORY_DOCUMENTS. That should give you the default output path for text files.
https://developer.android.com/reference/android/content/Context.html#getExternalFilesDir(java.lang.String)
EDIT
I just tested this. It looks like Context.openFileOutput() dumps everything, regardless of file type, to Conext.getFilesDir()
https://developer.android.com/reference/android/content/Context.html#getFilesDir()
I literally looked through stackoverflow trying to find the right answer... maybe I am doing something wrong.
I am making my first more elaborate app, that is quizz app for children. I want the scores to be saved in the highscorestable.txt, that will be later opened, updated, read, etc. The file should exist after closing the application to reuse it with the next game and so on.
I was using http://developer.android.com/guide/topics/data/data-storage.html . I want the file to be saved on the phone memory.
I have the following code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_high_scores);
Intent intent = getIntent();
String userData;
scores =(EditText)findViewById(R.id.scores);
if(intent.getStringExtra(EndScreen.EXTRA_MESSAGE)!=null)
{
userData = intent.getStringExtra(EndScreen.EXTRA_MESSAGE);
}
else
{
userData="";
}
String temp = "";//to widzi przy zaladowaniu
String output = "";
String g="";
//FIRST READING not necessary?
try{
FileInputStream fin = openFileInput("highscorestable.txt");
int c;
while( (c = fin.read()) != -1){
temp = temp + Character.toString((char)c);
}
fin.close();
}
catch (Exception e) {
// e.printStackTrace();
}
if(temp.equals(null))
{
temp = "";
}
//output = userData; //+ temp;
FileOutputStream fos;//WRITING
try {
fos = openFileOutput("highscorestable.txt", Context.MODE_PRIVATE);
fos.write(userData.getBytes());
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
//READING2
try{
FileInputStream fin = openFileInput("highscorestable.txt");
int c;
while( (c = fin.read()) != -1){
g = g + Character.toString((char)c);
}
fin.close();
output= output+g;
scores.setText(output);
}
catch (Exception e) {
}
The intent itself works, actually everything works, however the fileitself does not last. I mean, when I start a new game, the old data is not restored. How to fix it?
Try using sharedPrefrences: http://developer.android.com/training/basics/data-storage/shared-preferences.html
They are stored permanently in the app as XML and are only readable to the app if configured properly. (unless you NEED text, read here: http://developer.android.com/training/basics/data-storage/files.html . Remember to add the permissions to your manifest)
EDIT:
try appending to the file not writing
I am using the below code for downloading an already uploaded sqlite db file from google drive to the data/data/packagename/databases folder, but when the method completes, I am seeing a db corruption warning message logged in logcat and also all the data on the device for the app is overwritten and shows up blank, upon opening the app.
mfile = Drive.DriveApi.getFile(mGoogleApiClient, mResultsAdapter.getItem(0).getDriveId());
mfile.openContents(mGoogleApiClient, DriveFile.MODE_READ_ONLY, null).setResultCallback(contentsOpenedCallback);
--mfile is an instance of DriveFile
final private ResultCallback<ContentsResult> contentsOpenedCallback = new ResultCallback<ContentsResult>()
{
#Override
public void onResult(ContentsResult result)
{
if (!result.getStatus().isSuccess())
{
FileUtils.appendLog(getApplicationContext(), Tag + "-onResult", "Error opening file");
return;
}
try
{
if (GetFileFromDrive(result))
{
//FileUtils.Restore(getApplicationContext());
SharedPrefHelper.EditSharedPreference(getApplicationContext(), Constants.PREFS_DO_RESTORE, false);
}
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
private boolean GetFileFromDrive(ContentsResult result)
{
Contents contents = result.getContents();
//InputStreamReader rda = new InputStreamReader(contents.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(contents.getInputStream()));
FileOutputStream outStream;
String currLine;
boolean restoreSuccess = false;
File sourceDbFile = BackupDBBeforeDeletion();
if(sourceDbFile != null)
sourceDbFile.delete();
try
{
outStream = new FileOutputStream(getApplicationContext().getDatabasePath(Constants.DB_NAME));
while ((currLine = reader.readLine()) != null)
{
outStream.write(currLine.getBytes());
}
outStream.flush();
reader.close();
outStream.close();
restoreSuccess = true;
}
catch (FileNotFoundException e)
{
// TODO: Log exception
}
catch (IOException e)
{
// TODO: Log Exception
}
return restoreSuccess;
}
When the method GetFileFromDrive completes, a db corruption shows up on LogCat and all the existing data on the app's datanase file (sqlite db) is gone.
Please help, as I have verified that the drive uploaded sqlite db file is correct and well formed, by downloading the same and opening it up in Sqlite Browser. It's the download from drive that is not working.
This solution is not working for me. The sqlite files I got from google drive is more longer than I saved in google drive. That, probably, happen because you are using a Buffereader class and the method readline that reads data in char.
In my project and experience this solutions does not work, I got a corrupted sqlite db.
So... I save sqlite db in google drive in byte so **I read from google drive the same sqlite db in byte, using BufferedInputStream.
This works perfectly for me:
DriveContents contents = result.getDriveContents();
BufferedInputStream bis = new BufferedInputStream(contents.getInputStream());
byte[] buffer = new byte[1024];
int bytesread = 0;
FileOutputStream outStream;
/*if(currentDB != null)
currentDB.delete();*/
try
{
outStream = new FileOutputStream(currentDB);
while( (bytesread = bis.read(buffer)) != -1)
{
outStream.write(buffer,0,bytesread);
}
outStream.flush();
bis.close();
outStream.close();
}
catch (FileNotFoundException e)
{
Log.i(TAG,e.getMessage());
}
catch (IOException e)
{
Log.i(TAG,e.getMessage());
}
finally {
Toast.makeText(getActivity().getBaseContext(),"Data from Google Drive restored successfully." , Toast.LENGTH_LONG).show();
}
contents.discard(mGoogleApiClient);
I was able to finally fix my own issue, by replacing the file.openContents with file.open and setting a result call back with DriveContents result back rather than ContentsResult.
Also, used the DriveContents to set an InputStream on the same (initially opened in Mode_Read_Only in open method) and then writing it out into a physical ".db" file on the data base path location.
Now, the database doesn't get corrupted and restores data successfully.
I have searched a lot but it seems older answers are wrong as storage seems to have changed from data/data and permission WRITE_INTERNAL_MEMORY is no longer available. I am using Eclipse.
I have a multi-choice test and want to store the status of the answers a user has given:
N = not attepmpted, C = Correct last time, I = Incorrect last attempt
Therefore the file needs to be re-writeable - will be read as an array and then the array with new status will be over-written.
The code to write the file on first run is - you can see I've just changed it to write "N" now rather than lines of "N" as needed. There is also a single-line txt file to store the user id:
public void RunFirst(View view) throws IOException{
//need to initialise file as a list of N's:
count = 0;
StringBuilder sb = new StringBuilder();
while(count<4){
sb.append("N");
sb.append("\n");
count = count +1;
};
NsString = sb.toString();
String progfile = "userprogress.txt";
try {
FileOutputStream fos = new FileOutputStream(progfile);
fos = openFileOutput(progfile, Context.MODE_PRIVATE);
fos.write(NsString.getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
// read userID
TextView usrID = (TextView) findViewById(R.id.editTextUserNameInput);
userID = usrID.getText().toString();
Toast.makeText(getApplicationContext(), "Welcome" + userID,
Toast.LENGTH_LONG).show();
//save userID
String usridfile = "userid.txt";
try{
FileOutputStream fosuserid = new FileOutputStream(usridfile);
fosuserid = openFileOutput(usridfile, Context.MODE_PRIVATE);
fosuserid.write(userID.getBytes());
fosuserid.close();
Toast.makeText(getApplicationContext(), "filesaved",
Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
To read from the file:
private void readprogressfile(){
//#Override
try
{
Toast.makeText(getApplicationContext(), "b4 file",
Toast.LENGTH_LONG).show();
InputStream input = openFileInput("userprogress.txt");
InputStreamReader isr = new InputStreamReader(input);
BufferedReader buffrdr = new BufferedReader(isr);
userprog = new String [4];
int size = input.available();
byte[] buffer = new byte[size];
count = 0;
line = null;
while(count <4){
input.read(buffer);
line = new String(buffer);
userprog[count]= line;
Toast.makeText(getApplicationContext(), "status:" + count + userprog[count],
Toast.LENGTH_LONG).show();
};
input.close();
// byte buffer into a string
String text= new String(buffer);
//txtContent.setText(text);
Toast.makeText(getApplicationContext(), "after file",
Toast.LENGTH_LONG).show();
TextView showfile = (TextView)findViewById(R.id.textViewShowAns);
showfile.setText("Q status:"+ userprog[qno]);
}catch (IOException e) {
e.printStackTrace ();}
}
;
}
the fact that WRITE_INTERNAL_MEMORY permission is deprecated don't mean that you can't write to internal memory anymore. actually, it's the opposite - Google decided there is no need in any permission to write / create files in your private internal folder.
you can get path to your private application storage folder by the method getFilesDir()
this is the perfect place to write your private files, and made especially for that purpose.
as Google wrote in the documentation:
You don’t need any permissions to save files on the internal storage. Your application always has permission to read and write files in its internal storage directory.
source and more info on - http://developer.android.com/training/basics/data-storage/files.html
In my app there are 3 EditTexts. I want to write the content of this EditTexts to a file, but the filewrite throws a nullpointer exception. Why?
OutputStream f1; is declared globally.
BtnSave = (Button)findViewById(R.id.Button01);
BtnSave.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
intoarray = name + "|" + number + "|" + freq + "\n";
Toast.makeText(Main.this, "" + intoarray, Toast.LENGTH_SHORT).show();
//so far so good
byte buf[] = intoarray.getBytes();
try {
f1 = new FileOutputStream("file2.txt");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
f1.write(buf); //nullpointer exception
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
f1.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Most likely
f1 = new FileOutputStream("file2.txt");
failed and since you caught the exception f1 remained null. In most cases in Android you can only create files either in your application data directory or external storage.
The way you are currently using this won't work, generally you are trying to write to internal storage, which is private to your app and must be contained within your applications directory.
The proper way to create the file stream is
fin = openFileOutput("file2.txt", Context.MODE_PRIVATE); // open for writing
fout = openFileInput("file2.txt", Context.MODE_PRIVATE); // open for reading
Which will locate the file in your storage area for your application, which is typically something like
/data/data/com.yourpackagename/files/...
You can still create directories within your applications area if you need a directory structure of course.
If you need to write to external storage that's a different process, for more information see Android Data Storage
Sorry for all you were trying help me, I asked the wrong question. I wanted to use internal storage (and it is now working). I don't know what the problem is, but the with the code below (that i have used a lot) filewrite is ok:
try {
File root = Environment.getExternalStorageDirectory();
File file = new File(root, "Data.txt");
if (root.canWrite()) {
FileWriter filewriter = new FileWriter(file, true);
BufferedWriter out = new BufferedWriterfilewriter);
out.write(intoarray);
out.close();
}
} catch (IOException e) {
Log.e("TAG", "Could not write file " + e.getMessage());
}
I would delete the topic if I could. I accept this answer to close the topic.
Thanks, anyway.