2010-07-11 4 views
19

J'essaie de lire un fichier binaire à partir d'un URLConnection. Lorsque je le teste avec un fichier texte, il semble fonctionner correctement, mais pas pour les fichiers binaires. J'utilise le type mime suivant sur le serveur lorsque le fichier est envoyé:Lecture du fichier binaire depuis URLConnection

application/octet-stream 

Mais jusqu'à présent, rien ne semble fonctionner. Voici le code que j'utilise pour recevoir le fichier:

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(); 

Répondre

34

Voici comment je le fais,

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

Le test 'n> 0' est inutile. Selon les javadocs, le seul cas où zéro peut être retourné est quand buffer.length est zéro. –

+5

... et dans tous les cas, une écriture de longueur nulle est inoffensive. – EJP

+0

Vous avez sauvé ma journée :) –

14

Si vous essayez de lire un flux binaire, vous ne devriez pas envelopper la InputStream dans un Reader de toute nature. Lisez les données dans un tampon de tableau d'octets en utilisant la méthode InputStream.read(byte[], int, int). Ensuite, écrivez à partir du tampon à FileOutputStream. La façon dont vous êtes en train de lire/écrire le fichier va le convertir en "caractères" et revenir en octets en utilisant le codage de caractères par défaut de votre plate-forme. Ceci est susceptible de manipuler les données binaires.

(Il y a un charset (LATIN-1) qui fournit un 1 à 1 cartographie sans perte entre les octets et un sous-ensemble de la valeur de l'espace char. Cependant, cela est une mauvaise idée même si la cartographie fonctionne. Vous y être la traduction/copier les données binaires de byte[] à char[] et à nouveau ... ce qui ne sert à rien dans ce contexte.)

+0

Ou vous pouvez essayer envelopper votre InputStream dans BufferedInputStream. – bhups

+1

@bhups - c'est vrai, mais cela n'aidera que si vous allez faire beaucoup de petites lectures. Si vous faites exclusivement des lectures de blocs volumineux, un BufferedInputStream réduit le débit un peu. –

+1

Ceci est correct. 'InputStreamReader' va transformer les données en octets en données de caractères UTF-16 (dans ce cas, en utilisant l'encodage par défaut de la plate-forme, ce qui est une mauvaise idée même pour le texte/plain). Un caractère Java n'est pas un octet comme dans d'autres langues. – McDowell