zoukankan      html  css  js  c++  java
  • 安卓学习-其他-文件读写

    在android中的文件放在不同位置,它们的读取方式也有一些不同。

    本文对android中对资源文件的读取、数据区文件的读取、SD卡文件的读取及RandomAccessFile的方式和方法进行了整理。供参考。

     一、资源文件的读取:

          1) 从resource的raw中读取文件数据: 

    String res = ""; 
    try{ 
     
        //得到资源中的Raw数据流
        InputStream in = getResources().openRawResource(R.raw.test); 
    
        //得到数据的大小
        int length = in.available();       
    
        byte [] buffer = new byte[length];        
    
        //读取数据
        in.read(buffer);         
    
        //依test.txt的编码类型选择合适的编码,如果不调整会乱码 
        res = EncodingUtils.getString(buffer, "BIG5"); 
        
        //关闭    
        in.close();            
    
       }catch(Exception e){ 
          e.printStackTrace();         
       } 

      2) 从resource的asset中读取文件数据 

    String fileName = "test.txt"; //文件名字 
    String res=""; 
    try{ 
    
       //得到资源中的asset数据流
       InputStream in = getResources().getAssets().open(fileName); 
    
       int length = in.available();         
       byte [] buffer = new byte[length];        
    
       in.read(buffer);            
       in.close();
       res = EncodingUtils.getString(buffer, "UTF-8");     
    
      }catch(Exception e){ 
    
          e.printStackTrace();         
    
       } 

     二、读写/data/data/<应用程序名>目录上的文件: 

    //写数据
    public void writeFile(String fileName,String writestr) throws IOException{ 
      try{ 
    
            FileOutputStream fout =openFileOutput(fileName, MODE_PRIVATE); 
    
            byte [] bytes = writestr.getBytes(); 
    
            fout.write(bytes); 
    
            fout.close(); 
          } 
    
            catch(Exception e){ 
            e.printStackTrace(); 
           } 
    } 
    
    //读数据
    public String readFile(String fileName) throws IOException{ 
      String res=""; 
      try{ 
             FileInputStream fin = openFileInput(fileName); 
             int length = fin.available(); 
             byte [] buffer = new byte[length]; 
             fin.read(buffer);     
             res = EncodingUtils.getString(buffer, "UTF-8"); 
             fin.close();     
         } 
         catch(Exception e){ 
             e.printStackTrace(); 
         } 
         return res; 
    
    }   

     三、读写SD卡中的文件。也就是/mnt/sdcard/目录下面的文件 : 

    //写数据到SD中的文件
    public void writeFileSdcardFile(String fileName,String write_str) throws IOException{ 
     try{ 
    
           FileOutputStream fout = new FileOutputStream(fileName); 
           byte [] bytes = write_str.getBytes(); 
    
           fout.write(bytes); 
           fout.close(); 
         }
    
          catch(Exception e){ 
            e.printStackTrace(); 
           } 
       } 
    
      
    //读SD中的文件
    public String readFileSdcardFile(String fileName) throws IOException{ 
      String res=""; 
      try{ 
             FileInputStream fin = new FileInputStream(fileName); 
    
             int length = fin.available(); 
    
             byte [] buffer = new byte[length]; 
             fin.read(buffer);     
    
             res = EncodingUtils.getString(buffer, "UTF-8"); 
    
             fin.close();     
            } 
    
            catch(Exception e){ 
             e.printStackTrace(); 
            } 
            return res; 
    } 

     四、使用File类进行文件的读写: 

    //读文件
    public String readSDFile(String fileName) throws IOException {  
    
            File file = new File(fileName);  
    
            FileInputStream fis = new FileInputStream(file);  
    
            int length = fis.available(); 
    
             byte [] buffer = new byte[length]; 
             fis.read(buffer);     
    
             res = EncodingUtils.getString(buffer, "UTF-8"); 
    
             fis.close();     
             return res;  
    }  
    
    //写文件
    public void writeSDFile(String fileName, String write_str) throws IOException{  
    
            File file = new File(fileName);  
    
            FileOutputStream fos = new FileOutputStream(file);  
    
            byte [] bytes = write_str.getBytes(); 
    
            fos.write(bytes); 
    
            fos.close(); 
    } 

     五、另外,File类还有下面一些常用的操作: 

    String Name = File.getName();  //获得文件或文件夹的名称:
    String parentPath = File.getParent();  //获得文件或文件夹的父目录
    String path = File.getAbsoultePath();//绝对路经
    String path = File.getPath();//相对路经 
    File.createNewFile();//建立文件  
    File.mkDir(); //建立文件夹  
    File.isDirectory(); //判断是文件或文件夹
    File[] files = File.listFiles();  //列出文件夹下的所有文件和文件夹名
    File.renameTo(dest);  //修改文件夹和文件名
    File.delete();  //删除文件夹或文件

     六、使用RandomAccessFile进行文件的读写: 

    RandomAccessFile的使用方法比较灵活,功能也比较多,可以使用类似seek的方式可以跳转到文件的任意位置,从文件指示器当前位置开始读写。
    它有两种构造方法
    new RandomAccessFile(f,"rw");//读写方式
    new RandomAccessFile(f,"r");//只读方式
    使用事例: 

    /* 
     * 程序功能:演示了RandomAccessFile类的操作,同时实现了一个文件复制操作。 
     */  
      
    import java.io.*;  
      
    public class RandomAccessFileDemo {  
     public static void main(String[] args) throws Exception {  
      RandomAccessFile file = new RandomAccessFile("file", "rw");  
      // 以下向file文件中写数据  
      file.writeInt(20);// 占4个字节  
      file.writeDouble(8.236598);// 占8个字节  
      file.writeUTF("这是一个UTF字符串");// 这个长度写在当前文件指针的前两个字节处,可用readShort()读取  
      file.writeBoolean(true);// 占1个字节  
      file.writeShort(395);// 占2个字节  
      file.writeLong(2325451l);// 占8个字节  
      file.writeUTF("又是一个UTF字符串");  
      file.writeFloat(35.5f);// 占4个字节  
      file.writeChar('a');// 占2个字节  
      
      file.seek(0);// 把文件指针位置设置到文件起始处  
      
      // 以下从file文件中读数据,要注意文件指针的位置  
      System.out.println("——————从file文件指定位置读数据——————");  
      System.out.println(file.readInt());  
      System.out.println(file.readDouble());  
      System.out.println(file.readUTF());  
      
      file.skipBytes(3);// 将文件指针跳过3个字节,本例中即跳过了一个boolean值和short值。  
      System.out.println(file.readLong());  
      
      file.skipBytes(file.readShort()); // 跳过文件中“又是一个UTF字符串”所占字节,注意readShort()方法会移动文件指针,所以不用加2。  
      System.out.println(file.readFloat());  
        
      //以下演示文件复制操作  
      System.out.println("——————文件复制(从file到fileCopy)——————");  
      file.seek(0);  
      RandomAccessFile fileCopy=new RandomAccessFile("fileCopy","rw");  
      int len=(int)file.length();//取得文件长度(字节数)  
      byte[] b=new byte[len];  
      file.readFully(b);  
      fileCopy.write(b);  
      System.out.println("复制完成!");  
     }  
    }  

     七、读取资源文件时能否实现类似于seek的方式可以跳转到文件的任意位置,从指定的位置开始读取指定的字节数呢?

    答案是可以的。

    在FileInputStream和InputStream中都有下面的函数:

    public long skip (long byteCount); //从数据流中跳过n个字节
    public int read (byte[] buffer, int offset, int length); //从数据流中读取length数据存在buffer的offset开始的位置。offset是相对于buffer的开始位置的,不是数据流。

     可以使用这两个函数来实现类似于seek的操作,请看下面的测试代码: 

    //其中read_raw是一个txt文件,存放在raw目录下。
    //read_raw.txt文件的内容是:"ABCDEFGHIJKLMNOPQRST"
    public String getRawString() throws IOException {
        
        String str = null;
        
        InputStream in = getResources().openRawResource(R.raw.read_raw);
        
        int length = in.available();
        byte[] buffer = new byte[length];
        
        in.skip(2); //跳过两个字节
        in.read(buffer,0,3); //读三个字节
        
        in.skip(3); //跳过三个字节
        in.read(buffer,0,3); //读三个字节
        
        //最后str="IJK"
        str = EncodingUtils.getString(buffer, "BIG5");
        
        
        in.close();
        
        return str;
    }

     从上面的实例可以看出skip函数有点类似于C语言中的seek操作,但它们之间有些不同。 

    需要注意的是:

    1、skip函数始终是从当前位置开始跳的。在实际应用当中还要再判断一下该函数的返回值。

    2、read函数也始终是当前位置开始读的。

    3、另外,还可以使用reset函数将文件的当前位置重置为0,也就是文件的开始位置。 

    如何得到文件的当前位置?

    我没有找到相关的函数和方法,不知道怎么样才能得到文件的当前位置,貌似它也并不是太重要。

     八、如何从FileInputStream中得到InputStream? 

    public String readFileData(String fileName) throws IOException{ 
      String res=""; 
      try{ 
             FileInputStream fin = new FileInputStream(fileName); 
         InputStream in = new BufferedInputStream(fin);
    
             ...
    
          }
          catch(Exception e){ 
             e.printStackTrace(); 
          }
    
    }

     九、APK资源文件的大小不能超过1M,如果超过了怎么办?我们可以将这个数据再复制到data目录下,然后再使用。复制数据的代码如下: 

        public boolean assetsCopyData(String strAssetsFilePath, String strDesFilePath){
               boolean bIsSuc = true;
               InputStream inputStream = null;
               OutputStream outputStream = null;
               
               File file = new File(strDesFilePath);
               if (!file.exists()){
                   try {
                      file.createNewFile();
                      Runtime.getRuntime().exec("chmod 766 " + file);
                   } catch (IOException e) {
                      bIsSuc = false;
                   }
                   
               }else{//存在
                   return true;
               }
               
               try {
                   inputStream = getAssets().open(strAssetsFilePath);
                   outputStream = new FileOutputStream(file);
                   
                   int nLen = 0 ;
                   
                   byte[] buff = new byte[1024*1];
                   while((nLen = inputStream.read(buff)) > 0){
                      outputStream.write(buff, 0, nLen);
                   }
                   
                   //完成
               } catch (IOException e) {
                   bIsSuc = false;
               }finally{
                   try {
                      if (outputStream != null){
                          outputStream.close();
                      }
                      
                      if (inputStream != null){
                          inputStream.close();
                      }
                   } catch (IOException e) {
                      bIsSuc = false;
                   }
                   
               }
               
               return bIsSuc;
            }    

    转载时请注明出处:http://blog.csdn.net/ztp800201/article/details/7322110


    总结:

    1、apk中有两种资源文件,使用两种不同的方式进行打开使用。
    raw使用InputStream in = getResources().openRawResource(R.raw.test);
    asset使用InputStream in = getResources().getAssets().open(fileName);

    这些数据只能读取,不能写入。更重要的是该目录下的文件大小不能超过1M。

    同时,需要注意的是,在使用InputStream的时候需要在函数名称后加上throws IOException。

    2、SD卡中的文件使用FileInputStream和FileOutputStream进行文件的操作。
    3、存放在数据区(/data/data/..)的文件只能使用openFileOutput和openFileInput进行操作。
    注意不能使用FileInputStream和FileOutputStream进行文件的操作。
    4、RandomAccessFile类仅限于文件的操作,不能访问其他IO设备。它可以跳转到文件的任意位置,从当前位置开始读写。

    5、InputStream和FileInputStream都可以使用skip和read(buffre,offset,length)函数来实现文件的随机读取。

  • 相关阅读:
    Golang Failpoint 的设计与实现
    没涉及到最值求解;观点:矩阵乘法无法表达出结果。 现实生活中事件、现象的数学表达
    多元微分学 枚举破解15位路由器密码 存储空间限制 拆分减长,求最值 数据去重
    ARP Poisoning Attack and Mitigation Techniques ARP欺骗 中间人攻击 Man-In-The-Middle (MITM) attack 嗅探 防范 Can one MAC address have two different IP addresses within the network?
    The C10K problem
    HTTP Streaming Architecture HLS 直播点播 HTTP流架构
    现代IM系统中消息推送和存储架构的实现
    现代IM系统中的消息系统架构
    长连接锁服务优化实践 C10K问题 nodejs的内部构造 limits.conf文件修改 sysctl.conf文件修改
    doubleclick cookie、动态脚本、用户画像、用户行为分析和海量数据存取 推荐词 京东 电商 信息上传 黑洞 https://blackhole.m.jd.com/getinfo
  • 原文地址:https://www.cnblogs.com/weijj/p/4195787.html
Copyright © 2011-2022 走看看