2121import org .xmlpull .v1 .XmlPullParser ;
2222import org .xmlpull .v1 .XmlPullParserException ;
2323
24+ import java .io .BufferedInputStream ;
25+ import java .io .ByteArrayInputStream ;
2426import java .io .File ;
2527import java .io .FileInputStream ;
2628import java .io .FileNotFoundException ;
29+ import java .io .IOException ;
2730import java .io .InputStream ;
2831
2932/**
@@ -38,14 +41,21 @@ public class ParserFactory {
3841
3942 public static XmlPullParser create (File f )
4043 throws XmlPullParserException , FileNotFoundException {
41- KXmlParser parser = instantiateParser (f .getName ());
42- parser .setInput (new FileInputStream (f ), ENCODING );
43- return parser ;
44+ InputStream stream = new FileInputStream (f );
45+ return create (stream , f .getName (), f .length ());
4446 }
4547
4648 public static XmlPullParser create (InputStream stream , String name )
49+ throws XmlPullParserException {
50+ return create (stream , name , -1 );
51+ }
52+
53+ private static XmlPullParser create (InputStream stream , String name , long size )
4754 throws XmlPullParserException {
4855 KXmlParser parser = instantiateParser (name );
56+
57+ stream = readAndClose (stream , name , size );
58+
4959 parser .setInput (stream , ENCODING );
5060 return parser ;
5161 }
@@ -61,6 +71,61 @@ private static KXmlParser instantiateParser(String name) throws XmlPullParserExc
6171 return parser ;
6272 }
6373
74+ private static InputStream readAndClose (InputStream stream , String name , long size )
75+ throws XmlPullParserException {
76+ // just a sanity check. It's doubtful we'll have such big files!
77+ if (size > Integer .MAX_VALUE ) {
78+ throw new XmlPullParserException ("File " + name + " is too big to be parsed" );
79+ }
80+ int intSize = (int ) size ;
81+
82+ // create a buffered reader to facilitate reading.
83+ BufferedInputStream bufferedStream = new BufferedInputStream (stream );
84+ try {
85+ int avail ;
86+ if (intSize != -1 ) {
87+ avail = intSize ;
88+ } else {
89+ // get the size to read.
90+ avail = bufferedStream .available ();
91+ }
92+
93+ // create the initial buffer and read it.
94+ byte [] buffer = new byte [avail ];
95+ int read = stream .read (buffer );
96+
97+ // this is the easy case.
98+ if (read == intSize ) {
99+ return new ByteArrayInputStream (buffer );
100+ }
101+
102+ // check if there is more to read (read() does not necessarily read all that
103+ // available() returned!)
104+ while ((avail = bufferedStream .available ()) > 0 ) {
105+ if (read + avail > buffer .length ) {
106+ // just allocate what is needed. We're mostly reading small files
107+ // so it shouldn't be too problematic.
108+ byte [] moreBuffer = new byte [read + avail ];
109+ System .arraycopy (buffer , 0 , moreBuffer , 0 , read );
110+ buffer = moreBuffer ;
111+ }
112+
113+ read += stream .read (buffer , read , avail );
114+ }
115+
116+ // return a new stream encapsulating this buffer.
117+ return new ByteArrayInputStream (buffer );
118+
119+ } catch (IOException e ) {
120+ throw new XmlPullParserException ("Failed to read " + name , null , e );
121+ } finally {
122+ try {
123+ bufferedStream .close ();
124+ } catch (IOException e ) {
125+ }
126+ }
127+ }
128+
64129 private static class CustomParser extends KXmlParser {
65130 private final String mName ;
66131
0 commit comments