当我读取InputStream并尝试再次使用它时,我收到此错误。
<pack name="Pack" id="pack" required="yes">
<description>Pack</description>
<executable targetfile="${INSTALL_PATH}/bin/run.sh" os="unix" stage="never" failure="warn" keep="true" />
</pack>
我正在使用的代码是......
07-20 17:36:24.762 11253-11277/? W/System.err﹕ java.io.IOException
07-20 17:36:24.762 11253-11277/? W/System.err﹕ at java.io.InputStream.reset(InputStream.java:208)
07-20 17:36:24.762 11253-11277/? W/System.err﹕ at demo31.com.maps.GMapDirections$DownloadDocumentTask.doInBackground(GMapDirections.java:134)
07-20 17:36:24.762 11253-11277/? W/System.err﹕ at demo31.com.maps.GMapDirections$DownloadDocumentTask.doInBackground(GMapDirections.java:86)
07-20 17:36:24.762 11253-11277/? W/System.err﹕ at android.os.AsyncTask$2.call(AsyncTask.java:292)
07-20 17:36:24.762 11253-11277/? W/System.err﹕ at javautil.concurrent.FutureTask.run(FutureTask.java:237)
07-20 17:36:24.762 11253-11277/? W/System.err﹕ at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
07-20 17:36:24.762 11253-11277/? W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
07-20 17:36:24.762 11253-11277/? W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
07-20 17:36:24.762 11253-11277/? W/System.err﹕ at java.lang.Thread.run(Thread.java:818)
07-20 17:36:24.762 11253-11277/? D/GMapDirections﹕ Exception while downloading data: java.io.IOException
当我尝试解析iStream的内容时会启动异常,因为之前我已经使用BufferedReader读取了它。
@Override
protected Document doInBackground(ArrayList... latLngs) {
Log.d(TAG, "DownloadDocumentTask(doInBackground): Estoy dentro del background!!!");
try {
HttpsURLConnection urlConnection;
FileService file = new FileService();
InputStream iStream;
Document result;
file.writeLog(TAG, GMapDirections.class.getName(), getUrlConnection());
URL url = new URL(getUrlConnection());
// Creating an http connection to communicate with url
urlConnection = (HttpsURLConnection) url.openConnection();
// Connecting to url
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
urlConnection.setRequestProperty("charset", "utf-8");
urlConnection.setRequestProperty("Accept", "application/xml");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(false);
urlConnection.connect();
//Return data
iStream = urlConnection.getInputStream();
//Display what returns POST request
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
file.writeLog(GMapDirections.TAG, "doInBackground", sb.toString());
// Parse the data to a Document Object
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
result = builder.parse(iStream);
urlConnection.disconnect();
return result;
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "Exception while downloading data: " + e.toString());
}
return null;
}
那么,我如何使用DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
result = builder.parse(iStream);
阅读iStream
,然后用它来解析内容而不会出错?
答案 0 :(得分:2)
您的堆栈跟踪和代码似乎不匹配。从堆栈跟踪看起来,doInBackground递归调用自身,然后是InputStream.reset()。但我在你的代码中看不到任何电话。
关于重新阅读流的实际问题: 由于您显然已经尝试过(并且失败了)InputStream.reset(),因此该流中的数据量可能太大(或者您忘记调用InputStream.mark())。简单的方法是创建另一个连接+流并读取它。这确实意味着您将实际且低效地从URL传输两次数据。
更有效的方法:
将流的全部内容读入内存/或临时文件(取决于大小),然后将其用作数据源。
使用TeeInputStream(https://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/input/TeeInputStream.html)随时复制流数据。
答案 1 :(得分:0)
如果您想再次阅读Stream,则必须通过调用iStream.reset()
来自InputStream文档:http://developer.android.com/reference/java/io/InputStream.html
public synchronized void reset()
在API级别1中添加
将此流停留在最后标记的位置。如果自设置标记以来读取的字节数大于为标记提供的限制,或者未设置标记,则抛出anIOException。
此实现始终抛出IOException,具体的子类应提供正确的实现。
<强>抛出强>
IOException如果此流已关闭或发生另一个IOException。
答案 2 :(得分:0)
这是因为你致电BufferedReader.close()
。来自Javadocs,
关闭流并释放与其关联的所有系统资源。
我刚才看了一遍,因为我担心这样的序列:
new BufferedReader(new FileReader(...))
会泄漏FileReader
的Reader句柄。事实证明,BufferedReader.close
也关闭了基础读者。
答案 3 :(得分:0)
在您关闭所有流的位置添加finally
部分。移动try
块之外的流声明,即:
BufferedReader br;
InputStream iStream;
try {
// your regular code, but remove this line as you'll close later
// br.close();
} catch (Exception whatever) {
//...
} finally {
if (iStream != null) {
iStream.close(); // TODO you need to catch exception here too
}
}
答案 4 :(得分:0)
根据@emu的答案(见第1点)
更有效的方法:
的 1。将流的全部内容读入内存/或临时文件(取决于大小),然后将其用作数据源。
最好的解决方案是......
@Override
protected Document doInBackground(Void... voids) {
try {
HttpsURLConnection urlConnection;
FileService file = new FileService();
InputStream iStream;
Document result;
file.writeLog(TAG, GMapDirections.class.getName(), getUrlConnection());
URL url = new URL(getUrlConnection());
// Creating an http connection to communicate with url
urlConnection = (HttpsURLConnection) url.openConnection();
// Connecting to url
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
urlConnection.setRequestProperty("charset", "utf-8");
urlConnection.setRequestProperty("Accept", "application/xml");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(false);
urlConnection.connect();
//Return data
iStream = urlConnection.getInputStream();
// Parse the data to a Document Object
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
result = builder.parse(iStream);
urlConnection.disconnect();
//Write data get it from POST request
//Transform Document 2 InputStream
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Source xmlSource = new DOMSource(result);
Result outputTarget = new StreamResult(outputStream);
TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
iStream = new ByteArrayInputStream(outputStream.toByteArray());
//Write document in a file
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
file.writeLog(GMapDirections.TAG, "doInBackground", sb.toString());
//Return Document with data
return result;
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "Exception while downloading data: " + e.toString());
}
return null;
}