I'm currently trying to store json data I get on the Internet in the internal storage of the phone. In order to do so, I have get the data from an API as a string (no issue in this part, nor during the parsing afterwards). Then comes the part where I try to store it in a file... And the problems that come along!
The ultimate goal is to update data when an Internet connection is available, and use the data previously stored when no connection can be found.
Here is my code (data is in the String jsonString):
// IN CASE OF INTERNET CONNECTION (ie "jsonString != null")
if (jsonString != null) {
try {
FileOutputStream fos = new FileOutputStream(json_InternalFile);
fos.write(jsonString.getBytes());
fos.close();
} catch (FileNotFoundException e) {
Log.e("Response: ", "> " + "File not found");
e.printStackTrace();
} catch (IOException e) {
Log.e("Response: ", "> " + "IO Exception");
e.printStackTrace();
}
}
// IF NO CONNECTION AVAILABLE (ie "jsonString == null)
if (jsonString == null) {
try {
FileInputStream fis = new FileInputStream(json_InternalFile);
DataInputStream dis = new DataInputStream(fis);
BufferedReader br = new BufferedReader(new InputStreamReader(dis));
String strLine;
while ((strLine = br.readLine()) != null) {
jsonString = jsonString + strLine;
}
dis.close();
} catch (FileNotFoundException e) {
Log.e("Response: ", "> " + "File not found");
e.printStackTrace();
} catch (IOException e) {
Log.e("Response: ", "> " + "File not found");
e.printStackTrace();
}
}
None of the parts works individually. When I run the app, I got this message: "Unfortunately, the app "APP_NAME" stopped running" (whichever part I comment)
I also tried to replace the line:
FileOutputStream fos = new FileOutputStream(json_InternalFile);
with:
FileOutputStream fos = openFileOutput(jsonStorage_FileName, 0);
... Without success ^^'
I used - and abused ;) - the following code I found:
http://www.mysamplecode.com/2012/06/android-internal-external-storage.html
Thank you in advance, I really can't see the problem here (and it's turning me slightly mad ><)
Related
I have a problem on my code; basically I have an array containing some key:
String[] ComputerScience = { "A", "B", "C", "D" };
And so on, containing 40 entries.
My code reads 900 pdf from 40 folder corresponding to each element of ComputerScience, manipulates the extracted text and stores the output in a file named A.txt , B.txt, ecc ...
Each folder "A", "B", ecc contains 900 pdf.
After a lot of documents, an exception "Too many open files" is thrown.
I'm supposing that I am correctly closing files handler.
static boolean writeOccurencesFile(String WORDLIST,String categoria, TreeMap<String,Integer> map) {
File dizionario = new File(WORDLIST);
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
File cat_out = new File("files/" + categoria + ".txt");
fileWriter = new FileWriter(cat_out, true);
} catch (IOException e) {
e.printStackTrace();
}
try {
fileReader = new FileReader(dizionario);
} catch (FileNotFoundException e) { }
try {
BufferedReader bufferedReader = new BufferedReader(fileReader);
if (dizionario.exists()) {
StringBuffer stringBuffer = new StringBuffer();
String parola;
StringBuffer line = new StringBuffer();
int contatore_index_parola = 1;
while ((parola = bufferedReader.readLine()) != null) {
if (map.containsKey(parola) && !parola.isEmpty()) {
line.append(contatore_index_parola + ":" + map.get(parola).intValue() + " ");
map.remove(parola);
}
contatore_index_parola++;
}
if (! line.toString().isEmpty()) {
fileWriter.append(getCategoryID(categoria) + " " + line + "\n"); // print riga completa documento N x1:y x2:a ...
}
} else { System.err.println("Dictionary file not found."); }
bufferedReader.close();
fileReader.close();
fileWriter.close();
} catch (IOException e) { return false;}
catch (NullPointerException ex ) { return false;}
finally {
try {
fileReader.close();
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
But the error still comes. ( it is thrown at:)
try {
File cat_out = new File("files/" + categoria + ".txt");
fileWriter = new FileWriter(cat_out, true);
} catch (IOException e) {
e.printStackTrace();
}
Thank you.
EDIT: SOLVED
I found the solution, there was, in the main function in which writeOccurencesFile is called, another function that create a RandomAccessFile and doesn't close it.
The debugger sais that Exception has thrown in writeOccurencesFile but using Java Leak Detector i found out that the pdf were already opened and not close after parsing to pure text.
Thank you!
Try using this utility specifically designed for the purpose.
This Java agent is a utility that keeps track of where/when/who opened files in your JVM. You can have the agent trace these operations to find out about the access pattern or handle leaks, and dump the list of currently open files and where/when/who opened them.
When the exception occurs, this agent will dump the list, allowing you to find out where a large number of file descriptors are in use.
i have tried using try-with resources; but the problem remains.
Also running in system macos built-in console print out a FileNotFound exception at the line of FileWriter fileWriter = ...
static boolean writeOccurencesFile(String WORDLIST,String categoria, TreeMap<String,Integer> map) {
File dizionario = new File(WORDLIST);
try (FileWriter fileWriter = new FileWriter( "files/" + categoria + ".txt" , true)) {
try (FileReader fileReader = new FileReader(dizionario)) {
try (BufferedReader bufferedReader = new BufferedReader(fileReader)) {
if (dizionario.exists()) {
StringBuffer stringBuffer = new StringBuffer();
String parola;
StringBuffer line = new StringBuffer();
int contatore_index_parola = 1;
while ((parola = bufferedReader.readLine()) != null) {
if (map.containsKey(parola) && !parola.isEmpty()) {
line.append(contatore_index_parola + ":" + map.get(parola).intValue() + " ");
map.remove(parola);
}
contatore_index_parola++;
}
if (!line.toString().isEmpty()) {
fileWriter.append(getCategoryID(categoria) + " " + line + "\n"); // print riga completa documento N x1:y x2:a ...
}
} else {
System.err.println("Dictionary file not found.");
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
This is the code that i am using now, although the bad managing of Exception, why the files seem to be not closed?
Now i am making a test with File Leak Detector
Maybe your code raises another exception that you are not handling. Try add catch (Exception e) before finally block
You also can move BufferedReader declaration out the try and close it in finally
i using this function:
> private void writeToFile(String data) {
> try {
> OutputStreamWriter outputStreamWriter = new OutputStreamWriter(openFileOutput("mywords.txt",
> Context.MODE_PRIVATE));
> outputStreamWriter.write(data);
> outputStreamWriter.close();
> }
> catch (IOException e) {
> Log.e("Exception", "File write failed: " + e.toString());
> } }
i want to write a lot of times and every time i write it changes like deletes all and adds new thing i write but i do not want it to delete
husky thanks i do not know why you deleted your comment it works i changed to MODE_APPEND
another problem how do i do space in the text file
Pass true as the second argument to FileOutputStream to open the file in append mode.
OutputStreamWriter writer = new OutputStreamWriter(
new FileOutputStream("mywords.txt", true), "UTF-8");
OutputStreamWriter by default overwrites. In order to append information to a file, you will have to give it additional information in the constructor. See also OutputStreamWriter does not append for more information.
Try this:
private void writeToFile(String data) {
File file = new File("mywords.txt");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file, true);
// Writes bytes from the specified byte array to this file output stream
fos.write(data.getBytes());
}
catch (FileNotFoundException e) {
System.out.println("File not found" + e);
}
catch (IOException ioe) {
System.out.println("Exception while writing file " + ioe);
}
finally {
// close the streams using close method
try {
if (fos != null) {
fos.close();
}
}
catch (IOException ioe) {
System.out.println("Error while closing stream: " + ioe);
}
}
}
I have tried various kinds of codes to convert a large CSV file (~300 MB) to byte[] but each time it fails giving Java Heap Space error as shown below:
184898 [jobLauncherTaskExecutor-1] DEBUG
org.springframework.batch.core.step.tasklet.TaskletStep - Rollback
for Error: java.lang.OutOfMemoryError: Java heap space 185000
[jobLauncherTaskExecutor-1] DEBUG
org.springframework.transaction.support.TransactionTemplate -
Initiating transaction rollback on application exception
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2367)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:415)
at java.lang.StringBuffer.append(StringBuffer.java:237)
at org.apache.log4j.helpers.PatternParser$LiteralPatternConverter.format(PatternParser.java:419)
at org.apache.log4j.PatternLayout.format(PatternLayout.java:506)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:310)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:162)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
at org.apache.log4j.Category.callAppenders(Category.java:206)
at org.apache.log4j.Category.forcedLog(Category.java:391)
at org.apache.log4j.Category.log(Category.java:856)
at org.slf4j.impl.Log4jLoggerAdapter.log(Log4jLoggerAdapter.java:601)
at org.apache.commons.logging.impl.SLF4JLocationAwareLog.debug(SLF4JLocationAwareLog.java:133)
at org.apache.http.impl.conn.Wire.wire(Wire.java:77)
at org.apache.http.impl.conn.Wire.output(Wire.java:107)
at org.apache.http.impl.conn.LoggingSessionOutputBuffer.write(LoggingSessionOutputBuffer.java:76)
at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:119)
at org.apache.http.entity.ByteArrayEntity.writeTo(ByteArrayEntity.java:115)
at org.apache.http.entity.HttpEntityWrapper.writeTo(HttpEntityWrapper.java:98)
at org.apache.http.impl.client.EntityEnclosingRequestWrapper$EntityWrapper.writeTo(EntityEnclosingRequestWrapper.java:108)
at org.apache.http.impl.entity.EntitySerializer.serialize(EntitySerializer.java:122)
at org.apache.http.impl.AbstractHttpClientConnection.sendRequestEntity(AbstractHttpClientConnection.java:271)
at org.apache.http.impl.conn.AbstractClientConnAdapter.sendRequestEntity(AbstractClientConnAdapter.java:227)
at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:257)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:712)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:517)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
So far, I have tried using the following versions of code for doing the file to byte[] conversion:
Version 1: Core Java
File file = new File(fileName);
FileInputStream fin = null;
byte fileContent[] = null;
try {
fin = new FileInputStream(file);
fileContent = new byte[(int) file.length()];
fin.read(fileContent);
} catch (FileNotFoundException e) {
System.out.println("File not found" + e);
} catch (IOException ioe) {
System.out.println("Exception while reading file " + ioe);
} finally {
try {
if (fin != null) {
fin.close();
}
} catch (IOException ioe) {
System.out.println("Error while closing stream: " + ioe);
}
}
return fileContent;
Version 2: Java 7 NIO
Path path = Paths.get(fileName);
byte[] data = null;
try {
data = Files.readAllBytes(path);
} catch (IOException e) {
e.printStackTrace();
}
return data;
Version 3: Apache Commons IO
File file = new File(fileName);
FileInputStream fis = null;
byte fileContent[] = null;
try {
fis = new FileInputStream(file);
fileContent = IOUtils.toByteArray(fis);
} catch (FileNotFoundException e) {
System.out.println("File not found" + e);
} catch (IOException ioe) {
System.out.println("Exception while reading file " + ioe);
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException ioe) {
System.out.println("Error while closing stream: " + ioe);
}
}
return fileContent;
Version 4: Google Guava
File file = new File(fileName);
FileInputStream fis = null;
byte fileContent[] = null;
try {
fis = new FileInputStream(file);
fileContent = ByteStreams.toByteArray(fis);
} catch (FileNotFoundException e) {
System.out.println("File not found" + e);
} catch (IOException ioe) {
System.out.println("Exception while reading file " + ioe);
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException ioe) {
System.out.println("Error while closing stream: " + ioe);
}
}
return fileContent;
Version 5: Apache.commons.io.FileUtils
File file = new File(fileName);
byte fileContent[] = null;
try {
fileContent = org.apache.commons.io.FileUtils.readFileToByteArray(file);
} catch (FileNotFoundException e) {
System.out.println("File not found" + e);
} catch (IOException ioe) {
System.out.println("Exception while reading file " + ioe);
}
return fileContent;
I have even setup my Heap Space settings to be quite big. It’s about 6 GB (5,617,772 K) for my external Tomcat as shown in the memory consumption in the Task Manager.
For the first three versions of code the heap space increases suddenly to more than 5 GB upon hitting this byte[] generation code and then it fails. With Google Guava, it seemed very promising and the memory consumption stayed to about 3.5 GB for quite some time, like about 10 minutes, after hitting the byte[] generation code and then it too suddenly jumped to more than 5 GB and failed.
I am unable to figure out a solution for this problem. Can somebody help me solve this problem? Any help in this would be greatly appreciated.
A 300MB file will not consume 6GB of heap when loaded into a byte array. And looking closer at your stacktrace, it seems the loading part is completely fine. "The java.lang.OutOfMemoryError: Java heap space" is only thrown when you try to log something using Log4j.
The logging seems to originate from 3rd party code instead of your own, so you might not be able to change what is being logged, but you can definitely reduce the logging via Log4j configuration, try increasing the log level (to WARN, ERROR or FATAL) for org.apache.* and you should be good to go.
I have a question regarding internal files in android.. I tried to write some data into a file and then read it back however, it seems like I can't write data to a file unless I cast it to an integer first.. is there anyway that I can save double or float values.. I added the code I'm trying to use below:
FormatCluster formatCluster = ((FormatCluster)objectCluster.returnFormatCluster(ofFormats,"Calibrated"));
if (formatCluster != null) {
//Obtain data for text view
calibratedDataArray[0] = formatCluster.mData;
calibratedUnits = formatCluster.mUnits;
A.setText("data: " + formatCluster.mData);
String filename = "myfile";
//String string = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write((int)formatCluster.mData);//here I don't want to cast the value to integer
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
//testing.setText)
double ch;
StringBuffer fileContent = new StringBuffer("");
FileInputStream fis;
try {
fis = context.openFileInput( filename );
try {
while( (ch = fis.read()) != -1)
testing.setText(fileContent.append(ch));
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Envelope your InputStream and OutputStream with a DataInputStream and a DataOutputStream. These classes have the method you need
When I set a ringtone from my app works once, but when running the code again, it tries to create a duplicate entry in the media store, which creates problems. Without creating seperate unique file names for every sound file, I want to fix this problem.
I found this solution posted in an answer here: setting audio file as Ringtone
and am trying to use that to fix mine.
When I try it in my code below, I get two errors. One is an SQLiteException and the other is a RuntimeException which is caused by the squlite error, which is after the Java code.
String TAG = "CFFS";
File dir = new File(Environment.getExternalStorageDirectory()+ "/ringtones"); // Set base DIR where new ringtone will live
dir.mkdirs(); // create if directors don't exist
File outputFile = new File(dir, "College Fight Song.mp3"); // Define out new output file
Uri inURI = null;
try {
inURI = Uri.parse(getIntent().getStringExtra("com.carboni.fightsongs.FILE_RES_ID"));
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Could not get URI " + e);
}
// If we didn't parse a good URI then don't execute the code below
if (inURI != null) {
InputStream in = null;
// Get the input stream
try { in = new BufferedInputStream(this.getContentResolver().openInputStream(inURI)); }
catch (Exception e) { Log.e(TAG, "Exception getting input stream " + e); }
// Get the output stream
OutputStream out = null;
try { out = new FileOutputStream(outputFile); }
catch (Exception e) { Log.e(TAG, "Exception getting output stream " + e); }
// Again, if we don't have 2 good handles then don't try to read/write them
if ((in != null) && (out != null)) {
byte[] buf = new byte[1024]; // Define our buffer size
int bytesRead = 0;
while (bytesRead >= 0) {
try {
bytesRead = in.read(buf, 0, buf.length); // Read max of 1024 bytes
if (bytesRead > 0)
out.write(buf); // Write buffer to new file if we got a good read
} catch (Exception e) {
Log.e(TAG,"Exception reading " + e);
e.printStackTrace();
}
}
}
// Close out handles and proceed
try {
in.close();
out.close();
}
catch (Exception e) { Log.e(TAG, "Exception closing streams " + e); }
ContentValues v = new ContentValues();
v.put(MediaStore.MediaColumns.DATA, outputFile.getAbsolutePath());
v.put(MediaStore.MediaColumns.TITLE, "College Football Fight Song");
v.put(MediaStore.MediaColumns.SIZE, outputFile.length());
v.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
v.put(MediaStore.Audio.Media.IS_RINGTONE, true);
Uri pURI = MediaStore.Audio.Media.getContentUriForPath(outputFile.getAbsolutePath());
// remove entry every time so we don't get duplicate entries and have a problem setting a 2nd time
getContentResolver().delete(pURI, MediaStore.MediaColumns.DATA + "\"" + outputFile.getAbsolutePath() + "\"", null);
Uri nURI = this.getContentResolver().insert(pURI, v);
Log.i(TAG, "Setting ringtone URI to " + nURI);
// Set ringtone
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, nURI);
Toast.makeText(this, "Ringtone set", Toast.LENGTH_LONG).show();
ERROR:
09-03 14:16:08.343: ERROR/DatabaseUtils(11968): android.database.sqlite.SQLiteException: near ""/mnt/sdcard/ringtones/College Fight Song.mp3"": syntax error: , while compiling: DELETE FROM audio_meta WHERE _data"/mnt/sdcard/ringtones/College Fight Song.mp3"
It looks like the error is this line:
getContentResolver().delete(pURI, MediaStore.MediaColumns.DATA + "\"" + outputFile.getAbsolutePath() + "=\"", null);