I am using print writer and fileoutputstream to write a file in android async task using following function:
public static void saveFileToExternalMemoryAsync(Context context,String fileName, String json)throws Exception{
File AppPath = new File(Environment.getExternalStorageDirectory() + "/PDMA/DMAPPOutputs/");
if (!AppPath.exists()) {
AppPath.mkdirs();
}
File outputFile = new File(AppPath.getAbsolutePath() + "/" + fileName + ".dmapp");
if (!outputFile.exists())
outputFile.createNewFile();
MediaScannerConnection.scanFile(context, new String[] {AppPath.toString(),outputFile.toString()}, null, null);
FileOutputStream fileOutputStream = new FileOutputStream(outputFile, true);
PrintWriter pw = new PrintWriter(fileOutputStream);
try{
pw.println(json);
pw.flush();
pw.close();
fileOutputStream.flush();
fileOutputStream.close();
}catch (Exception e){
e.printStackTrace();
}finally{
pw.flush();
pw.close();
fileOutputStream.flush();
fileOutputStream.close();
MediaScannerConnection.scanFile(context, new String[] {AppPath.toString(),outputFile.toString()}, null, null);
}
}
problem is that when I try to copy this file by connecting mobile to pc in mtp, its not copied fully. If I right click to see its size, its less than actual. Now If in android, I copy and paste this file somewhere else, say in downloads folder, size is correct and file is also complete.
What can be the problem.
UPDATE:
If I use fileOutputStream to write bytes one by one , then file is generated but I have to close application to access this file from pc.
Well it turns out that by adding this.cancel(true) at the end of onPostExecute() solved problem in my case.
Related
I am creating an android application which reads and writes data to a file in the location /sdcard/ReadandWrite/.when i writing to that file it does not write in append mode.it will removes the old data and writes the new one.please help me to solve this.Here is my code.
private File openfile() {
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File (sdCard.getAbsolutePath() + "/ReadandWrite");
dir.mkdirs();
File file = new File(dir, "myfile.txt");
file.setWritable(true);
if(file.exists())
{
file.canRead();
file.setWritable(true);
}
else {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
private void writetofile() {
try {
File file=openfile();
OutputStreamWriter myOutWriter =
new OutputStreamWriter(new FileOutputStream(file));
myOutWriter.append(text.getText());
myOutWriter.close();
myOutWriter.close();
Toast.makeText(getBaseContext(),
"Done writing SD 'mysdfile.txt'",
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}
You need to configure the FileOutputStream to use append mode. From JDK documentation:
public FileOutputStream(String name,
boolean append)
throws FileNotFoundException
Creates a file output stream to write to the file with the specified
name. If the second argument is true, then bytes will be written to
the end of the file rather than the beginning. A new FileDescriptor
object is created to represent this file connection.
First, if there is a security manager, its checkWrite method is called
with name as its argument.
If the file exists but is a directory rather than a regular file, does
not exist but cannot be created, or cannot be opened for any other
reason then a FileNotFoundException is thrown.
Parameters:
name - the system-dependent file name
append - if true, then bytes will be written to the end of the file rather than the beginning Throws:
FileNotFoundException - if the file exists but is a directory rather than a regular file, does not exist but cannot be created, or
cannot be opened for any other reason.
SecurityException - if a security manager exists and its checkWrite method denies write access to the file. Since:
JDK1.1 See Also:
SecurityManager.checkWrite(java.lang.String)
So change
OutputStreamWriter myOutWriter = new OutputStreamWriter(new FileOutputStream(file));
to
OutputStreamWriter myOutWriter = new OutputStreamWriter(new FileOutputStream(file, true));
saving socres to highscore.sav file, it works fine on desktop, but not on android. why?
String fileName = "highScores.sav";
file = new File(fileName);
public static void save(){
try{
FileOutputStream fileOut = new FileOutputStream(file);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(gd);
out.close();
}
catch(Exception e){
e.printStackTrace();
System.out.println(e);
Gdx.app.exit();
}
}
public static void load(){
try{
if(!saveFileExists()){
init();
return;
}
FileInputStream fileIn = new FileInputStream(file);
ObjectInputStream in = new ObjectInputStream(fileIn);
gd = (GameData) in.readObject();
in.close();
}
catch(Exception e){
e.printStackTrace();
System.out.println(e);
Gdx.app.exit();
}
}
got error: java.io.FileNotFoundException: /highScores.sav: open failed: EROFS (Read-only file system)
This isn't working because you have not specified a directory to save into. Android has tight restrictions on where an app can write files.
You don't need any permissions to read or write a file to internal memory. But you do need to specify internal memory (called local memory in libgdx).
Libgdx already handles this directly for you so you don't need to differentiate between desktop and Android. This explains exactly how to do it. All you need is the string or bytes you want to write into the file, and the libgdx API's handle the rest.
FileHandle file = Gdx.files.local(filename);
file.writeString(stringToWrite, false);
If you want to continue using your method of writing the file, you can get the path to the file like this:
String fileName = "highScores.sav";
file = new File(Gdx.files.getLocalStoragePath () + "/" + fileName);
Have you added the permission to the android app to allow writing to the storage space?
i'm using the below code to save log data to a file.
However, every time a new call is made, the old content is gone.....
i can't figure out what the issue is however....
public void writeToFile(String fileName, String textToWrite) {
FileOutputStream fOut = null;
try {
File root = new File(Environment.getExternalStorageDirectory() , fileName);
if (! root.exists()){
root.createNewFile();
}
fOut = new FileOutputStream(root);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
myOutWriter.append(textToWrite);
myOutWriter.flush();
myOutWriter.close();
}
catch (Exception e) {
new MailService().mailMessage(e.toString());
}
finally{
if(fOut != null){
try{
fOut.close();
}
catch(Exception ex){
}
}
}
}
You need to pass second parameter boolean true to FileOutputStream constructor which indicates the file will be opened in append mode rather than write mode.
FileOutputStream out=new FileOutputStream("myfile");
Everytime you execute the above code it will open the file in write mode so that the new content will overwrite the old content. However, the FileOutputStream constructor accepts a second argument which is a boolean indicating whether to open the file in append mode.
FileOutputStream out=new FileOutputStream("myfile",true);
The above code will open the file in append mode so that the new content will be appended to the end of old content.
To know more about FileOutputStream constructors see this.
I am working on an app in which I would like to save some Bitmaps to the SD Card. I have looked at a lot of examples and other questions, and from that I have made the following code:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
String dirPath = Environment.getExternalStorageDirectory().toString() + "/myFolder";
File dir = new File(dirPath);
dir.mkdirs();
String fileName = "bitmapname.jpg";
File file = new File(dirPath, fileName);
FileOutputStream fileOutPutStream;
try {
boolean created = file.createNewFile();
Log.d("Checks", "File created: " + created);
fileOutPutStream = new FileOutputStream(file);
fileOutPutStream.write(byteArrayOutputStream.toByteArray());
fileOutPutStream.close();
} catch (FileNotFoundException e) {
Log.d("Checks", "FileNotFoundException");
e.printStackTrace();
} catch (IOException e) {
Log.d("Checks", "IOException");
Log.d("Checks", e.getMessage());
e.printStackTrace();
}
I don't see what's wrong with this code. It doesn't give any errors and my app runs without crashing. However, when I connect my phone to my computer and open the SD Card I do not see the folder "myFolder" and I can not find the saved image anywhere. Do you guys have any ideas as to why this is?
EDIT: I noticed that I can see the saved bitmaps in the Android gallery, and they are indeed in a folder called "myFolder". However, I still don't see them when I connect my phone to my computer and browse my sd card.
From my experience I had similar issued when I forgot the fileOutPutStream.flush(); before the close().
Are you sure you are setting the permission to write to SD card? Try setting this one:
WRITE_EXTERNAL_STORAGE
Edit:
Ok, try this:
Environment.getExternalStorageDirectory().getAbsolutePath()
Instead of:
Environment.getExternalStorageDirectory().toString()
Or even create a directory like this:
File dir = new File(Environment.getExternalStorageDirectory() +
File.separator +
"myFolder");
dir.mkdirs();
I think I have looked at all of the relevant questions and I still can't get this to work.
Here is the code:
File sdCard = Environment.getExternalStorageDirectory();
File directory= new File (sdCard.getAbsolutePath() + appName);
directory.mkdirs();
File file = new File(directory,fileName);
The folder is created, but I get an error saying the file does not exist. appName is a string containing the name of the folder and that works correctly. fileName is a string containing the name of the file I want to include.
I have included the permission in the manifest.
What am I doing wrong?
Update:
The code tries to make a subdirectory and a file at the same time, which hidden because the code uses a named String rather than a String literal. Adding an intermediate step to create the subdirectory solved the problem.
If the directory is created, then you're on the right track. In your code you are not actually creating the file on the SD card. If you need to create the file, then do this:
File sdCard = Environment.getExternalStorageDirectory();
File file = new File(sdCard.getAbsolutePath() + appName + "/" + fileName);
directory.mkdirs();
file.createNewFile()
This is notional only. It would be much better to actually separate your fileName into a separate subfolder and the actual file and handle them separately.
Try this out:
In this I am creating a text file (.txt file) of a string.
public void createFileFromString(String text)
{
File logFile = new File("sdcard/xmlresponseiphone.txt");
if (!logFile.exists())
{
try
{
logFile.createNewFile();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try
{
//BufferedWriter for performance, true to set append to file flag
BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true));
buf.append(text);
buf.newLine();
buf.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Test this, and see what are you missing :)
Try with something like this. In this case I'm saving an image!
For creating the directory:
File directory = new File(Environment.getExternalStorageDirectory()
+ File.separator + appName);
directory.mkdirs();
And for saving into it
public void save(Bitmap graph, Context context, String name, String time, boolean now) throws IOException {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
graph.compress(Bitmap.CompressFormat.PNG, 100, bytes);
// you can create a new file name "test.jpg" in sdcard folder.
String fileName = "";
if (now){
fileName = getDateTime()+"_00"+".png";
}
else {
fileName = time.replace(".txt", ".png");
}
File f = new File(Environment.getExternalStorageDirectory()
+ File.separator + "appName/" + fileName);
f.createNewFile(); // write the bytes in file
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
}
I think the trick is in File.separator!