Java 在 Android 中写入和读取二进制文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21816049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Write and read binary files in Android
提问by miszu
I created a custom object of type Task
and I want to save it in a binary file in internal storage. Here is the class I created:
我创建了一个自定义类型的对象,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;
}
}
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. Furthermore, I used a simple method found online but I get permission denied. As I said, I am very new to Android development.
现在我想创建一个从文件中提取数据的方法。通过在互联网上阅读,很多人都在使用,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();
}
}
}
Any help will be appreciated.
任何帮助将不胜感激。
采纳答案by P basak
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. You can refer to this pageregarding the various ways you can save files to internal and external storage,
您可以在那里创建一个文件夹并保存您的文件。如果您的系统允许将用户文件保存在那里,您也可以使用“/data/local/”。您可以参考此页面了解将文件保存到内部和外部存储的各种方式,
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 Serializableinterface for reading and writing serializable objects. 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,
您还可以使用Serializable接口来读取和写入可序列化对象。事实上,当我尝试将数据值直接写入文件而不是任何传统数据库时,我曾经使用过这个(在我本科的第一年,我不熟悉数据库)。一个很好的例子在这里,
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())
;
}
回答by Vlad Schnakovszki
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 interfaceand 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 文件或具有某种结构的文件中。
回答by TechnalyticSteve
Android provides a private directory structure to each application for exactly this kind of data. You don't need special permissions to access it. The only caveat (which is generally a good caveat) is that onlyyour app can access it. (This principle is part of the security that prevents other apps from doing bad things to you.)
对于这种数据,Android 为每个应用程序提供了一个私有目录结构。您不需要特殊权限即可访问它。唯一的警告(这通常是一个很好的警告)是只有您的应用程序可以访问它。(此原则是防止其他应用对您做坏事的安全性的一部分。)
If this meets you need for storage, just call getFilesDir()
from whatever context is readily available (usually your activity). It looks like in your case you would want to pass the context as a parameter of readData()
and writeData()
. Or you could call getFilesDir()
to get the storage directory and then pass that as the parameter to readData()
and writeData()
.
如果这满足您的存储需求,只需getFilesDir()
从任何现成的上下文(通常是您的活动)调用即可。在您的情况下,您似乎希望将上下文作为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. 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. 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.
另一个警告(通过艰难的方式学习)。虽然没有记录,但我发现有时 Android 会在此应用程序目录中创建文件。我强烈建议不要将文件直接存储在此应用程序文件夹中,而是在返回的应用程序目录中创建自己的存储目录getFilesDir()
,然后将文件存储在那里。这样您就不必担心可能出现的其他文件,例如,如果您尝试列出存储目录中的文件。
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 的观点,DataInputStream
并且DataOutputStream
是读取和写入数据的最佳选择。我不推荐序列化,除非在可传输性是一个因素的非常狭窄的应用程序集中,因为它非常低效。在我的情况下,对象需要 15 秒才能完成使用DataInputStream
.)在不到 2 秒的时间内通过序列化加载