Android - 将输入流存储在文件中
Posted
技术标签:
【中文标题】Android - 将输入流存储在文件中【英文标题】:Android - Store inputstream in file 【发布时间】:2012-06-06 22:14:44 【问题描述】:我正在从 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();
关于如何保存输入流以便稍后加载的任何想法。
干杯
【问题讨论】:
【参考方案1】:您可以使用Google Guava
import com.google.common.io.ByteStreams;
代码:
try (FileOutputStream fos = new FileOutputStream(new File("C:\\example.txt")))
ByteStreams.copy(inputStream, fos)
【讨论】:
【参考方案2】:-
在您应用程序的
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"));
【讨论】:
我把implementation 'commons-io:commons-io:2.5
同步了,但它以红色显示 import org.apache.commons.io.FileUtils;
的 FileUtils?【参考方案3】:
在这里,输入是您的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();
【讨论】:
嵌套尝试块? 异常随时可能发生,否则会泄漏系统资源。 “input”变量是 InputStream 的一个实例,而不是 InputStreamReader。【参考方案4】: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
【讨论】:
对不起,如果发生异常(例如,断线),我们可以将异常重新抛出到上层吗?【参考方案5】:这是一个处理所有异常的解决方案,它基于之前的答案:
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();
【讨论】:
【参考方案6】:有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;
【讨论】:
【参考方案7】:简单函数
试试这个简单的函数把它整齐地包起来:
// 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 和他的answer。
【讨论】:
out.close() 应该在 finally 块中,以避免在发生异常时泄漏资源。如果在此处执行 in.close() 则相同,尽管关闭它确实是调用者的责任。 @jk7 实际上你可能是对的。看看更新后的答案。【参考方案8】:更短的版本:
OutputStream out = new FileOutputStream(file);
fos.write(IOUtils.read(in));
out.close();
in.close();
【讨论】:
因为它需要来自 Apache commons 的 IOUtils,并且这是添加到移动应用程序的重量级依赖项。大多数人更喜欢依赖于标准 SDK 类的解决方案。 对于测试(test
和 androidTest
工件),没关系,因为它不会包含在应用程序中。以上是关于Android - 将输入流存储在文件中的主要内容,如果未能解决你的问题,请参考以下文章