简体   繁体   English

在Android中写入和读取二进制文件

[英]Write and read binary files in Android

I created a custom object of type Task and I want to save it in a binary file in internal storage. 我创建了一个Task类型的自定义对象,我想将它保存在内部存储中的二进制文件中。 Here is the class I created: 这是我创建的类:

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;

    }
}

In an activity, I created a method that will save my object to a file. 在一个活动中,我创建了一个将对象保存到文件的方法。 This is the code I used: 这是我使用的代码:

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();
    }
}

Now I would like to create a method that will extract the data from the file. 现在我想创建一个从文件中提取数据的方法。 By reading on the internet, a lot of people use FileInputStream but I have trouble with extracting the bytes from it and knowing how long a String can be. 通过在互联网上阅读,很多人使用FileInputStream但我无法从中提取字节并知道String可以有多长。 Furthermore, I used a simple method found online but I get permission denied. 此外,我使用了一种在线发现的简单方法,但我得到了许可被拒绝。 As I said, I am very new to Android development. 正如我所说,我对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();
        }
    }
}

Any help will be appreciated. 任何帮助将不胜感激。

For permission issues, I encourage you to use an external storage such as an SD card. 对于权限问题,我建议您使用外部存储设备,如SD卡。

Environment.getExternalStorageDirectory()

you can create a folder there and save your files. 你可以在那里创建一个文件夹并保存你的文件。 You can also use "/data/local/" if your system permits user files to be saved there. 如果系统允许将用户文件保存在那里,也可以使用“/ data / local /”。 You can refer to this page regarding the various ways you can save files to internal and external storage, 您可以参考此页面,了解有关将文件保存到内部和外部存储的各种方法,

For the second problem I suggest you to use DataInputStream , 对于第二个问题,我建议你使用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();

You can code something like this, 你可以编写这样的代码,

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);
    }
}

You can also Use Serializable interface for reading and writing serializable objects. 您还可以使用Serializable接口来读取和编写可序列化对象。 In fact, I used this once when I tried to write data values directly to files instead of any traditional databases (In my very first undergraduate years, I was not familiar with databases). 事实上,当我尝试将数据值直接写入文件而不是任何传统数据库时,我曾经使用过一次(在我的第一个大学本科,我不熟悉数据库)。 A good example is 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())
  ;
} 

From what I see, you are trying to dump the contents of the object into a file and then read it back. 从我看到的,您正在尝试将对象的内容转储到文件中,然后将其读回。 But the way you are doing it now is just writing all the data to the file without any structure, which is a terrible idea. 但是你现在这样做的方法就是将所有数据写入文件而没有任何结构,这是一个糟糕的主意。

I would recommend you try to implement the Serializable interface and then just use the writeObject() and readObject() methods. 我建议你尝试实现Serializable接口 ,然后只使用writeObject()和readObject()方法。

Alternatively, you could dump the data into an XML file or something that has some structure to it. 或者,您可以将数据转储到XML文件或具有某种结构的文件中。

Android provides a private directory structure to each application for exactly this kind of data. Android为每种应用程序提供了一种私有目录结构,以实现这种数据。 You don't need special permissions to access it. 您无需特殊权限即可访问它。 The only caveat (which is generally a good caveat) is that only your app can access it. 唯一的警告(通常是一个很好的警告)是只有你的应用程序可以访问它。 (This principle is part of the security that prevents other apps from doing bad things to you.) (此原则是安全性的一部分,可防止其他应用程序对您执行不良操作。)

If this meets you need for storage, just call getFilesDir() from whatever context is readily available (usually your activity). 如果这符合您的存储需求,只需从任何可用的上下文(通常是您的活动)调用getFilesDir() )。 It looks like in your case you would want to pass the context as a parameter of readData() and writeData() . 在您的情况下,您可能希望将上下文作为readData()writeData()的参数传递。 Or you could call getFilesDir() to get the storage directory and then pass that as the parameter to readData() and writeData() . 或者您可以调用getFilesDir()来获取存储目录,然后将其作为参数传递给readData()writeData()

One other caveat (learned the hard way). 另一个警告(艰难地学习)。 Although undocumented, I've found that sometimes Android will create files in this application directory. 虽然没有文档,但我发现有时Android会在这个应用程序目录中创建文件。 I strongly recommend that rather than storing files directly in this application folder you instead create your own storage directory in the application directory returned by getFilesDir() , and then store your files there. 我强烈建议您不要直接将文件存储在此应用程序文件夹中,而是在getFilesDir()返回的应用程序目录中创建自己的存储目录,然后将文件存储在那里。 That way you won't have to worry about other files that might show up, for example if you try to list the files in the storage directory. 这样您就不必担心可能出现的其他文件,例如,如果您尝试列出存储目录中的文件。

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

(I agree with P basak that DataInputStream and DataOutputStream are your best option for reading and writing the data. I disrecommend Serialization except in a very narrow set of applications where transportability is a factor as it is very inefficient. In my case objects that took 15 seconds to load via Serialization loaded in less than 2 seconds using DataInputStream .) (我同意P basak, DataInputStreamDataOutputStream是读取和写入数据的最佳选择。我推断序列化,除非在一个非常狭窄的应用程序集中,可移植性是一个因素,因为它是非常低效的。在我的情况下,对象花了15使用DataInputStream在不到2秒的时间内通过Serialization加载的秒数。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM