我正在从URL中检索XML提要,然后对其进行解析。我需要做的是将其存储在手机内部,以便在没有互联网连接时它可以解析保存的选项而不是实时选项。
我面临的问题是我可以创建 url 对象,使用 getInputStream 获取内容,但它不会让我保存它。
URL url = null;
InputStream inputStreamReader = null;
XmlPullParser xpp = null;
url = new URL("http://*********");
inputStreamReader = getInputStream(url);
ObjectOutput out = new ObjectOutputStream(new FileOutputStream(new File(getCacheDir(),"")+"cacheFileAppeal.srl"));
//--------------------------------------------------------
//This line is where it is erroring.
//--------------------------------------------------------
out.writeObject( inputStreamReader );
//--------------------------------------------------------
out.close();
任何想法,我可以保存输入流,以便以后加载它。
干杯
在这里,输入是你的inputStream
。然后使用相同的文件(名称)和FileInputStream
在将来读取数据。
try {
File file = new File(getCacheDir(), "cacheFileAppeal.srl");
try (OutputStream output = new FileOutputStream(file)) {
byte[] buffer = new byte[4 * 1024]; // or other buffer size
int read;
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
}
} finally {
input.close();
}
简单函数
试试这个简单的函数,把它整齐地包装在:
// Copy an InputStream to a File.
//
private void copyInputStreamToFile(InputStream in, File file) {
OutputStream out = null;
try {
out = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len;
while((len=in.read(buf))>0){
out.write(buf,0,len);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
// Ensure that the InputStreams are closed even if there's an exception.
try {
if ( out != null ) {
out.close();
}
// If you want to close the "in" InputStream yourself then remove this
// from here but ensure that you close it yourself eventually.
in.close();
}
catch ( IOException e ) {
e.printStackTrace();
}
}
}
感谢Jordan LaPrise和他的回答。
Kotlin 版本(经过测试,不需要库):
fun copyStreamToFile(inputStream: InputStream, outputFile: File) {
inputStream.use { input ->
val outputStream = FileOutputStream(outputFile)
outputStream.use { output ->
val buffer = ByteArray(4 * 1024) // buffer size
while (true) {
val byteCount = input.read(buffer)
if (byteCount < 0) break
output.write(buffer, 0, byteCount)
}
output.flush()
}
}
}
我们利用use
功能,该功能将在结束时自动关闭两个流。
即使发生异常,流也会正确关闭。
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html
https://kotlinlang.org/docs/tutorials/kotlin-for-py/scoped-resource-usage.html
较短的版本:
OutputStream out = new FileOutputStream(file);
fos.write(IOUtils.read(in));
out.close();
in.close();
这是一个处理所有异常的解决方案,并且基于前面的答案:
void writeStreamToFile(InputStream input, File file) {
try {
try (OutputStream output = new FileOutputStream(file)) {
byte[] buffer = new byte[4 * 1024]; // or other buffer size
int read;
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 在应用程序的
build.gradle
文件中,在dependencies
下添加:
implementation 'commons-io:commons-io:2.5'
- 在您的代码中:
import org.apache.commons.io.FileUtils;
// given you have a stream, e.g.
InputStream inputStream = getContext().getContentResolver().openInputStream(uri);
// you can now write it to a file with
FileUtils.copyToFile(inputStream, new File("myfile.txt"));
有 IOUtils 的方式:
copy(InputStream input, OutputStream output)
它的代码类似于这样:
public static long copyStream(InputStream input, OutputStream output) throws IOException {
long count = 0L;
byte[] buffer = new byte[4096];
for (int n; -1 != (n = input.read(buffer)); count += (long) n)
output.write(buffer, 0, n);
return count;
}
使用谷歌番石榴
import com.google.common.io.ByteStreams;
法典:
try (FileOutputStream fos = new FileOutputStream(new File("C:\example.txt"))){
ByteStreams.copy(inputStream, fos)
}
现代 Kotlin 方式
fun File.copyInputStreamToFile(inputStream: InputStream?) {
outputStream().use { fileOut ->
inputStream?.copyTo(fileOut)
}
}
// Sample of usage
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
data?.data?.let { uri ->
val inputStream = contentResolver.openInputStream(uri)
val file = File(cacheDir, "todo_filename.jpg")
file.copyInputStreamToFile(inputStream)
}
}
更多的 Kotlin-y 方法:
fun copyInputStreamToFile(inputStream: InputStream, file: File) {
try {
inputStream.use { input ->
FileOutputStream(file).use { input.copyTo(it) }
}
} catch (e: IOException) {
e.printStackTrace()
}
}
我们对inputStream
和FileOutputStream
都使用 use
函数。use 函数可确保资源在不再需要后正确关闭,即使在异常的情况下也是如此。
此外,我们还利用可用于 InputStream 的copyTo
扩展函数,该功能简化了复制过程并在内部处理缓冲和循环逻辑。这使代码更加简洁,并减少了与资源管理相关的错误的可能性。