我的资源文件夹中有一个文件...我该如何阅读?
现在我正在尝试:
public static String readFileAsString(String filePath)
throws java.io.IOException{
StringBuffer fileData = new StringBuffer(1000);
BufferedReader reader = new BufferedReader(
new FileReader(filePath));
char[] buf = new char[1024];
int numRead=0;
while((numRead=reader.read(buf)) != -1){
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
buf = new char[1024];
}
reader.close();
return fileData.toString();
}
但是它会抛出空指针异常......
该文件名为“origin”,位于文件夹资产
中我试图用它来施展:
readFileAsString("file:///android_asset/origin");
和
readFileAsString("asset/origin");``
但都失败了......有什么建议吗?
答案 0 :(得分:11)
BufferedReader的readLine()方法在到达文件末尾时返回null,因此您需要注意它并避免尝试将其附加到字符串中。
以下代码应该很简单:
public static String readFileAsString(String filePath) throws java.io.IOException
{
BufferedReader reader = new BufferedReader(new FileReader(filePath));
String line, results = "";
while( ( line = reader.readLine() ) != null)
{
results += line;
}
reader.close();
return results;
}
简单而重要。
答案 1 :(得分:6)
您可以使用AssetsManager
打开输入流。
InputStream input = getAssets().open("origin");
Reader reader = new InputStreamReader(input, "UTF-8");
getAssets()
是Context
类的方法。
另请注意,您不应重新创建字符缓冲区(buf = new char[1024]
,即周期的最后一行)。
答案 2 :(得分:6)
public static String readFile( String filePath ) throws IOException
{
Reader reader = new FileReader( filePath );
StringBuilder sb = new StringBuilder();
char buffer[] = new char[16384]; // read 16k blocks
int len; // how much content was read?
while( ( len = reader.read( buffer ) ) > 0 ){
sb.append( buffer, 0, len );
}
reader.close();
return sb.toString();
}
非常直接,非常快,适用于不合理的大型文本文件(100 + MB)
(最后的代码)
很多时候没关系,但这种方法非常快且可读性很强。实际上它的复杂度比@ Raceimation的答案快 - O(n)而不是O(n ^ 2)。
我测试了六种方法(从慢到快):
在非常大的文件上完全预分配缓冲区是最快的,但该方法不是非常通用,因为必须提前知道总文件大小。这就是为什么我建议使用带有char []缓冲区的strBuilder,它仍然很简单,如果需要,可以轻松地接受任何输入流而不仅仅是文件。然而,它对于所有合理的案例来说肯定足够快
import java.io.*;
public class Test
{
static final int N = 5;
public final static void main( String args[] ) throws IOException{
test( "1k.txt", true );
test( "10k.txt", true );
// concat with += would take ages here, so we skip it
test( "100k.txt", false );
test( "2142k.txt", false );
test( "pruned-names.csv", false );
// ah, what the heck, why not try a binary file
test( "/Users/hansi/Downloads/xcode46graphicstools6938140a.dmg", false );
}
public static void test( String file, boolean includeConcat ) throws IOException{
System.out.println( "Reading " + file + " (~" + (new File(file).length()/1024) + "Kbytes)" );
strbuilderwithchars( file );
strbuilderwithchars( file );
strbuilderwithchars( file );
tick( "Warm up... " );
if( includeConcat ){
for( int i = 0; i < N; i++ )
concat( file );
tick( "> Concat with += " );
}
else{
tick( "> Concat with += **skipped** " );
}
for( int i = 0; i < N; i++ )
strbuilderguess( file );
tick( "> StringBuilder init with length " );
for( int i = 0; i < N; i++ )
strbuilder( file );
tick( "> StringBuilder with line buffer " );
for( int i = 0; i < N; i++ )
strbuilderwithchars( file );
tick( "> StringBuilder with char[] buffer" );
for( int i = 0; i < N; i++ )
strbufferwithchars( file );
tick( "> StringBuffer with char[] buffer " );
for( int i = 0; i < N; i++ )
singleBuffer( file );
tick( "> Allocate byte[filesize] " );
System.out.println();
}
public static long now = System.currentTimeMillis();
public static void tick( String message ){
long t = System.currentTimeMillis();
System.out.println( message + ": " + ( t - now )/N + " ms" );
now = t;
}
// StringBuilder with char[] buffer
// + works if filesize is unknown
// + pretty fast
public static String strbuilderwithchars( String filePath ) throws IOException
{
Reader reader = new FileReader( filePath );
StringBuilder sb = new StringBuilder();
char buffer[] = new char[16384]; // read 16k blocks
int len; // how much content was read?
while( ( len = reader.read( buffer ) ) > 0 ){
sb.append( buffer, 0, len );
}
reader.close();
return sb.toString();
}
// StringBuffer with char[] buffer
// + works if filesize is unknown
// + faster than stringbuilder on my computer
// - should be slower than stringbuilder, which confuses me
public static String strbufferwithchars( String filePath ) throws IOException
{
Reader reader = new FileReader( filePath );
StringBuffer sb = new StringBuffer();
char buffer[] = new char[16384]; // read 16k blocks
int len; // how much content was read?
while( ( len = reader.read( buffer ) ) > 0 ){
sb.append( buffer, 0, len );
}
reader.close();
return sb.toString();
}
// StringBuilder init with length
// + works if filesize is unknown
// - not faster than any of the other methods, but more complicated
public static String strbuilderguess(String filePath) throws IOException
{
File file = new File( filePath );
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
StringBuilder sb = new StringBuilder( (int)file.length() );
while( ( line = reader.readLine() ) != null)
{
sb.append( line );
}
reader.close();
return sb.toString();
}
// StringBuilder with line buffer
// + works if filesize is unknown
// + pretty fast
// - speed may (!) vary with line length
public static String strbuilder(String filePath) throws IOException
{
BufferedReader reader = new BufferedReader(new FileReader(filePath));
String line;
StringBuilder sb = new StringBuilder();
while( ( line = reader.readLine() ) != null)
{
sb.append( line );
}
reader.close();
return sb.toString();
}
// Concat with +=
// - slow
// - slow
// - really slow
public static String concat(String filePath) throws IOException
{
BufferedReader reader = new BufferedReader(new FileReader(filePath));
String line, results = "";
int i = 0;
while( ( line = reader.readLine() ) != null)
{
results += line;
i++;
}
reader.close();
return results;
}
// Allocate byte[filesize]
// + seems to be the fastest for large files
// - only works if filesize is known in advance, so less versatile for a not significant performance gain
// + shortest code
public static String singleBuffer(String filePath ) throws IOException{
FileInputStream in = new FileInputStream( filePath );
byte buffer[] = new byte[(int) new File( filePath).length()]; // buffer for the entire file
int len = in.read( buffer );
return new String( buffer, 0, len );
}
}
/**
*** RESULTS ***
Reading 1k.txt (~31Kbytes)
Warm up... : 0 ms
> Concat with += : 37 ms
> StringBuilder init with length : 0 ms
> StringBuilder with line buffer : 0 ms
> StringBuilder with char[] buffer: 0 ms
> StringBuffer with char[] buffer : 0 ms
> Allocate byte[filesize] : 1 ms
Reading 10k.txt (~313Kbytes)
Warm up... : 0 ms
> Concat with += : 708 ms
> StringBuilder init with length : 2 ms
> StringBuilder with line buffer : 2 ms
> StringBuilder with char[] buffer: 1 ms
> StringBuffer with char[] buffer : 1 ms
> Allocate byte[filesize] : 1 ms
Reading 100k.txt (~3136Kbytes)
Warm up... : 7 ms
> Concat with += **skipped** : 0 ms
> StringBuilder init with length : 19 ms
> StringBuilder with line buffer : 21 ms
> StringBuilder with char[] buffer: 9 ms
> StringBuffer with char[] buffer : 9 ms
> Allocate byte[filesize] : 8 ms
Reading 2142k.txt (~67204Kbytes)
Warm up... : 181 ms
> Concat with += **skipped** : 0 ms
> StringBuilder init with length : 367 ms
> StringBuilder with line buffer : 372 ms
> StringBuilder with char[] buffer: 208 ms
> StringBuffer with char[] buffer : 202 ms
> Allocate byte[filesize] : 199 ms
Reading pruned-names.csv (~11200Kbytes)
Warm up... : 23 ms
> Concat with += **skipped** : 0 ms
> StringBuilder init with length : 54 ms
> StringBuilder with line buffer : 57 ms
> StringBuilder with char[] buffer: 32 ms
> StringBuffer with char[] buffer : 31 ms
> Allocate byte[filesize] : 32 ms
Reading /Users/hansi/Downloads/xcode46graphicstools6938140a.dmg (~123429Kbytes)
Warm up... : 1665 ms
> Concat with += **skipped** : 0 ms
> StringBuilder init with length : 2899 ms
> StringBuilder with line buffer : 2978 ms
> StringBuilder with char[] buffer: 2702 ms
> StringBuffer with char[] buffer : 2684 ms
> Allocate byte[filesize] : 1567 ms
**/
聚苯乙烯。您可能已经注意到StringBuffer比StringBuilder稍快。这有点无稽之谈,因为类是相同的,除了StringBuilder不同步。如果有人可以(或)不能重现这个...我最好奇:)
答案 3 :(得分:1)
我写了一个与你的功能相同的功能。我写了一段时间,但我相信它仍然可以正常工作。
public static final String grabAsSingleString(File fileToUse)
throws FileNotFoundException {
BufferedReader theReader = null;
String returnString = null;
try {
theReader = new BufferedReader(new FileReader(fileToUse));
char[] charArray = null;
if(fileToUse.length() > Integer.MAX_VALUE) {
// TODO implement handling of large files.
System.out.println("The file is larger than int max = " +
Integer.MAX_VALUE);
} else {
charArray = new char[(int)fileToUse.length()];
// Read the information into the buffer.
theReader.read(charArray, 0, (int)fileToUse.length());
returnString = new String(charArray);
}
} catch (FileNotFoundException ex) {
throw ex;
} catch(IOException ex) {
ex.printStackTrace();
} finally {
try {
theReader.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
return returnString;
}
现在您可以根据需要使用此功能,但是当您通过文件对象或字符串传递文件时,请确保您提供文件的完整路径,例如“C:\ Program Files” \ test.dat“或者您传入工作目录中的相对链接。您的工作目录通常是您启动应用程序的目录(除非您更改它)。因此,如果文件位于名为data的文件夹中,您将传入“./data/test.dat”
是的,我知道这是在使用android,所以Windows URI不适用,但你应该明白我的观点。
答案 4 :(得分:1)
您应该尝试org.appache.commons.io.IOUtils.toString(InputStream is)
将文件内容作为字符串。在那里你可以传递你将从
InputStream
对象
getAssets().open("xml2json.txt")
在Activity
。
要String
使用此功能:
String xml = IOUtils.toString((getAssets().open("xml2json.txt")));