Methods Summary |
---|
public void | delete()Delete the atomic file. This deletes both the base and backup files.
mBaseName.delete();
mBackupName.delete();
|
public void | failWrite(java.io.FileOutputStream str)Call when you have failed for some reason at writing to the stream
returned by {@link #startWrite()}. This will close the current
write stream, and roll back to the previous state of the file.
if (str != null) {
sync(str);
try {
str.close();
mBaseName.delete();
mBackupName.renameTo(mBaseName);
} catch (IOException e) {
Log.w("AtomicFile", "failWrite: Got exception:", e);
}
}
|
public void | finishWrite(java.io.FileOutputStream str)Call when you have successfully finished writing to the stream
returned by {@link #startWrite()}. This will close, sync, and
commit the new data. The next attempt to read the atomic file
will return the new file stream.
if (str != null) {
sync(str);
try {
str.close();
mBackupName.delete();
} catch (IOException e) {
Log.w("AtomicFile", "finishWrite: Got exception:", e);
}
}
|
public java.io.File | getBaseFile()Return the path to the base file. You should not generally use this,
as the data at that path may not be valid.
return mBaseName;
|
public java.io.FileInputStream | openRead()Open the atomic file for reading. If there previously was an
incomplete write, this will roll back to the last good data before
opening for read. You should call close() on the FileInputStream when
you are done reading from it.
Note that if another thread is currently performing
a write, this will incorrectly consider it to be in the state of a bad
write and roll back, causing the new data currently being written to
be dropped. You must do your own threading protection for access to
AtomicFile.
if (mBackupName.exists()) {
mBaseName.delete();
mBackupName.renameTo(mBaseName);
}
return new FileInputStream(mBaseName);
|
public byte[] | readFully()A convenience for {@link #openRead()} that also reads all of the
file contents into a byte array which is returned.
FileInputStream stream = openRead();
try {
int pos = 0;
int avail = stream.available();
byte[] data = new byte[avail];
while (true) {
int amt = stream.read(data, pos, data.length-pos);
//Log.i("foo", "Read " + amt + " bytes at " + pos
// + " of avail " + data.length);
if (amt <= 0) {
//Log.i("foo", "**** FINISHED READING: pos=" + pos
// + " len=" + data.length);
return data;
}
pos += amt;
avail = stream.available();
if (avail > data.length-pos) {
byte[] newData = new byte[pos+avail];
System.arraycopy(data, 0, newData, 0, pos);
data = newData;
}
}
} finally {
stream.close();
}
|
public java.io.FileOutputStream | startWrite()Start a new write operation on the file. This returns a FileOutputStream
to which you can write the new file data. The existing file is replaced
with the new data. You must not directly close the given
FileOutputStream; instead call either {@link #finishWrite(FileOutputStream)}
or {@link #failWrite(FileOutputStream)}.
Note that if another thread is currently performing
a write, this will simply replace whatever that thread is writing
with the new file being written by this thread, and when the other
thread finishes the write the new write operation will no longer be
safe (or will be lost). You must do your own threading protection for
access to AtomicFile.
// Rename the current file so it may be used as a backup during the next read
if (mBaseName.exists()) {
if (!mBackupName.exists()) {
if (!mBaseName.renameTo(mBackupName)) {
Log.w("AtomicFile", "Couldn't rename file " + mBaseName
+ " to backup file " + mBackupName);
}
} else {
mBaseName.delete();
}
}
FileOutputStream str = null;
try {
str = new FileOutputStream(mBaseName);
} catch (FileNotFoundException e) {
File parent = mBaseName.getParentFile();
if (!parent.mkdir()) {
throw new IOException("Couldn't create directory " + mBaseName);
}
try {
str = new FileOutputStream(mBaseName);
} catch (FileNotFoundException e2) {
throw new IOException("Couldn't create " + mBaseName);
}
}
return str;
|
static boolean | sync(java.io.FileOutputStream stream)
try {
if (stream != null) {
stream.getFD().sync();
}
return true;
} catch (IOException e) {
}
return false;
|