Android读取文本原始资源文件

138

我有一个文本文件作为原始资源添加。该文本文件包含如下文本:

b) IF APPLICABLE LAW REQUIRES ANY WARRANTIES WITH RESPECT TO THE
SOFTWARE, ALL SUCH WARRANTIES ARE 
LIMITED IN DURATION TO NINETY (90)
DAYS FROM THE DATE OF  DELIVERY.

(c) NO ORAL OR WRITTEN INFORMATION OR
ADVICE GIVEN BY  VIRTUAL ORIENTEERING,
ITS DEALERS, DISTRIBUTORS, AGENTS OR
EMPLOYEES SHALL CREATE A WARRANTY OR
IN ANY WAY INCREASE THE SCOPE OF ANY
WARRANTY PROVIDED HEREIN. 

(d) (USA only) SOME STATES DO NOT
ALLOW THE EXCLUSION OF IMPLIED
WARRANTIES, SO THE ABOVE EXCLUSION MAY
NOT  APPLY TO YOU. THIS WARRANTY GIVES
YOU SPECIFIC LEGAL  RIGHTS AND YOU MAY
ALSO HAVE OTHER LEGAL RIGHTS THAT 
VARY FROM STATE TO STATE.

我屏幕上的布局如下:

<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
                     android:layout_width="fill_parent" 
                     android:layout_height="wrap_content" 
                     android:gravity="center" 
                     android:layout_weight="1.0"
                     android:layout_below="@+id/logoLayout"
                     android:background="@drawable/list_background"> 
            
            <ScrollView android:layout_width="fill_parent"
                        android:layout_height="fill_parent">
                        
                    <TextView  android:id="@+id/txtRawResource" 
                               android:layout_width="fill_parent" 
                               android:layout_height="fill_parent"
                               android:padding="3dip"/>
            </ScrollView>  
   
    </LinearLayout>

读取原始资源的代码如下:

TextView txtRawResource= (TextView)findViewById(R.id.txtRawResource);

txtDisclaimer.setText(Utils.readRawTextFile(ctx, R.raw.rawtextsample);

public static String readRawTextFile(Context ctx, int resId)
{
    InputStream inputStream = ctx.getResources().openRawResource(resId);

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

    int i;
    try {
        i = inputStream.read();
        while (i != -1)
        {
            byteArrayOutputStream.write(i);
            i = inputStream.read();
        }
        inputStream.close();
    } catch (IOException e) {
        return null;
    }
    return byteArrayOutputStream.toString();
}

文本已显示,但每行后面都有奇怪的字符[]。我该如何去除这些字符?我认为这是一个换行符。

3
请将原始参数注释为@RawRes,这样Android Studio才能识别原始资源。 - Roel
1
工作解决方案应该发布为答案,这样它可以被投票支持。 - LarsH
14个回答

174
您可以使用以下内容:
    try {
        Resources res = getResources();
        InputStream in_s = res.openRawResource(R.raw.help);

        byte[] b = new byte[in_s.available()];
        in_s.read(b);
        txtHelp.setText(new String(b));
    } catch (Exception e) {
        // e.printStackTrace();
        txtHelp.setText("Error: can't show help.");
    }

5
我不确定在这里使用Inputstream.available()是正确的选择,而是将n读取到ByteArrayOutputStream中,直到n == -1。 - ThomasRS
15
对于大型资源,这种方法可能行不通。这取决于输入流读取缓冲区的大小,可能只会返回资源的一部分。 - d4n3
6
@d4n3 是正确的,输入流可用方法的文档说明为:“返回可以在没有更多输入的情况下读取或跳过的大致字节数。请注意,此方法提供的保证非常薄弱,实际上并不是很有用。” - ozba
1
查看Android文档中的InputStream.available。如果我理解正确,他们说不应该将其用于此目的。谁能想到读取一个愚蠢的文件内容会这么难... - anhoppe
3
你不应该捕获通用异常。应该捕获IOException。 - alcsan

77

如果您使用基于字符的 BufferedReader 而不是基于字节的 InputStream,会发生什么?

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = reader.readLine();
while (line != null) { 
    ...
    line = reader.readLine();
}

不要忘记 readLine() 会跳过换行符!


对我而言,以下代码起了作用: InputStream is = my_app_context.getResources().openRawResource(R.raw.name_of_text_file); Scanner text_scanner = new Scanner(is); // 玩得开心! - TomeeNS

55

使用 Kotlin,您只需要一行代码就可以做到这一点:

resources.openRawResource(R.raw.rawtextsample).bufferedReader().use { it.readText() }

或者甚至声明扩展函数:

fun Resources.getRawTextFile(@RawRes id: Int) =
        openRawResource(id).bufferedReader().use { it.readText() }

然后直接使用它:

val txtFile = resources.getRawTextFile(R.raw.rawtextsample)

2
你是一个天使。 - Bob Liberatore
这是唯一对我有效的方法!谢谢! - fuomag9
需要指定charset吗?我没有看到readText接受这样的参数,这样安全吗?还是最好使用特定的charsetByteArray进行转换? - Tamim Attafi
1
@TamimAttafi readText 的默认字符集是 UTF-8,如果您的文本使用不同的字符集,则必须显式设置它。只要文本不太大且源文本的字符集为 UTF-8,就是安全的。 - Arsenius

32
如果您使用来自Apache“commons-io”的IOUtils,那么它会更加容易:
InputStream is = getResources().openRawResource(R.raw.yourNewTextFile);
String s = IOUtils.toString(is);
IOUtils.closeQuietly(is); // don't forget to close your streams

依赖项: http://mvnrepository.com/artifact/commons-io/commons-io

Maven:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

Gradle:

'commons-io:commons-io:2.4'

1
我应该导入什么才能使用IOUtils? - ThE uSeFuL
1
Apache commons-io 库(http://commons.apache.org/proper/commons-io/)。或者如果您使用 Maven(http://mvnrepository.com/artifact/commons-io/commons-io)。 - tbraun
8
对于 Gradle 项目:compile "commons-io:commons-io:2.1" 可翻译为:使用 Gradle 编译时,引入 Commons IO 库版本 2.1,代码如下:compile "commons-io:commons-io:2.1"。 - JustinMorris
13
通常来说,为了避免写出三行代码而导入外部的第三方库似乎有些杀鸡焉用牛刀。 - milosmns

4
请这样做:
// reads resources regardless of their size
public byte[] getResource(int id, Context context) throws IOException {
    Resources resources = context.getResources();
    InputStream is = resources.openRawResource(id);

    ByteArrayOutputStream bout = new ByteArrayOutputStream();

    byte[] readBuffer = new byte[4 * 1024];

    try {
        int read;
        do {
            read = is.read(readBuffer, 0, readBuffer.length);
            if(read == -1) {
                break;
            }
            bout.write(readBuffer, 0, read);
        } while(true);

        return bout.toByteArray();
    } finally {
        is.close();
    }
}

    // reads a string resource
public String getStringResource(int id, Charset encoding) throws IOException {
    return new String(getResource(id, getContext()), encoding);
}

    // reads an UTF-8 string resource
public String getStringResource(int id) throws IOException {
    return new String(getResource(id, getContext()), Charset.forName("UTF-8"));
}

通过Activity,添加

public byte[] getResource(int id) throws IOException {
        return getResource(id, this);
}

或者从一个测试用例中,添加。
public byte[] getResource(int id) throws IOException {
        return getResource(id, getContext());
}

同时要注意错误处理——当资源必须存在或者出现了(非常?)严重的问题时,不要捕获并忽略异常。


你需要关闭 openRawResource() 打开的流吗? - Alex Semeniuk
我不知道,但那肯定是标准的。更新示例。 - ThomasRS

3
@borislemke,您可以通过类似的方式来实现这一点。
TextView  tv ;
findViewById(R.id.idOfTextView);
tv.setText(readNewTxt());
private String readNewTxt(){
InputStream inputStream = getResources().openRawResource(R.raw.yourNewTextFile);
 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

 int i;
 try {
 i = inputStream.read();
while (i != -1)
  {
   byteArrayOutputStream.write(i);
   i = inputStream.read();
   }
    inputStream.close();
  } catch (IOException e) {
   // TODO Auto-generated catch block
 e.printStackTrace();
 }

 return byteArrayOutputStream.toString();
 }

2

以下是从原始文件夹读取文本文件的简单方法:

public static String readTextFile(Context context,@RawRes int id){
    InputStream inputStream = context.getResources().openRawResource(id);
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    byte buffer[] = new byte[1024];
    int size;
    try {
        while ((size = inputStream.read(buffer)) != -1) 
            outputStream.write(buffer, 0, size);
        outputStream.close();
        inputStream.close();
    } catch (IOException e) {

    }
    return outputStream.toString();
}

2

这里包含了Weekens和Vovodroid的解决方案。

这个解决方案比Vovodroid的更正确,比Weekens的更完整。

    try {
        InputStream inputStream = res.openRawResource(resId);
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            try {
                StringBuilder result = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    result.append(line);
                }
                return result.toString();
            } finally {
                reader.close();
            }
        } finally {
            inputStream.close();
        }
    } catch (IOException e) {
        // process exception
    }

2

这是另一种肯定有效的方法,但我无法让它读取多个文本文件并在单个活动中查看多个文本视图,有人可以帮忙吗?

TextView helloTxt = (TextView)findViewById(R.id.yourTextView);
    helloTxt.setText(readTxt());
}

private String readTxt(){

 InputStream inputStream = getResources().openRawResource(R.raw.yourTextFile);
 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

 int i;
try {
i = inputStream.read();
while (i != -1)
  {
   byteArrayOutputStream.write(i);
   i = inputStream.read();
  }
  inputStream.close();
} catch (IOException e) {
 // TODO Auto-generated catch block
e.printStackTrace();
}

 return byteArrayOutputStream.toString();
}

2
这里提供一个Kotlin实现的示例。
    try {
        val inputStream: InputStream = this.getResources().openRawResource(R.raw.**)
        val inputStreamReader = InputStreamReader(inputStream)
        val sb = StringBuilder()
        var line: String?
        val br = BufferedReader(inputStreamReader)
        line = br.readLine()
        while (line != null) {
            sb.append(line)
            line = br.readLine()
        }
        br.close()

        var content : String = sb.toString()
        Log.d(TAG, content)
    } catch (e:Exception){
        Log.d(TAG, e.toString())
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接