2010-07-11 181 views
19

我想从URLConnection读取二进制文件。当我用文本文件测试它时,它似乎工作正常,但对于二进制文件它没有。当文件发出时,我在服务器上使用以下MIME类型:从URLConnection读取二进制文件

application/octet-stream 

但是到目前为止似乎没有任何工作。这是我用来接收文件的代码:

file = File.createTempFile("tempfile", ".bin"); 
file.deleteOnExit(); 

URL url = new URL("http://somedomain.com/image.gif"); 

URLConnection connection = url.openConnection(); 

BufferedReader input = new BufferedReader(new InputStreamReader(connection.getInputStream())); 

Writer writer = new OutputStreamWriter(new FileOutputStream(file)); 

int c; 

while((c = input.read()) != -1) { 

    writer.write((char)c); 
} 

writer.close(); 

input.close(); 

回答

34

这是我要做的事,

input = connection.getInputStream(); 
byte[] buffer = new byte[4096]; 
int n; 

OutputStream output = new FileOutputStream(file); 
while ((n = input.read(buffer)) != -1) 
{ 
    output.write(buffer, 0, n); 
} 
output.close(); 
+7

'n> 0'测试是不必要的。根据javadocs,可以返回零的唯一情况是'buffer.length'为零。 – 2010-07-11 22:00:52

+5

...并且无论如何零长度写是无害的。 – EJP 2010-07-12 06:47:37

+0

你救了我的一天:) – 2014-01-20 21:47:10

14

如果你想读一个二进制流,不应该在任何形式的Reader包裹InputStream。使用InputStream.read(byte[], int, int)方法将数据读入字节数组缓冲区。然后从缓冲区写入FileOutputStream

您正在读/写文件的方式会使用您平台的默认字符编码将其转换为“字符”并返回字节。这可能会破坏二进制数据。 (有一个字符集(LATIN-1),它提供了字节和值空间子集之间的1对1无损映射,但即使映射工作,这也是一个坏主意。被翻译/从byte[]二进制数据复制到char[],然后再返回......实现的只有在这种情况下)。

+0

或者你可以尝试包装你的InputStream进入BufferedInputStream。 – bhups 2010-07-11 06:33:06

+1

@bhups - 这是真的,但它只会帮助你做很多小的读取。如果你专门做大块读取,BufferedInputStream实际上会降低吞吐量。 – 2010-07-11 06:42:28

+1

这是正确的; 'InputStreamReader'会将字节数据转换为UTF-16字符数据(在这种情况下,使用默认的平台编码,即使对于文本/纯文本也是一个坏主意)。 Java char不像其他语言中的那样是八位字节。 – McDowell 2010-07-11 09:25:55