I am trying to read from a file to which some user credentials were written. I want to write the file to an internal storage location. The code:
private void writeSendDetails(String name, String number, String emailID) {
//This function writes details to userCredentials.txt and also sends it to server.
String text = "Name: " + userName + "\n" + "Number: " + userNumber + "\n" + "Email ID:" + userEmailID;
FileOutputStream fos = null;
try {
fos = openFileOutput(userCredFile, MODE_PRIVATE);
Log.v(this.toString(), fos.toString());
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(fos != null) {
OutputStreamWriter osw = new OutputStreamWriter(fos);
try {
osw.write(text);
} catch (IOException e) {
// TODO Auto-generated catch block
Log.v(this.toString(), "IOException caught in osw.write");
e.printStackTrace();
}
try {
osw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
osw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Log.v(this.toString(), "Written everything to userCredentials.txt");
readUserCredentials();
//code to send to server should begin here.
}
private void readUserCredentials() {
//function to read name, number and email ID from userCredentials.txt
/* Steps:
* 1. Check if file exists.
* 2. If it does, read all relevant credentials.
*/
File f = new File(userCredFile);
if(f.canRead()) {
Log.v(this.toString(), "Can open userCredentials for reading from.");
}
try {
FileReader fis = new FileReader(f);
Log.v(this.toString(), "Wrapping a buffered reader around file reader.");
BufferedReader bufRead = new BufferedReader(fis, 100);
String line;
try {
while((line = bufRead.readLine()) != null) {
Log.v(this.toString(), "Line read = " + line);
line = bufRead.readLine();
if(line.indexOf("Name: ") != -1) {
Log.v(this.toString(), "Found name in the string.");
userName = line.substring(6);
} else if(line.indexOf("Number: ") != -1) {
Log.v(this.toString(), "Found number in the string.");
userNumber = line.substring(8);
} else if(line.indexOf("Email ID: ") != -1) {
Log.v(this.toString(), "Found email in the string.");
userEmailID = line.substring(10);
}
}
Log.v(this.toString(), "User credentials = " + userName + " " + userNumber + " " + userEmailID);
} catch (IOException e) {
Log.v(this.toString(), "IOException caught.");
}
} catch (FileNotFoundException e1) {
Log.v(this.toString(), "File not found for reading.");
}
}
The LogCat output shows:
04-14 15:20:43.789: V/com.sriram.htmldisplay.htmlDisplay#44c0c660(675): Written everything to userCredentials.txt
04-14 15:20:43.789: V/com.sriram.htmldisplay.htmlDisplay#44c0c660(675): File not found for reading.
04-14 15:20:43.889: V/com.sriram.htmldisplay.fireflymenu#44c401e0(675): File not found for reading.
My question(s):
1. I need to write the file to internal storage. Am I doing it correctly?
2. Why is the file just written not being read?
Some things for your code:
#Oren is correct, you should use Log.e(TAG, "message", e) instead of the auto-created stuff from eclipse!
you should simply merge the 3 try/catch to one. No need to make it 3 times...
you should use Log.e() as said above for your FileNotFoundException too, so see the stacktrace to check the real reason (which currently covers the hint to solve your issue)
If you would have done at least number 3, you would have seen that the file you try to read could not be found. Thats why your log doesn't show the Can open userCredentials for reading from. output from your if statement.
The reason for that is pretty simple: You create the file by using openFileOutput(userCredFile, MODE_PRIVATE);. If you read the documentation of openFileOutput you will stumble upon:
The name of the file to open; can not contain path separators.
That means that userCredFile can only be something like test.txt. Also this method creates a file in a directory that can't be easily access from "outside".
When you now try to read the file via FileReader(userCredFile) it should be obvious, that android will try to open it in the root directory: /text.txt and it will, of course, fail. No non-root app can write/read in the root directory.
The main question, and also the answer to your issue: Why don't you use the corresponding openFileInput(userCredFile) method to read the file?
Related
I feel like nesting try-catch logic inside a catch block is not ideal / not clean code, but I am not sure how to refactor my code such that:
When there is no file found (catch FileNotFoundExeption) my program will create a new file (which generates IOException), without nesting the try catch.
public String hiMessage() {
String message = "Hello! Initializing program.\n";
try {
storage.readFromTasksFileToList(tasks);
message += "This is where you left off previously:\n";
} catch (FileNotFoundException e) {
message += "Fetching failed. " + e.getMessage() + "\n";
message += "Creating file now...\n";
File dukeTxt = new File(Duke.filePath);
try { // nested try catch inside catch
dukeTxt.createNewFile(); // throws IOException
message += "File created! " + dukeTxt.getAbsolutePath() + "\n";
message += "Reading file...\n";
} catch (IOException ioe) {
message += "\t File creation was not successful. \n";
message += "\t Exiting system.";
return message;
}
}
message += getAllTasksAsString();
return message;
}
Ideally, you should check the existance of the file before reading it. Something along these lines:
File dukeTxt = new File(Duke.filePath);
if (dukeTxt.exist()) {
try { dukeTxt.createNewFile(); }
catch(IOException ioe) {...}
}
try { storage.readFromTasksFileToList(tasks); }
catch (FileNotFoundException fnfe) {...}
I use netty offical example HttpStaticFileServerHandler as file server, but when I download file from server I met a problem, the mp4 file I download from server is not complete and can't display.
https://github.com/netty/netty/blob/4.1/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java
And here is my client code:
FileOutputStream fos = null;
try {
URL website = new URL("http://localhost:8090/export/App/***.mp4");
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
fos = new FileOutputStream("/Users/mine/***.mp4");
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
} catch (Exception e) {
System.out.println("error msg:\n" + e);
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException ioe) {
System.out.println("fos close fail:\n" + ioe);
}
}
Make sure you close your FileOutputStream using fos.close().
Failing to do so means that only part of the data will be written, and that other programs may experience problems when accessing the file.
Another thing you could check is viewing the filesize of the file, those should match at both sides, if the file is way too small, open it with an text editor, and view the contents to check for clues.
I solved this problem. I find the RandomAccessFile is not closed in correct time.
Here is the change:
RandomAccessFile raf;
try {
raf = new RandomAccessFile(file, "r");
} catch (FileNotFoundException ignore) {
sendError(ctx, NOT_FOUND);
return;
}
...
sendFileFuture.addListener(new ChannelProgressiveFutureListener() {
#Override
public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) {
if (total < 0) { // total unknown
System.err.println(future.channel() + " Transfer progress: " + progress);
} else {
System.err.println(future.channel() + " Transfer progress: " + progress + " / " + total);
}
}
#Override
public void operationComplete(ChannelProgressiveFuture future) {
System.err.println(future.channel() + " Transfer complete.");
raf.close();// close raf when transfer completed
}
});
I have an Android Application that write one line in a file every time the method OnLocationChanged() is called. Data inside each line is separated by a semicolon. I store the epoch time (System.currentTimeMillis()), the latitude and the longitude of the new location:
File example 1:
1477294804758;45.17358813287331;5.750043562562213
1477294805758;45.17358813287331;5.750043562562213
Between those two lines, there is 1 second gap so everything is fine.
Most of the time, it works. But sometimes, every second, it writes two lines :
File example 2:
1477294806761;45.17358813287331;5.750043562562213
1477294806776;45.17358813287331;5.750043562562213
1477294807767;45.17358813287331;5.750043562562213
1477294807779;45.17358813287331;5.750043562562213
OnLocationChanged is called twice every second with a 15 millis gap.
I could not find a way to reproduce this bug. It is erratic.
Here is how I implement the location provider :
locationManager = (LocationManager) this.getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,0,MainActivity.this);
My MainActivity implements LocationListener.
Here is how I write data to the file :
#Override
public void onLocationChanged(Location location) {
try {
File dataFile = new File(saveFileFlyData);
if(!dataFile.exists())
dataFile.createNewFile();
FileOutputStream fOut = null;
try {
fOut = new FileOutputStream(dataFile, true);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
OutputStreamWriter osw = new OutputStreamWriter(fOut);
try {
if(mCurrentLocation != null)
{
osw.write(System.currentTimeMillis() +
";" + mCurrentLocation.getLatitude() +
";" + mCurrentLocation.getLongitude()+
"\n"
);
}
else
{
osw.write(0 +
";" + 0 +
";" + 0+
"\n"
);
}
osw.flush();
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
}
I cant see why it works from time to time.
I am really new to android and writing a simple game for android.
In the game, like in most games you have score,
now, I want the score to be saved in Internal Storage, and for some reason, I manage to save the score, but not load it back.
here is the code:
final TextView best = (TextView) findViewById(R.id.best);
public int read = -1;
public StringBuffer buffer = new StringBuffer();
public String scoreTxt = buffer.substring(0, buffer.indexOf(" ") + 1);
public int score = 0;
// Save
try {
fileOutputStream = openFileOutput("record.txt", Context.MODE_PRIVATE);
fileOutputStream.write(scoreString.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Toast.makeText(MainActivity.this, "Save() works fine", Toast.LENGTH_SHORT).show();
// load
try {
FileInputStream fileInputStream = openFileInput("record.txt");
while ((read = fileInputStream.read())!= -1){
buffer.append((char)read);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
best.setText("Best: " + scoreTxt);
Toast.makeText(MainActivity.this, "load() is good too " + scoreTxt, Toast.LENGTH_SHORT).show();
when I run the app, there is no crash or anything special in the logcat, but when ever I use scoreTxt the output is nothing, just " ".
can somebody help me solve this problem? Thanks
You never assign scoreTxt a value in your code.
You need to parse buffer after it has being populated.Now when scoreTxt is initialized buffer is null
You need to replace this
best.setText("Best: " + scoreTxt);
with
scoreTxt = buffer.substring(0, buffer.indexOf(" ") + 1);
best.setText("Best: " + scoreTxt);
In addition I wouldn't store game score into a file because score changes frequently and you want to avoid disk access a lot. Store it in SharedPreferences and from time to time flush it to a file on a background thread.
well this is a strange one.
The first save attampt usually works (1 more try max).
but in a heavy load (many saves in a row) the saved file disappears.
if uncommenting the "Thread.sleep" the error is captured otherwise the validation passes succesfully
public void save(Object key, T objToSave) throws FileNotFoundException, IOException {
IOException ex = null;
for (int i = 0; i < NUM_OF_RETRIES; i++) {
try {
/* saving */
String filePath = getFilePath(key);
OutputStream outStream = getOutStream(filePath);
ObjectOutputStream os = new ObjectOutputStream(outStream);
os.writeObject(objToSave);
os.close();
/* validations warnings etc. */
if (i>0){
logger.warn(objToSave + " saved on attamped " + i);
/* sleep more on each fail */
Thread.sleep(100+i*8);
}
//Thread.sleep(50);
File doneFile = new File(filePath);
if (! (doneFile.exists())){
logger.error("got here but file was not witten to disk ! id was" + key);
throw new IOException();
}
logger.info("6. start persist " + key + " path=" + new File(filePath).getAbsolutePath() + " exists="+doneFile.exists());
return;
} catch (IOException e) {
logger.error(objToSave + " failed on attamped " + i);
ex = e;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
throw ex;
}
It is not a java writers issue.
I was not using threads explicitly but in my test I was deleting the folder i was saving to using: Runtime.getRuntime("rm -rf saver_directory");
I found out the hard way that it is asynchronous and the exact delete and create time was changing in mili-seconds.
so the solution was adding "sleep" after the delete.
the correct answer would be using java for the delete and not making a shortcuts ;)
Thank you all.