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 类的解决方案。 对于测试(testandroidTest 工件),没关系,因为它不会包含在应用程序中。

以上是关于Android - 将输入流存储在文件中的主要内容,如果未能解决你的问题,请参考以下文章

我已将图像从 html 存储到输入流,所以我想将输入流存储到驱动器中的文件夹 [重复]

将输入流转换为文件android

如何将二进制消息作为输入流处理?

Java IO操作

c++如何用文件流将数据存储到一个TxT文件中

IO流