【问题标题】:Write and read binary files in Android在 Android 中写入和读取二进制文件
【发布时间】:2014-02-16 20:22:31
【问题描述】:

我创建了一个Task 类型的自定义对象,我想将它保存在内部存储中的二进制文件中。这是我创建的类:

public class Task {

    private String title;
    private int year;
    private int month;
    private int day;
    private int hour;
    private int minute;

    public Task(String inputTitle, int inputYear, int inputMonth, int inputDay, int inputHour, int inputMinute) {

        this.title = inputTitle;
        this.year = inputYear;
        this.month = inputMonth;
        this.day = inputDay;
        this.hour = inputHour;
        this.minute = inputMinute;

    }

    public String getTitle() {

        return this.title;

    }

    public int getYear() {

        return this.year;

    }

    public int getMonth() {

        return this.month;

    }

    public int getDay() {

        return this.day;

    }

    public int getHour() {

        return this.hour;

    }

    public int getMinute() {

        return this.minute;

    }
}

在一个活动中,我创建了一个将我的对象保存到文件的方法。这是我使用的代码:

public void writeData(Task newTask) {
    try {
        FileOutputStream fOut = openFileOutput("data", MODE_WORLD_READABLE);
        fOut.write(newTask.getTitle().getBytes());
        fOut.write(newTask.getYear());
        fOut.write(newTask.getMonth());
        fOut.write(newTask.getDay());
        fOut.write(newTask.getHour());
        fOut.write(newTask.getMinute());
        fOut.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

现在我想创建一个从文件中提取数据的方法。通过在互联网上阅读,很多人使用FileInputStream,但我无法从中提取字节并知道字符串的长度。此外,我使用了一种在网上找到的简单方法,但我的权限被拒绝了。正如我所说,我对 Android 开发非常陌生。

public void readData(){
    FileInputStream fis = null;
    try {
        fis = new FileInputStream("data");
        System.out.println("Total file size to read (in bytes) : "
                + fis.available());
        int content;
        while ((content = fis.read()) != -1) {
            // convert to char and display it
            System.out.print((char) content);
        }

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (fis != null)
                fis.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

任何帮助将不胜感激。

【问题讨论】:

    标签: java android fileinputstream fileoutputstream


    【解决方案1】:

    对于权限问题,我建议您使用 SD 卡等外部存储设备。

    Environment.getExternalStorageDirectory()
    

    您可以在那里创建一个文件夹并保存您的文件。如果您的系统允许将用户文件保存在那里,您也可以使用“/data/local/”。 您可以参考此page,了解将文件保存到内部和外部存储的各种方式,

    第二个问题我建议你使用DataInputStream

    File file = new File("myFile");
    byte[] fileData = new byte[(int) file.length()];
    DataInputStream dis = new DataInputStream(new FileInputStream(file));
    dis.readFully(fileData);
    dis.close();
    

    你可以编写这样的代码,

    import java.io.*;
    public class Sequence {
        public static void main(String[] args) throws IOException {
        DataInputStream dis = new DataInputStream(System.in);
        String str="Enter your Age :";
        System.out.print(str);
        int i=dis.readInt();
        System.out.println((int)i);
        }
    }
    

    你也可以使用Serializable接口来读写可序列化的对象。事实上,当我尝试将数据值直接写入文件而不是任何传统数据库时,我曾经使用过一次(在我本科的第一年,我不熟悉数据库)。一个很好的例子是here

    import java.io.*;
    import java.util.*;
    import java.util.logging.*;
    
    /** JDK before version 7. */
    public class ExerciseSerializable {
    
      public static void main(String... aArguments) {
        //create a Serializable List
        List<String> quarks = Arrays.asList(
          "up", "down", "strange", "charm", "top", "bottom"
        );
    
        //serialize the List
        //note the use of abstract base class references
    
        try{
          //use buffering
          OutputStream file = new FileOutputStream("quarks.ser");
          OutputStream buffer = new BufferedOutputStream(file);
          ObjectOutput output = new ObjectOutputStream(buffer);
          try{
            output.writeObject(quarks);
          }
          finally{
            output.close();
          }
        }  
        catch(IOException ex){
          fLogger.log(Level.SEVERE, "Cannot perform output.", ex);
        }
    
        //deserialize the quarks.ser file
        //note the use of abstract base class references
    
        try{
          //use buffering
          InputStream file = new FileInputStream("quarks.ser");
          InputStream buffer = new BufferedInputStream(file);
          ObjectInput input = new ObjectInputStream (buffer);
          try{
            //deserialize the List
            List<String> recoveredQuarks = (List<String>)input.readObject();
            //display its data
            for(String quark: recoveredQuarks){
              System.out.println("Recovered Quark: " + quark);
            }
          }
          finally{
            input.close();
          }
        }
        catch(ClassNotFoundException ex){
          fLogger.log(Level.SEVERE, "Cannot perform input. Class not found.", ex);
        }
        catch(IOException ex){
          fLogger.log(Level.SEVERE, "Cannot perform input.", ex);
        }
      }
    
      // PRIVATE 
    
      //Use Java's logging facilities to record exceptions.
      //The behavior of the logger can be configured through a
      //text file, or programmatically through the logging API.
      private static final Logger fLogger =
        Logger.getLogger(ExerciseSerializable.class.getPackage().getName())
      ;
    } 
    

    【讨论】:

    【解决方案2】:

    据我所知,您正试图将对象的内容转储到文件中,然后将其读回。但是你现在这样做的方式只是将所有数据写入文件而没有任何结构,这是一个糟糕的想法。

    我建议您尝试实现Serializable interface,然后只使用 writeObject() 和 readObject() 方法。

    或者,您可以将数据转储到 XML 文件或具有某种结构的文件中。

    【讨论】:

      【解决方案3】:

      Android 为每个应用程序提供了一个私有目录结构来存储这类数据。您不需要特殊权限即可访问它。唯一的警告(通常是一个很好的警告)是只有您的应用可以访问它。 (此原则是防止其他应用对您做坏事的安全性的一部分。)

      如果这满足您的存储需求,只需从任何可用的上下文(通常是您的活动)调用getFilesDir()。在您的情况下,您似乎希望将上下文作为readData()writeData() 的参数传递。或者您可以调用getFilesDir() 来获取存储目录,然后将其作为参数传递给readData()writeData()

      另外一个警告(学会了艰难的方式)。虽然没有记录,但我发现有时 Android 会在此应用程序目录中创建文件。我强烈建议不要将文件直接存储在此应用程序文件夹中,而是在getFilesDir() 返回的应用程序目录中创建自己的存储目录,然后将文件存储在那里。这样您就不必担心可能会出现的其他文件,例如,如果您尝试列出存储目录中的文件。

      File myStorageFolder = new File(context.getFilesDir(), "myStorageFolder");
      

      (我同意 P basak 的观点,即 DataInputStreamDataOutputStream 是读取和写入数据的最佳选择。我不建议使用序列化,除非在非常有限的应用程序中可传输性是一个非常低效的因素。在我的情况下,通过序列化加载需要 15 秒的对象使用 DataInputStream 在不到 2 秒的时间内加载。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-17
        • 1970-01-01
        • 2014-01-07
        • 2015-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多