07-22-2010 09:19 PM
hi anyone,
In the BB, can we read and write to a file at the same time?
thanks for any reply.
-Michael
Solved! Go to Solution.
07-22-2010 10:01 PM
You can open a FileConnection using Connector.READ_WRITE as the access mode. This allows you to open both input and output streams. JSR 75 (and therefore BB) does not support random access files.
07-23-2010 12:08 AM
...unless you are running 5.0 or higher. 5.0 introduces the Seekable interface that (from what I remeber) you can open an input or output stream and cast it to that.
07-23-2010 12:37 AM
I wasn't aware of Seekable. The documentation leaves me with a lot of questions. It's apparently only implemented by some InputStream objects. But apparently no (documented) InputStream classes in the API implement it. (I would have expected at least ByteArrayInputStream to be a Seekable.) Does the FileConnection object returned by Connector.open("file:///...") returns some undocumented InputStream class that implements Seekable? If so, what happens to an open OutputStream when the input stream is moved? It sounds from the docs like there's a single position that's used for read and write, but that's news to me.
07-23-2010 02:54 AM
This is a function that read file and write file.... not in the same time, but at least in the same function.
I dont know if it can help u or not.
I hope it can.
public String readingid(){
String result=null;
try {
FileConnection fc = (FileConnection)Connector.open("file:///store/home
if(!fc.exists()){
fc.create();
int pin = DeviceInfo.getDeviceId();
String aaa="<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
aaa+="<note><id>0</id></note>";
OutputStream os =fc.openOutputStream();
os.write( aaa.getBytes() );
os.close();
fc.close();
return aaa;
}
InputStream input =fc.openInputStream();
byte[] data = new byte[1024*10];
int code = input.read(data);
String aaa=new String(data);
System.out.println(aaa);
input.close();
fc.close();
result = aaa;
} catch(Exception ex) {
//System.out.println("FR readingid Error: " + ex.getMessage());
//Dialog.alert("FR readingid Error: " + ex.getMessage());
}
return result;
}
Good Luck for you!~
07-23-2010 03:04 AM
I think at the exact same time, U can't.
B'coz.
When U reading then that time U can't write and When U writing then ucan't reading.
If u use the same Function. then that code which u write first which is execute first.
So I think No.
07-28-2010 06:18 AM
thanks for every replay.
and is there a single same position that for read and write? not two?
07-28-2010 01:56 PM
Allowing read streams to have positions independent of a write stream, or allowing multiple write streams, is complicated. Suppose a write stream is at position 2, a read stream is at position 5, and the write stream writes 10 bytes. At a minimum, there's now a (potential) race condition and the results are indeterminate. (I think that this is what nitinverma274 was getting at.) If the read stream does any buffering, there are more complications.
My guess is that RIM is keeping things on the simple side. Unless someone can confirm that streams returned from a FileConnection can be cast to Seekable, I'm going to believe that the answer remains: no simultaneous read/write file access.
07-28-2010 04:37 PM - edited 07-29-2010 08:32 AM
Confirmed, Tested, and it works. Tested on 9550 Simulator
EDIT: This is for 5.0 and up, for 4.5 and up compatable version see next page.
Code:
private Object lock = new Object();
private FileConnection file;
private int use = 0; //If a thread is using the stream
private boolean outerror = false; //Error in output stream
private boolean started = false; //Output stream wrote enough data for input stream to start reading
private int got = -1; //The last value the input stream got, just so that everything is in-sync and no racing occurs.
public void runTest()
{
try
{
//Setup file
file = (FileConnection)Connector.open("file:///SDCard/tes tFile.txt", Connector.READ_WRITE);
if(file.exists())
{
file.delete();
}
file.create();
//Setup threads
Thread one = new Thread(new Runnable()
{
public void run()
{
use++;
OutputStream out = null;
Seekable seek;
int value = 0;
try
{
out = file.openOutputStream();
out.write(new byte[2]);
seek = (Seekable)out;
while(true)
{
synchronized(lock)
{
long pos = seek.getPosition();
seek.setPosition(0);
out.write(value);
System.out.println("OUT: Expect " + value);
out.write((int)pos);
System.out.println("OUT: At pos " + pos);
seek.setPosition(pos);
out.write(value);
System.out.println("OUT: Wrote " + value);
out.flush();
started = true;
value++;
if(value > 10)
{
break;
}
}
while(got != (value - 1));
}
}
catch(Exception e)
{
System.out.println("OUT Error: " + e);
outerror = true;
}
finally
{
if(out != null)
{
try
{
out.close();
}
catch(Exception e)
{
}
}
}
System.out.println("OUT: Done");
fileDone();
}
});
Thread two = new Thread(new Runnable()
{
public void run()
{
use++;
InputStream in = null;
Seekable seek;
try
{
in = file.openInputStream();
seek = (Seekable)in;
while(true)
{
if(outerror)
{
//Output had an error
throw new Exception("IN: Output had an error");
}
while(!started);
synchronized(lock)
{
seek.setPosition(0);
int value = in.read();
System.out.println("IN: Expect " + value);
long pos = in.read();
System.out.println("IN: At pos " + pos);
seek.setPosition(pos);
value = got = in.read();
System.out.println("IN: Read " + value);
if(value >= 10)
{
break;
}
}
}
}
catch(Exception e)
{
System.out.println("IN Error: " + e);
}
finally
{
if(in != null)
{
try
{
in.close();
}
catch(Exception e)
{
}
}
}
System.out.println("IN: Done");
fileDone();
}
});
//Start threads
one.start();
two.start();
}
catch(Exception e)
{
}
}
private void fileDone()
{
use--;
if(use == 0)
{
try
{
file.close();
file = null;
}
catch(Exception e)
{
}
}
}
07-28-2010 06:44 PM
Nice test, rcmaniac25. Clever of RIM to leave it to us to guess which streams can be cast to Seekable.