I'm writing a simple budget app for myself, and I'm having trouble figuring out how to write to internal storage. I don't seem to be writing to the file properly, and I can't find any more in depth examples than the Data Storage article on developer.android.com
Basically, I'm trying to write a test float to the MyBalance file, then read it into balance. In my actual code I use try/catch statements around the file in/out operations, but I skipped them to make the code more readable.
float test = 55;
float balance;
byte[] buffer = null;
FileOutputStream fos = openFileOutput( "MyBalance", Context.MODE_PRIVATE );
fos.write(Float.floatToRawIntBits(balance));
fis.read(buffer); //null pointer
ByteBuffer b = ByteBuffer.wrap(buffer);
balance=b.getFloat();
That's the gist of it, anyone see what I'm doing wrong?
Edit:
Thanks for the reply, I went ahead and converted to/from String like you suggested, but I still don't think the file is being created. I have an if statement that reads from it if it exists in onResume() and it isn't being run. Lemme post some of my code.
Here's how I'm writing the file, (setbal is an EditText and balanceview is a TextView):
balance = Float.valueOf(setbal.getText().toString());
balanceview.setText(setbal.getText());
balstring = String.valueOf(balance);
for (int i = 0; i < balstring.length(); ++i)
try {
fos.write((byte)balstring.charAt(i));
} catch (IOException e) {
e.printStackTrace();
}
I check if the file exists in onResume() like so:
File file = new File("data/data/com.v1nsai.mibudget/balance.txt");
Is that where an internal file for that context would be stored?
So this isn't exactly what you asked for, but this is how I have it working for Strings, and it may be helpful to you to see. (You could box the primatives and toString them of course if you wanted to use this code.)
Writing
FileOutputStream fos = context.openFileOutput("savedstate.txt", 0);
for (int i = 0; i < out.length(); ++i)
fos.write((byte)out.charAt(i));
Reading
StringBuilder inb = new StringBuilder();
FileInputStream fis = this.mContext.openFileInput("savedstate.txt");
int ch;
while((ch = fis.read()) != -1)
inb.append((char)ch);
Update
One thought that springs to mind is that you may not want to trust using a File object with a hand typed full path to the file. Instead, just use the FileInputStream with the context object and a relative path like in my code, then see if you get a String back of some length or something like that, or an exception that the file doesn't exist.
If you are really curious of where the file is created, or want to see it with your own eyes, I believe you can browse to it on your phone through the file manager in DDMS.
One last thing, I would suggest moving the try/catch block outside of your writing loop. Since it is an identical task being repeated, there is no need for the overhead of that approach, though it is typically good practice to minimize the size of your try/catch blocks.
Ok really one last thing, if you want to use the File object with the full path, you might want to have the path be the following:
File file = new File("/data/data/com.v1nsai.mibudget/balance.txt");
The beginning slash may make all the difference.
Related
I planned to use shared memory between an activity and a service in separate process to transfer big content between them.
To that end I read every info I have found on MemoryFile and how to transfer it between activity and specifically this stackoverflow entry what is the use of MemoryFile in android .
But I am unable to call getParcelFileDescriptor (using the described solution) on my android version 4.xx. It seems that the method does not exist anymore.
Nevertheless I come to the following code to send a ParcelFileDescriptor to my service
(take it as pseudo code, but in fact it is ruboto code):
shm = MemoryFile.new("picture", 1000)
f = shm.getFileDescriptor()
p = ParcelFileDescriptor.dup( f)
b = Bundle.new()
b.putParcelable( "shm", p)
msg.setData( b)
service.send( msg)
To test that the shared memory is properly accessible, I have written a string in it,
and try to retrieve it on the service side.
I have the following (true java) code to do that:
Parcelable p = msg.getData().getParcelable("shm");
ParcelFileDescriptor shm = (ParcelFileDescriptor) p;
FileDescriptor f = shm.getFileDescriptor();
if( f.valid()) {
FileInputStream in = new FileInputStream( f);
String s = readString( in); // this fail!
}
Every thing is ok, f is valid but I cannot read from the received fileDiscriptor, I get:
java.io.IOException: read failed: EINVAL (Invalid argument)
The code for the reading is the following:
public String readString(InputStream inputStream) throws IOException {
BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
String s = r.readLine();
return s;
}
So two question:
I am doing wrong ? (in any of the side)
or does the MemoryFile amputed from #getParcelFileDescriptor is now
unusable as a mean to share memory betweens two process ?
In this latter case, I fail to see any interest in this class then...
I have seen other article mentioning JNI code to used shared memory but would like to avoid that additional complexity.
I managed to transfer data between applications through a MemoryFile on Android 4.0.4 using shm.getFileDescriptor() and ParcelFileDescriptor.dup(f) so, fortunately, this class is still usable. In your case the problem may be in the content of the file, although I don't know how it can cause an Invalid argument error. Try writing and reading a fixed-length byte array instead of a string (which you don't actually write in the provided code) and read it simply with InputStream.read(buffer).
I saw this problem has been met many times, but strangely I was not able to find a solution.
I am trying to write a binary file to the SDcard. This is the source code:
private void saveDataLongs() {
try
{
ObjectOutputStream oos = new ObjectOutputStream(ctx.openFileOutput(Environment.getExternalStorageDirectory().getAbsolutePath()+"/longs.bin", ctx.MODE_WORLD_WRITEABLE));
for (int w=0; w<longCount; w++)
oos.writeLong(longs[w]);
oos.close();
}
catch(IOException e)
{ e.printStackTrace(); }
}
The Manifest contains
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
and I receive this error:
01-21 22:19:57.323: E/AndroidRuntime(13713): java.lang.RuntimeException: Unable to start activity ComponentInfo{it.ccc.ccc/it.ccc.ccc.Ccc}: java.lang.IllegalArgumentException: File /sdcard/longs.bin contains a path separator
From other posts I could understand that some functions are meant to write only in the private storage of the app, so they don't expect to manage directories and paths.
Is some one able to help me? Whall I use a different method to write the data to the sd, or just make some other action before doing it? I'm trying to write to the sdcard a simple binary file (btw it's a precalculated sequence of number, and I need to pass it to my PC and then move it back to the assets, so, if there is a different way to obtain this goal, it's ok anyway).
Thank you very much.
You say that you are trying to write to external storage, but you are calling openFileOutput(), which is for internal storage.
Change:
new ObjectOutputStream(ctx.openFileOutput(Environment.getExternalStorageDirectory().getAbsolutePath()+"/longs.bin", ctx.MODE_WORLD_WRITEABLE));
to:
new ObjectOutputStream(new FileOutputStream(new File(Environment.getExternalStorageDirectory(), "longs.bin")));
or, better yet, to:
new ObjectOutputStream(new FileOutputStream(new File(ctx.getExternalFilesDir(null), "longs.bin")));
I like CommonsWare's answer. I would simply like to add that if you ever DO want to go down a path, don't use /. Use File.separator. I don't think I've ever had any errors come up when simply using / but still.
So if you made a sub-folder called "To-dos" in the sdcard's directory, you would do something like the following:
new ObjectOutputStream(new File(Environment.getExternalStorageDirectory() + File.separator + "To-dos", "longs.bin"));
I have a android project and within that project I have a folder that contain some images.Now what i want is to access that folder within a jni function. So how should I do that?
An Android application is essentially a zip file, but there are a lot of nice helpers to get to those resources. First thing you need to remember is that these files are not actually in a folder, unless you put them there.
That said, there are a number of possible solutions for you situation.
JNI (almost) all the way
The most JNI-y way to go about things is to use have a method like
private native void processResources(AssetManager assets);
in your Activity, and use JNI to pry all the necessary resources from it, put them somewhere on disk, and process them.
Mix in a bit of Java
Probably an easier way is to have some Java code that helps with the resource management; something like
private void processAll() {
for (String resource : getResources().getAssets().list(mydir)) {
process(getResources().getAssets().open(resource));
}
// exception handling omitted for readability
}
private void process(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
for (int read = in.read(buf); read > 0; read = in.read(buf)) {
out.write(buf, 0, len);
}
process(out.toByteArray());
}
private native void process(byte[] resource);
and do the native processing based on the byte[].
Prepare files on the file system
A third solution is to move the files out of your bundle and onto the file system, and then point your native code to that directory.
So?
In the end, it all depends on what you exactly want to do with your resources, and whether or not they really need to be on the file system. I would keep things as close to Java as possible, and only go native when you really have to (e.g., your image manipulation code).
I have an app in which I have added Export/Import DB functionality... I want to do two things:
1) When exporting: Scramble the exported database so that normal folks (I know that some people can decode the best camouflage techniques) cannot read the contents...
2) When importing: Verify the file being imported to make sure that it is something that will work with my app and not anything else.
I have seen some links here about encryption that can address the 1st point here. But I dont want to do encryption. I want to do some simple scrambling. And I have seen some posts about verifying the table contents by checking for the tables that my application looks for. That is a good solution but i need to load the file first to verify and roll back if there are errors.
Any help would be greatly appreciated...
very very simple way: add some header to the file which you can later read back in and check:
// w/o exception handling finally etc
String secret = "zomg,secret";
byte[] header = secret.getBytes();
byte[] buffer = new byte[4096];
FileInputStream in = new FileInputStream("/your/sqlite.db");
FileOutputStream out = new FileOutputStream("/sdcard/the.secretfile");
out.write(header);
int read = 0;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
out.close();
in.close();
The best and simple way to deal with this is to generate Checksum (MD5) of your database file and compare with your per-calculated one. For more info
So I finally settled to doing DES encryption using cipherinputstream and instead of adding a header to verify the integrity, I am checking to see if all my table names are present in the file being imported. I saw that the sqlite DB file has the ddl statements in clear text. This is probably not the most elegant/complete solution but it works.
I am trying to obtain only one file (I know its name) from very large zip archive. This archive include around 100000 files because I do not want find my file in loop. I think that must be some solution for this case, something like command on Linux.
unzip archive.zip myfile.txt
I wrote following code
try {
FileInputStream fin = new FileInputStream(rootDir+"/archive.zip");
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = new ZipEntry("myfile.txt");
FileOutputStream fout = new FileOutputStream(rootDir+"/buff/" + ze.getName());
for (int c = zin.read(); c != -1; c = zin.read()) {
fout.write(c);
}
zin.closeEntry();
fout.close();
zin.close();
} catch(Exception e) {
Log.e("Decompress", "unzip", e);
}
This code create new file in buff directory, but this file is empty!
Please, help me with this trouble!
Thanks for your time!
I'm fairly new to Java, but the API documentation contains a pretty reasonable amount of information for the standard Java libraries, including for java.util.zip. Going from there into the ZipFile Entry, you can scroll down to the method listing to find a method called getEntry. This seems to be the route you should start with!
EDIT: bear in mind that you will probably need to include the directory (e.g.: "dir\subdirF\subdirW\FileThatYouWant.txt") when making the call, since that seems to be the way the files are named when you go through one-by-one.
EDIT 2: a considerable wealth of information is available here: Compressing and Decompressing Data Using Java APIs, if you're willing to read a bit :D.
Subject to memory constraints, the only reasonable solution for you might be to use a ZipInputStream object, which AFAIK will require you to step through each ZipEntry in the archive (on average 50,000?), but will not require you to load the entire file into memory. As far as performance, I would guess manually stepping through would be just as efficient as any current implementation of this niche functionality.