数据写入读取

来源:互联网 发布:阿里巴巴数据库在哪 编辑:程序博客网 时间:2024/05/23 02:05
  1. <!-- 往SDCard写入数据权限 -->  
  2. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
  3. <!-- 在SDCard中创建与删除文件权限 -->  
  4. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />  


[java] view plain copy
 print?
  1. package com.ppmeet;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileOutputStream;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8.   
  9. import org.apache.http.util.EncodingUtils;  
  10.   
  11. import android.content.Context;  
  12.   
  13. /** 
  14.  * class name:FileService<BR> 
  15.  * class description:android文件的一些读取操作<BR> 
  16.  * PS: <BR> 
  17.  *  
  18.  * @version 1.00 2010/10/21 
  19.  * @author CODYY)peijiangping 
  20.  */  
  21. public class FileService {  
  22.     private Context context;  
  23.   
  24.     public FileService(Context c) {  
  25.         this.context = c;  
  26.     }  
  27.   
  28.     // 读取sd中的文件  
  29.     public String readSDCardFile(String path) throws IOException {  
  30.         File file = new File(path);  
  31.         FileInputStream fis = new FileInputStream(file);  
  32.         String result = streamRead(fis);  
  33.         return result;  
  34.     }  
  35.   
  36.     // 在res目录下建立一个raw资源文件夹,这里的文件只能读不能写入。。。  
  37.     public String readRawFile(int fileId) throws IOException {  
  38.         // 取得输入流  
  39.         InputStream is = context.getResources().openRawResource(fileId);  
  40.         String result = streamRead(is);// 返回一个字符串  
  41.         return result;  
  42.     }  
  43.   
  44.     private String streamRead(InputStream is) throws IOException {  
  45.         int buffersize = is.available();// 取得输入流的字节长度  
  46.         byte buffer[] = new byte[buffersize];  
  47.         is.read(buffer);// 将数据读入数组  
  48.         is.close();// 读取完毕后要关闭流。  
  49.         String result = EncodingUtils.getString(buffer, "UTF-8");// 设置取得的数据编码,防止乱码  
  50.         return result;  
  51.     }  
  52.   
  53.     // 在assets文件夹下的文件,同样是只能读取不能写入  
  54.     public String readAssetsFile(String filename) throws IOException {  
  55.         // 取得输入流  
  56.         InputStream is = context.getResources().getAssets().open(filename);  
  57.         String result = streamRead(is);// 返回一个字符串  
  58.         return result;  
  59.     }  
  60.   
  61.     // 往sd卡中写入文件  
  62.     public void writeSDCardFile(String path, byte[] buffer) throws IOException {  
  63.         File file = new File(path);  
  64.         FileOutputStream fos = new FileOutputStream(file);  
  65.         fos.write(buffer);// 写入buffer数组。如果想写入一些简单的字符,可以将String.getBytes()再写入文件;  
  66.         fos.close();  
  67.     }  
  68.   
  69.     // 将文件写入应用的data/data的files目录下  
  70.     public void writeDateFile(String fileName, byte[] buffer) throws Exception {  
  71.         byte[] buf = fileName.getBytes("iso8859-1");  
  72.         fileName = new String(buf, "utf-8");  
  73.         // Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND  
  74.         // Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。  
  75.         // Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。  
  76.         // MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。  
  77.         // 如果希望文件被其他应用读和写,可以传入:  
  78.         // openFileOutput("output.txt", Context.MODE_WORLD_READABLE +  
  79.         // Context.MODE_WORLD_WRITEABLE);  
  80.         FileOutputStream fos = context.openFileOutput(fileName,  
  81.                 Context.MODE_APPEND);// 添加在文件后面  
  82.         fos.write(buffer);  
  83.         fos.close();  
  84.     }  
  85.   
  86.     // 读取应用的data/data的files目录下文件数据  
  87.     public String readDateFile(String fileName) throws Exception {  
  88.         FileInputStream fis = context.openFileInput(fileName);  
  89.         String result = streamRead(fis);// 返回一个字符串  
  90.         return result;  
  91.     }  
  92. }  


《------------------------------------------------------------------------------------------------》

一、序言

        IO操作,才程序中比较普遍,JAVA 中提出了IO/NIO 的概念,也一直在说NIO 比IO快,一直不知道原因,就想memcache 和ehcache 比较优劣一样,这些东西得自己看看如何实现的,才 知道区别,从而才知道优劣以及试用范围,而不仅仅是“听说”!这里我可以先了解下JAVA 如何操作IO的。

 

二、代码示例

       我们先看看简单文件操作:

       

Java代码  收藏代码
  1. // 这是将文件转换成输入流的的一种方式,获得了流我们就能干很多事  
  2. FileInputStream in = new FileInputStream(new File("...file"));  
 

 

       再看看FileInputStream 的源码:

    

Java代码  收藏代码
  1. public FileInputStream(File file) throws FileNotFoundException {  
  2.     String name = (file != null ? file.getPath() : null);  
  3.         // 安全管理器,这里暂时不说  
  4.     SecurityManager security = System.getSecurityManager();  
  5.     if (security != null) {  
  6.             // 检查是否可以按这名字读取  
  7.         security.checkRead(name);  
  8.     }  
  9.         if (name == null) {  
  10.             throw new NullPointerException();  
  11.         }  
  12.         // 获得文件描述,这个JDK 未公布  
  13.     fd = new FileDescriptor();  
  14.         // 打开文件,这是个native 方法,我们可以用openjdk 看看里面  
  15.     open(name);  
  16.     }  
 

 

  在FileInputStream.c下可以找到方法

    

Java代码  收藏代码
  1. // open 方法  
  2. JNIEXPORT void JNICALL  
  3. Java_java_io_FileInputStream_open(JNIEnv *env, jobject this, jstring path) {  
  4.     fileOpen(env, this, path, fis_fd, O_RDONLY);  
  5. }  
 

 

    OK。我们从该文件上面的引用io_util_md.c找到实现:

   

Java代码  收藏代码
  1. void  
  2. fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)  
  3. {  
  4.     jlong h = winFileHandleOpen(env, path, flags);  
  5.     if (h >= 0) {  
  6.         // 设置fd 的值  
  7.         SET_FD(this, h, fid);  
  8.     }  
  9. }  
 

 

 

    在上面文件里面可以看到:winFileHandleOpen,

   

Java代码  收藏代码
  1. jlong  
  2. winFileHandleOpen(JNIEnv *env, jstring path, int flags)  
  3. {  
  4.     const DWORD access =  
  5.         (flags & O_RDWR)   ? (GENERIC_WRITE | GENERIC_READ) :  
  6.         (flags & O_WRONLY) ?  GENERIC_WRITE :  
  7.         GENERIC_READ;  
  8.     const DWORD sharing =  
  9.         FILE_SHARE_READ | FILE_SHARE_WRITE;  
  10.     const DWORD disposition =  
  11.         /* Note: O_TRUNC overrides O_CREAT */  
  12.         (flags & O_TRUNC) ? CREATE_ALWAYS :  
  13.         (flags & O_CREAT) ? OPEN_ALWAYS   :  
  14.         OPEN_EXISTING;  
  15.     const DWORD  maybeWriteThrough =  
  16.         (flags & (O_SYNC | O_DSYNC)) ?  
  17.         FILE_FLAG_WRITE_THROUGH :  
  18.         FILE_ATTRIBUTE_NORMAL;  
  19.     const DWORD maybeDeleteOnClose =  
  20.         (flags & O_TEMPORARY) ?  
  21.         FILE_FLAG_DELETE_ON_CLOSE :  
  22.         FILE_ATTRIBUTE_NORMAL;  
  23.     const DWORD flagsAndAttributes = maybeWriteThrough | maybeDeleteOnClose;  
  24.     HANDLE h = NULL;  
  25.   
  26.     if (onNT) {  
  27.         WCHAR *pathbuf = pathToNTPath(env, path, JNI_TRUE);  
  28.         if (pathbuf == NULL) {  
  29.             /* Exception already pending */  
  30.             return -1;  
  31.         }  
  32.         h = CreateFileW(  
  33.             pathbuf,            /* Wide char path name */  
  34.             access,             /* Read and/or write permission */  
  35.             sharing,            /* File sharing flags */  
  36.             NULL,               /* Security attributes */  
  37.             disposition,        /* creation disposition */  
  38.             flagsAndAttributes, /* flags and attributes */  
  39.             NULL);  
  40.         free(pathbuf);  
  41.     } else {  
  42.         WITH_PLATFORM_STRING(env, path, _ps) {  
  43.             h = CreateFile(_ps, access, sharing, NULL, disposition,  
  44.                            flagsAndAttributes, NULL);  
  45.         } END_PLATFORM_STRING(env, _ps);  
  46.     }  
  47.     if (h == INVALID_HANDLE_VALUE) {  
  48.         int error = GetLastError();  
  49.         if (error == ERROR_TOO_MANY_OPEN_FILES) {  
  50.             JNU_ThrowByName(env, JNU_JAVAIOPKG "IOException",  
  51.                             "Too many open files");  
  52.             return -1;  
  53.         }  
  54.         throwFileNotFoundException(env, path);  
  55.         return -1;  
  56.     }  
  57.     return (jlong) h;  
  58. }  

 

   

 

  好吧,上面代码我也搞不明白- -,但是这几句代码:

  

Java代码  收藏代码
  1.   h = CreateFileW(  
  2.             pathbuf,            /* Wide char path name */  
  3.             access,             /* Read and/or write permission */  
  4.             sharing,            /* File sharing flags */  
  5.             NULL,               /* Security attributes */  
  6.             disposition,        /* creation disposition */  
  7.             flagsAndAttributes, /* flags and attributes */  
  8.             NULL);  
  9.   
  10. 以及  
  11.    WITH_PLATFORM_STRING(env, path, _ps) {  
  12.             h = CreateFile(_ps, access, sharing, NULL, disposition,  
  13.                            flagsAndAttributes, NULL);    

 

   我的理解是,这里通过CreateFileW方法,创建了一个类似文件描述的结构,然后通过CreateFile调windows 下面的底层方法,填充这个结构的数据,那么这个文件对象就能被我们上层对象识别了,就能是获取里面的资源。

  OK,我们现在创建了对文件之间的连接,拿到文件流对象之后,来看看我们常用的read 方法。

   

Java代码  收藏代码
  1. // 对字节的操作  
  2. public native int read() throws IOException;  
  3. private native int readBytes(byte b[], int off, int len) throws IOException;  

 

  

  在FileInputStream.c 里面同样可以找到

  

Java代码  收藏代码
  1. JNIEXPORT jint JNICALL  
  2. Java_java_io_FileInputStream_read(JNIEnv *env, jobject this) {  
  3.     return readSingle(env, this, fis_fd);  
  4. }  
  5.   
  6. JNIEXPORT jint JNICALL  
  7. Java_java_io_FileInputStream_readBytes(JNIEnv *env, jobject this,  
  8.         jbyteArray bytes, jint off, jint len) {  
  9.     return readBytes(env, this, bytes, off, len, fis_fd);  
  10. }  

 

 

    继续看io_util.c 里面:

   

Java代码  收藏代码
  1. jint  
  2. readSingle(JNIEnv *env, jobject this, jfieldID fid) {  
  3.     jint nread;  
  4.     char ret;  
  5.     FD fd = GET_FD(this, fid);  
  6.     if (fd == -1) {  
  7.         JNU_ThrowIOException(env, "Stream Closed");  
  8.         return -1;  
  9.     }  
  10.     // 看出是一个一个的读取,fd 表示刚才文件描述的一种结构  
  11.     nread = IO_Read(fd, &ret, 1);  
  12.     if (nread == 0) { /* EOF */  
  13.         return -1;  
  14.     } else if (nread == JVM_IO_ERR) { /* error */  
  15.         JNU_ThrowIOExceptionWithLastError(env, "Read error");  
  16.     } else if (nread == JVM_IO_INTR) {  
  17.         JNU_ThrowByName(env, "java/io/InterruptedIOException", NULL);  
  18.     }  
  19.     return ret & 0xFF;  
  20. }  

 

     

     关于IO_Read 的东西,在io_util_md.h 有定义:

    

Java代码  收藏代码
  1. /* 
  2.  * HPI是一个与主机通信的并行接口 
  3.  * Route the routines through HPI 
  4.  */  
  5. #define IO_Write JVM_Write  
  6. #define IO_Sync JVM_Sync  
  7. <strong>#define IO_Read JVM_Read</strong>  
  8. #define IO_Lseek JVM_Lseek  
  9. #define IO_Available JVM_Available  
  10. #define IO_SetLength JVM_SetLength  

 

    关于JVM_Read 我在jvm.h 里面看到

   

Java代码  收藏代码
  1. /* 
  2.    // 从文件里面读取 a char array 
  3.  * Read data from a file decriptor into a char array. 
  4.  * // 文件的来源 
  5.  * fd        the file descriptor to read from. 
  6.    // 读出来的存放位置 
  7.  * buf       the buffer where to put the read data. 
  8.    // 读的字节数 
  9.  * nbytes    the number of bytes to read. 
  10.  * 
  11.  * This function returns -1 on error, and 0 on success. 
  12.  */  
  13. JNIEXPORT jint JNICALL  
  14. JVM_Read(jint fd, char *buf, jint nbytes);  

   

    然后在jvm.cpp 里面找到

    关于这段代码,大神告诉我是宏定义,关于C和C++ 的东西,我已经无力回天啦。

    当然我们知道了介绍,可以理解这里会让调系统的read 方法。

    这可以参考:“操作系统read 的原理实现”,google 一下很多,这里就不解释了

    jvm.cpp 里面有很多关于IO这块的,可以去看看,但是都是 宏定义。。

    关于linux 下的这些代码,还有涉及一下阻塞等东西,以后在去研究一下操作系统的东西吧。

 

Java代码  收藏代码
  1. JVM_LEAF(jint, JVM_Read(jint fd, char *buf, jint nbytes))  
  2.   JVMWrapper2("JVM_Read (0x%x)", fd);  
  3.   
  4.   //%note jvm_r6  
  5.   return (jint)os::restartable_read(fd, buf, nbytes);  
  6. JVM_END  

0 0
原创粉丝点击