Android通过AssetManager访问资产的各种方式之间存在差异

时间:2012-04-19 18:00:55

标签: android

我是一名初学Android程序员,使用各种方法从AssetManager中读取资产时遇到了一个奇怪的问题。

我附上了展示此问题的示例代码。它读取包含“hello”的简单文本文件资产(“hello.txt”)。我以原始字节读取它并打印出字符的十六进制值(68 65 6c 6c 6f)。

我尝试的方法是(按照代码中的顺序):

  • 打开AssetFileDescriptor(AFD),创建InputStream:只读取前三个字节(68 65 6c ffffffff ffffffff)
  • 打开AFD,获取底层文件描述符,创建FileInputStream:完全错误的数据(50 4b 3 4 a)
  • 直接打开InputStream:正确(68 65 6c 6c 6f)

我也重复了相同的三种方法,这次首先读入一个字节数组,这(令人惊讶!)改变了第一个结果,但产生了相同的结果(为方便起见,这里重复):

  • 打开AFD,创建InputStream,首先读入字节数组:正确(68 65 6c 6c 6f)
  • 打开AFD,获取底层文件描述符,创建FileInputStream,先读入字节数组:完全错误的数据(50 4b 3 4 a)
  • 直接打开InputStream,先读入字节数组:正确(68 65 6c 6c 6f)

请注意,除了第一种情况(当只读入三个字节时),其他情况正好读取6个字节(包括末尾的换行符),然后按预期返回-1。这包括读入错误数据的情况。

有没有人遇到过这个?这是一个错误,还是我做错了什么?

谢谢!

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    AssetManager am = getAssets();
    StringBuilder sb = new StringBuilder();

    try {
        AssetFileDescriptor afd = am.openFd("hello.txt"); 
        InputStream instream = afd.createInputStream();
        sb.append(String.format("afd.createInputStream(): %x %x %x %x %x\n", instream.read(), instream.read(), instream.read(), instream.read(), instream.read()));
        instream.close();
        afd.close();
    }
    catch (IOException e) {
        throw new RuntimeException(e);
    }

    try {
        AssetFileDescriptor afd = am.openFd("hello.txt");
        InputStream instream = new FileInputStream(afd.getFileDescriptor());
        sb.append(String.format("new FileInputStream(afd): %x %x %x %x %x\n", instream.read(), instream.read(), instream.read(), instream.read(), instream.read()));
        instream.close();
        afd.close();
    }
    catch (IOException e) {
        throw new RuntimeException(e);
    }

    try {
        InputStream instream = am.open("hello.txt");
        sb.append(String.format("am.open(): %x %x %x %x %x\n", instream.read(), instream.read(), instream.read(), instream.read(), instream.read()));
        instream.close();
    }
    catch (IOException e) {
        throw new RuntimeException(e);
    }

    try {
        AssetFileDescriptor afd = am.openFd("hello.txt");
        InputStream instream = afd.createInputStream();
        byte[] b = new byte[instream.available()];
        instream.read(b);
        sb.append(String.format("afd.createInputStream() -> byte[]: %x %x %x %x %x\n", b[0], b[1], b[2], b[3], b[4]));
        instream.close();
        afd.close();
    }
    catch (IOException e) {
        throw new RuntimeException(e);
    }

    try {
        AssetFileDescriptor afd = am.openFd("hello.txt");
        InputStream instream = new FileInputStream(afd.getFileDescriptor());
        byte[] b = new byte[(int) afd.getLength()];
        instream.read(b);
        sb.append(String.format("new FileInputStream(afd) -> byte[]: %x %x %x %x %x\n", b[0], b[1], b[2], b[3], b[4]));
        instream.close();
        afd.close();
    }
    catch (IOException e) {
        throw new RuntimeException(e);
    }

    try {
        InputStream instream = am.open("hello.txt");
        byte[] b = new byte[instream.available()];
        instream.read(b);
        sb.append(String.format("am.open() -> byte[]: %x %x %x %x %x\n", b[0], b[1], b[2], b[3], b[4]));
        instream.close();
    }
    catch (IOException e) {
        throw new RuntimeException(e);
    }

    // print result
    TextView textview = (TextView) findViewById(R.id.textview);
    textview.setText(sb.toString());
    Log.d("blah", sb.toString());
}

1 个答案:

答案 0 :(得分:0)

从应用程序的BaseContext获取InputStream。下面的示例演示如何从assets文件夹中获取txt文件并将其内容打印到控制台。

    try {
        InputStream in = getBaseContext().getResources().getAssets().open("sample.txt");
        InputStreamReader is = new InputStreamReader(in);
        BufferedReader br = new BufferedReader(is);
        String read=br.readLine();

        while(read != null) {
            System.out.println(read);
            read = br.readLine();
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }