2010-07-11 6 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' равно нулю. –

+5

... и в любом случае запись нулевой длины безвредна. – EJP

+0

Ты спас мой день :) –

14

Если вы пытаетесь прочитать двоичный поток, вы не должны обернуть InputStream в Reader любого рода. Прочитайте данные в буфере массива байтов, используя метод InputStream.read(byte[], int, int). Затем запишите из буфера в FileOutputStream.

То, как вы в настоящее время читаете/записываете файл, преобразует его в «символы» и обратно в байты, используя кодировку символов по умолчанию вашей платформы. Это может привести к искажению двоичных данных.

(Существует кодировка (LATIN-1), которая обеспечивает сопоставление без потерь между байтами и подмножеством пространства значений char. Однако это плохая идея, даже когда отображение работает. переводить/копировать двоичные данные из byte[] в char[] и обратно ... который ничего не дает в этом контексте.)

+0

Или вы можете попробовать подведению свой InputStream в BufferedInputStream. – bhups

+1

@bhups - это правда, но это поможет, если вы собираетесь делать много небольших чтений. Если вы делаете только большие чтения блоков, BufferedInputStream фактически уменьшит пропускную способность. –

+1

Это правильно; 'InputStreamReader' преобразует байтовые данные в символьные данные UTF-16 (в этом случае используется кодировка платформы по умолчанию, что является плохой идеей даже для text/plain). Java-символ не является октетом, как на некоторых других языках. – McDowell

Смежные вопросы