关于输入:Android – 将输入流存储在文件中

Android - Store inputstream in file

我从一个URL中检索一个XML提要,然后对其进行解析。我需要做的是将它存储在手机内部,这样当没有互联网连接时,它可以解析保存的选项而不是实时选项。

我面临的问题是,我可以创建URL对象,使用getinputstream获取内容,但它不允许我保存它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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();

任何关于如何保存输入流的想法,以便稍后加载。

干杯


在这里,输入是您的inputStreamReader。然后使用相同的文件(名称)和FileInputStream在将来读取数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
try {
    File file = new File(getCacheDir(),"cacheFileAppeal.srl");
    OutputStream output = new FileOutputStream(file);
    try {
        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 {
        output.close();
    }
} finally {
    input.close();
}


简单函数

尝试这个简单的函数,将其整齐地包装在:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 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();
        }
    }
}

多亏了乔丹·拉普瑞斯和他的回答。


较短版本:

1
2
3
4
OutputStream out = new FileOutputStream(file);
fos.write(IOUtils.read(in));
out.close();
in.close();


下面是一个处理所有异常的解决方案,它基于前面的答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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();
        }
    }
}


Kotlin版本(已测试,无需库):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fun copyStreamToFile(inputStream: InputStream, outputFile: File) {
    inputStream.use { inputStream ->
        val output = FileOutputStream(outputFile)
        output.use { outputStream ->
            val buffer = ByteArray(4 * 1024) // buffer size
            while (true) {
                val byteCount = inputStream.read(buffer)
                if (byteCount < 0) break
                outputStream.write(buffer, 0, byteCount)
            }
            outputStream.flush()
        }
    }
}

我们使用use功能,它将在结束时自动关闭两个流。


IOutils的方式是:

1
copy(InputStream input, OutputStream output)

其代码类似于:

1
2
3
4
5
6
7
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;
}