420 likes | 666 Views
Cosc 4730. Files: BB: File Connection Optional Package Android: Internal and External storage. Note about Streams. In Java SE We use BufferedWriter and BufferedReader streams for most io These are not available Generally we get InputStream and OutputStream
E N D
Cosc4730 Files: BB: File Connection Optional Package Android: Internal and External storage
Note about Streams. • In Java SE • We use BufferedWriter and BufferedReader streams for most io • These are not available • Generally we get InputStream and OutputStream • And pass them to DataInputStream and DataOutputStream • On the BB we can also use the InputStreamReader and outputStreamWriter
DataOutputStream • DyteArrayOutputStreambaos = new ByteArrayOutputStream(); • DataOutputStream dos = new DataOutputStream(baos); • New you write records data to dos use one or more methods • write: writes an array of bytes, with an offset and length of byte array • writeBoolean: writes a boolean to the stream • writeByte: writes one byte to the stream • writeChar: writes one character to the stream • writeChars: write a String as a sequence of characters • writeDouble: converts Double to long (doubleToLongBits) and writes long to stream • writeFloat: converts float to a int (floatToIntBits) and writes the int to the stream • writeInt: writes an integer to the stream • writeLong: writes a long to the stream • writeShort: writes a short intger to the stream • writeUTF: writes a String using UTF-8 encoding to the stream • Once that's done, use baos variable to create the byte variable • byte[] bytes = boas.toByteArray();
DataInputStream • When reading back the data: • byteArrayInputStreambais = new ByteArrayInputStream(bytes); • where bytes is the array of bytes read from the RecordStore • DataInputStreamdis = new DataINputStream(bais); • Now read it back the same way it written, using: • read: Reads an array of bytes from the stream • readBoolean: Reads a boolean from the stream • readByte: Reads a single byte from the stream • readChar: Reads a character from the stream • readDouble: Reads a long from the stream and converts it to a double • readFloat: reads an int from the stream and converts it to a float • readInt: reads an integer from the stream • readLong: reads long integer from the stream • readShort: read a short integer from the stream • readUTF: reads a string in UTF-8 enconding.
File Connection Optional Package • fcop as the name states is an optional package, which may not be on be on every phone. • Does the phone even have a "file system". If not, then fcop won't be there either. • Most phones that take memory cards, should have fcop though. • A note, fcop is also bundled with the PIM optional packages as well.
How it connects to the O/S • The connector class creates the instances of the FileConnection interface to manage the access to the files on the device's file system. • Connector gives you access to input and output streams as well.
Is FCOP present? • If you are writing for multiple phones, you may have figure out if it exists on that phone at runtime. • Some simple code to know if it exists or not. String cv = System.getProperty("microedition.io.file.FileConnection.version"); if (cv != null) { System.out.println("FCOP is present"); System.out.println("Version is "+cv); //yes, FCOP is present. cv may say "1.0", but any non null says it exists } else { //no FCOP is present, use RecordStore? }
Root file system. • "file:///" required to access the file system. • NOTE: Three forward slashes are required. • But after that, it phone specific. • Such as names of media cards • "file:///MediaCard/", "file:///root1/", etc. • Get some default directories • String srcdir = System.getProperty("fileconn.dir.photos"); • fileconn.dir.photos: Image capture through your Mobile camera. • fileconn.dir.videos: Video capture through your Mobile camera. • fileconn.dir.tones: Ring tones default directory. • fileconn.dir.memorycard: Memory Card / SD Card / Flash Drive root directory • see http://www.blackberry.com/developers/docs/5.0.0api/java/lang/System.html PDAP section for a complete list.
Finding root file systems • FileSystemRegistry.listRoots() • returns an Enumeration of root the file Systems • Example to list each the root filesystem Enumeration drives = FileSystemRegistry.listRoots(); while (drives.hasMoreElements()) { String driveString = drives.nextElement().toString(); System.out.println(driveString + "\n"); } } Output: system/ SDCard/ • Note, to access these, you need to add file:/// to them • file:///SDCard/
Opening a Filesystem • Uses the Connector to make a access the filesystem. String fs = "file:/// SDCard /"; //assuming SDCard / is a filesystem. FileConnectionfc = (FileConnection) Connector.open(fs); • Now we use fc and the methods in FileConnection
FileConnection directory methods • long availableSize() • Free memory on available on the file system for (files or directories). • booleancanRead() • Checks if the file or directory is readable. • booleancanWrite() • Checks if the file or directory is writable. • long directorySize(booleanincludeSubDirs) • Determines the size in bytes on a file system of all of the files that are contained in a directory.
FileConnection directory methods (2) • Enumeration list() • Gets a list of all visible files and directories contained in a directory. • Enumeration list(String filter, booleanincludeHidden) • Gets a filtered list of files and directories contained in a directory. • Note, filter string, can use wildcard * • To see everything including hidden list("*", true);
Directory list example try { FileConnection fc = (FileConnection) Connector.open("file:///SDCard/"); Enumeration files = fc.list(); while (files.hasMoreElements()) { System.out.println((String)files.nextElement()); } } catch (IOException ex) { //failed to open }
FileConnection directory methods (3) • void mkdir() • Creates a directory corresponding to the directory string provided in the Connector.open() method. • Example • fc = (FileConnection) Connector.open("file://root1/mydir"); • fc.mkdir(); • void setReadable(boolean readable) • Sets the file or directory readable attribute to the indicated value. • void setWritable(boolean writable) • Sets the selected file or directory writable attribute to the indicated value. • void rename(String newName) • Renames the selected file or directory to a new name in the same directory. • boolean exists() • Checks if the file or directory specified in the URL passed to the Connector.open() method exists. • booleanisDirectory() • Checks if the URL passed to the Connector.open() is a directory. • void close() • Closes the connection
File I/O • we can use the following streams • DataInputStreamopenDataInputStream() • Open and return a data input stream for a connection. • DataOutputStreamopenDataOutputStream() • Open and return a data output stream for a connection. • InputStreamopenInputStream() • Open and return an input stream for a connection. • OutputStreamopenOutputStream() • Open and return an output stream for a connection.
FileConnection File methods • Look for some in the Directory methods. • void create() • Creates a file corresponding to the file string provided in the Connector.open() method for this FileConnection • long fileSize() • Determines the size of a file on the file system. • booleanisHidden() • Checks if the file is hidden. • booleanisOpen() • Returns an indication of whether the file connection is currently open or not. • void setFileConnection(String fileName) • Resets this FileConnection object to another file or directory.
Open a file. • Uses same connector.open() • but need to specify one more parameter. • Connector.READ • Connector.READ_WRITE • Connector.WRITE
File Example import javax.microedition.io.*; import javax.microedition.io.file.*; import java.io.*; import java.util.*; • First let's create the file and write something to it. String fs = "file:///SDCard/myfile.txt"; FileConnectionfc = (FileConnection) Connector.open(fs,Connector.WRITE); fc.create(); DataOutputStream dos = fc.openDataOutputStream(); dos.writeUTF("Hi there."); dos.close(); //close everything and return the resources. fc.close(); • Now read back the information. fc= (FileConnection) Connector.open(fs,Connector.READ); DataInputStreamdis = fc.openDataInputStream(); String t = dis.readUTF(); dis.close(); fc.close(); System.out.println("read from file: "+t);
The other 2 streams • If you want to read/write text instead of bytes, then you can use the OpenInputStream and OpenOutputStream • And use the InputStreamReader and outputStreamWriter • output example: String t = "Hi There"; OutputStreamWriter out = new OutputStreamWriter(fc.openOutputStream()); out.write(t); out.close(); fc.close();
The other 2 streams (2) • input is a little harder, since InputStreamReader read() returns one character at a time and it's an integer value fc= (FileConnection) Connector.open(fs,Connector.READ); InputStreamReader in = new InputStreamReader(fc.openInputStream()); t = ""; //now read in the text file, one character at a time. inti = in.read(); while (i !=-1) { //To stop at end of line use (i !=-1 && (char) i != '\n') t += (char)i; i = in.read(); } fc.close(); System.out.println("read from file: "+t);
The other 2 streams (2) • Using these can make things simpler. • But • Now you have split up the strings • String tokenizers covered at the end of this lecture. • Convert numbers to the correct type. • Otherwise • Now you can read text files created on most machines and write files that can be read by most computers as well.
PrintStream • You may also find the printStream useful as well for output. • one doesn't throw exceptions, sets a status flag • Uses print and println • Example String t = "Hi There"; int x = 12; PrintStream out = new PrintStream(fc.openOutputStream()); out.println(t); out.print(x); out.print(" "); out.println(x);
FileSystemListener • There is a listener, to see if the root file systems have changed (removed/added) • You override the default rootChanged (int state, String rootName) method • state is based on ROOT_ADDED or ROOT_REMOVED • rootName is the name of the changed root File System
Lastly • Apps can do a lot of damage with direct access to the file system. • vendors can/do two things: • Hide sections of the file system from third party applications. • Require third party applications to be signed, before they can access the file system. • but not needed for the emulators. • Blackberry only requires a signature for DRM file accessor methods.
Static files in the COD • You can read files out of the COD file as well. • Uses the Class method to find cod on the filesystem. • Returns a InputStream Class classs = Class.forName("edu.cs4755.fileSystem"); //to actually retrieve the resource prefix the name of the file with a "/" InputStreamis = classs.getResourceAsStream(“/file.txt”);
Android and data Storage • There are several methods to store data • Preferences • is a lightweight mechanism to store and retrieve key-value pairs of primitive data types. It is typically used to store application preferences • Content Providers • Only method to "share" information between applications. • Files System • Databases
Internal vs External storage • Internal storage • You can save files directly on the device's internal storage. • By default, files saved to the internal storage are private to your application and other applications cannot access them (nor can the user). • When the user uninstalls your application, these files are removed. • External storage • This can be a removable storage media (such as an SD card) or an internal (non-removable) storage. • Files saved to the external storage are world-readable and can be modified by the user when they enable USB mass storage to transfer files on a computer.
Internal Storage • FileOutputStreamopenFileOutput(String File, MODE) • File: the filename for output • MODE: Context.MODE_PRIVATE, MODE_APPEND, MODE_WORLD_READABLE, and MODE_WORLD_WRITEABLE. • Note If the file already exists, then it will be overwritten, except with MODE_APPEND. • It returns a FileOutputStream, which we then send to DataOutputStream. • Close() when you are finished with the file.
Internal Storage (2) • FileInputStreamopenFileInput(String File) • Open the files named. • Again, send it to DataInputStream for ease of reading. • getFilesDir() • Gets the absolute path to the filesystem directory where your internal files are saved. • getDir() • Creates (or opens an existing) directory within your internal storage space. • deleteFile() • Deletes a file saved on the internal storage. • String[] fileList() • Returns an array of files currently saved by your application.
Internal Example • Output dos = new DataOutputStream( openFileOutput("FileExample", Context.MODE_PRIVATE)); dos.writeUTF("First line of the file"); dos.writeUTF(“Second line of the file"); dos.close(); • Input String flist[] = fileList(); in = new DataInputStream( openFileInput(flist[0]) ) ; while(true) try { label1.append(in.readUTF() + "\n"); //label1 is a TextView } catch (EOFException e) { //reach end of file in.close(); }
Files in the apk • If you have a static (read only) file to package with your application at compile time, you can save the file in your project in res/raw/myDataFile, and then open it with getResources().openRawResource (R.raw.myDataFile). • It returns an InputStream object that you can use to read from the file.
External files • Before accessing files on external storage, you’ll need to check to see if the media is available. • Code to check booleanmExternalStorageAvailable = false;booleanmExternalStorageWriteable = false;String state = Environment.getExternalStorageState();if (Environment.MEDIA_MOUNTED.equals(state)) { // We can read and write the mediamExternalStorageAvailable = mExternalStorageWriteable = true;} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { // We can only read the mediamExternalStorageAvailable = true;mExternalStorageWriteable = false;} else { // Something else is wrong. It may be one of many other states, but all we need // to know is we can neither read nor writemExternalStorageAvailable = mExternalStorageWriteable = false;}
External Files (2) • //API 8 and above • getExternalFilesDir() • For none shared files • Creates the directory /Android/data/<package_name>/files/ • Directory and all files deleted when app is uninstalled. • getExternalStoragePublicDirectory() • For files that are to be shared. • Not deleted when app is uninstalled.
External Files (3) • File file = new File(getExternalFilesDir(null), “myfile.txt"); • Create directory if needed and the spot for the file, called myfile.txt • null: it’s a file for my application • If I wanted a music directory then • File file = new File(getExternalFilesDir( Environment.DIRECTORY_MUSIC), “file.mp3"); • Place in the a subdirectory of music.
External Files (4) • Read • in = new DataInputStream(new FileInputStream(file) ); • Write • dos = new DataOutputStream(new FileOutputStream(file) ); • Append: • dos = new DataOutputStream(new FileOutputStream(file),true ); • Read or write as normal. Then close the file when you are done. • Other useful methods of file • file.exists() //return true if file exists • file.delete(); //deletes the file • See http://developer.android.com/reference/java/io/File.html for more.
external files (5) • getExternalStoragePublicDirectory() File path = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES); • There is no NULL version. File file = new File(path, "DemoPicture.jpg"); // Make sure the directory exists.path.mkdirs();//Now use file just like before.
Additional notes. Strings
Breaking up strings. • Blackberry • Note, neither split nor StringTokenizer are not included in JavaME, so Blackberrydoes not include it either. • There is a very simple “split” in the StringUtilities package, call stringToWords and stringToKeywords which splits on non-characters. • For full split function see the following doc. It is also included in the blackberry filesystem example. • Android • the string.split(String RegularExpression) is included on Android. So String[] = line.split(“ “) would break up the string in line based on a space and put the resulting string array • Java.util has the StringTokenizer, but considered “legacy”.
Q A &