IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Format d'échange (XML, JSON...) Java Discussion :

Décompression d'un fichier de format .xml.gz téléchargé


Sujet :

Format d'échange (XML, JSON...) Java

  1. #1
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2007
    Messages
    365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mars 2007
    Messages : 365
    Par défaut Décompression d'un fichier de format .xml.gz téléchargé
    Bonjour à tous,

    Je en train d'effectuer un test de décompression d'un fichier de format .xml.gz en extension .xml que j'ai téléchargé par un de mes programmes java.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     try{
    			InputStream is = new FileInputStream(FichierZippe);
    			CompressorInputStream in = new CompressorStreamFactory().createCompressorInputStream("gz", is);
    			IOUtils.copy(in, new FileOutputStream("E:/dossier/liste.xml"));
    			in.close();	
    			} 
    		catch(Exception e){
    			e.printStackTrace();
    		}
    Seulement voilà j'ai une erreur suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Response content length: 1191994
    java.util.zip.ZipException: oversubscribed literal/length tree
    	at java.util.zip.InflaterInputStream.read(Unknown Source)
    	at java.util.zip.GZIPInputStream.read(Unknown Source)
    	at java.util.zip.InflaterInputStream.read(Unknown Source)
    	at org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream.read(GzipCompressorInputStream.java:51)
    	at java.io.InputStream.read(Unknown Source)
    	at java.io.InputStream.read(Unknown Source)
    	at org.apache.commons.compress.utils.IOUtils.copy(IOUtils.java:66)
    	at org.apache.commons.compress.utils.IOUtils.copy(IOUtils.java:47)
    	at org.apache.http.examples.client.ClientAuthentication.decompresseGZ(ClientAuthentication.java:288)
    	at org.apache.http.examples.client.ClientAuthentication.main(ClientAuthentication.java:176)

    Je voudrais savoir l'origine de cet erreur ?

    Voici les packages utilisés provenant d'Apache :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import org.apache.commons.compress.compressors.CompressorInputStream;
    import org.apache.commons.compress.compressors.CompressorStreamFactory;
    import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
    import org.apache.commons.compress.utils.IOUtils;
    import org.apache.commons.httpclient.Header;
    import org.apache.commons.httpclient.HeaderElement;
    import org.apache.commons.httpclient.HttpException;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpRequestInterceptor;
    import org.apache.http.HttpResponse;
    import org.apache.http.HttpResponseInterceptor;
    import org.apache.http.auth.AuthScope;
    import org.apache.http.auth.UsernamePasswordCredentials;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;

    Je vous montre également le code que j'utilise pour télécharger le fichier xml compressé par le protocole http avec authentification :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
     
     public static void main(String[] args) {
     
        	try{
        	DefaultHttpClient httpclient = new DefaultHttpClient();
     
            httpclient.getCredentialsProvider().setCredentials(
                    new AuthScope("siteweb.com", 80), 
                    new UsernamePasswordCredentials("utilisateur", "motdepasse"));
     
     
            HttpGet httpget = new HttpGet("http://siteweb.com/dossier/liste.xml.gz");
     
            System.out.println("executing request" + httpget.getRequestLine());
            HttpResponse response = httpclient.execute(httpget);
            HttpEntity entity = response.getEntity();
     
            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
            }
     
            if(entity != null){
            	BufferedReader in = new BufferedReader(new InputStreamReader(entity.getContent()));
            	BufferedWriter out = new BufferedWriter(new FileWriter("E:/dossier/liste.xml.gz"));
     
    		   String chaine = null;
    		    chaine = in.readLine();
    		    while(chaine != null)
    		    {
    		    	out.write(chaine);
    		    	chaine = in.readLine();
     
    		    }
     
    		    in.close ();
    		    out.close();
            }
     
            if (entity != null) {
                entity.consumeContent();
            }
     
     
            httpclient.getConnectionManager().shutdown();  
     
            decompresseGZ("E:/dossier/liste.xml.gz","E:/dossier/");
        	}catch(Exception e){
        		e.printStackTrace();
        	}
        }


    Cordialement .

  2. #2
    Membre Expert
    Avatar de polymorphisme
    Homme Profil pro
    Publishing
    Inscrit en
    Octobre 2009
    Messages
    1 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Publishing
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2009
    Messages : 1 460
    Par défaut
    Le compilateur te signale un problème à la ligne 51 de ton programme.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    at org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream.read(GzipCompressorInputStream.java:51)
    Après, ne connaissant pas cette librairie, je ne saurais t'en dire plus.

    Je vous montre également le code que j'utilise pour télécharger le fichier xml compressé par le protocole http avec authentification
    J'en vois pas bien l'interêt.

  3. #3
    Membre Expert
    Avatar de Patriarch24
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2003
    Messages
    1 047
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 047
    Par défaut
    As-tu essayé de décompresser le fichier avec un outil tel gunzip ? D'autres ?

    Peut-être utilises-tu mal la lib, ou alors le fichier en lui-même est corrompu (soit sur le serveur, soit lors du transfert).

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    ou alors c'est pas un vrai gz :p

  5. #5
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2007
    Messages
    365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mars 2007
    Messages : 365
    Par défaut
    Bonsoir à tous,

    Je reviens vers vous et pense que cela provient du programme qui joue le rôle de téléchargement.

    Puisque lorsque j'ouvre le fichier compressé en gz avec le logiciel de WinRar . j'ai l'erreur suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    !   F:\donnees_xml\List.xml.gz: Echec CRC dans CategoriesList.xml. Le fichier est corrompu

    Voici le code qui permet de télécharger le fichier compressé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
     
    /*
     * ====================================================================
     *
     *  Licensed to the Apache Software Foundation (ASF) under one or more
     *  contributor license agreements.  See the NOTICE file distributed with
     *  this work for additional information regarding copyright ownership.
     *  The ASF licenses this file to You under the Apache License, Version 2.0
     *  (the "License"); you may not use this file except in compliance with
     *  the License.  You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     *  Unless required by applicable law or agreed to in writing, software
     *  distributed under the License is distributed on an "AS IS" BASIS,
     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *  See the License for the specific language governing permissions and
     *  limitations under the License.
     * ====================================================================
     *
     * This software consists of voluntary contributions made by many
     * individuals on behalf of the Apache Software Foundation.  For more
     * information on the Apache Software Foundation, please see
     * <http://www.apache.org/>.
     *
     * [Additional notices, if required by prior licensing conditions]
     *
     */
     
    package authentification_http;
     
    import com.sun.net.httpserver.*;
     
    import org.apache.http.Header;
    import org.apache.http.HeaderElement;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpException;
    import org.apache.http.HttpRequest;
    import org.apache.http.HttpRequestInterceptor;
    import org.apache.http.HttpResponse;
    import org.apache.http.HttpResponseInterceptor;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.entity.HttpEntityWrapper;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.params.HttpParams;
    import org.apache.http.protocol.HttpContext;
    import org.apache.http.util.EntityUtils;
     
     
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.zip.Adler32;
    import java.util.zip.CheckedInputStream;
    import java.util.zip.GZIPInputStream;
    import java.util.zip.GZIPOutputStream;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipInputStream;
     
    import org.apache.commons.compress.compressors.CompressorInputStream;
    import org.apache.commons.compress.compressors.CompressorStreamFactory;
    import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
    import org.apache.commons.compress.utils.IOUtils;
     
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpRequest;
    import org.apache.http.HttpRequestInterceptor;
    import org.apache.http.HttpResponse;
    import org.apache.http.HttpResponseInterceptor;
    import org.apache.http.auth.AuthScope;
    import org.apache.http.auth.UsernamePasswordCredentials;
     
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.BasicResponseHandler;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.omg.CORBA.portable.ResponseHandler;
     
    /**
     * A simple example that uses HttpClient to execute an HTTP request against
     * a target site that requires user authentication.
     */
    public class ClientAuthentication {
     
        public static void main(String[] args) {
     
        	try{
        	DefaultHttpClient httpclient = new DefaultHttpClient();
     
     
        	httpclient.addRequestInterceptor(new HttpRequestInterceptor(){
     
                 public void process(
                         final HttpRequest request,
                         final HttpContext context) throws HttpException, IOException {
                     if (!request.containsHeader("Accept-Encoding")) {
     
                     	System.out.println("test");
     
                     	request.addHeader("Accept-Encoding","gzip,deflate");
     
                     	System.out.println(request.getLastHeader("Accept-Encoding"));
                     //	request.addHeader("Accept-Charset","ISO-8859-1,utf-8;q=0.7,*;q=0.7");
     
                     }
                 }
     
             });
     
     
     
     
            httpclient.addResponseInterceptor(new HttpResponseInterceptor(){
     
                public void process(
                        final HttpResponse response,
                        final HttpContext context) throws HttpException, IOException {
                    HttpEntity entity = response.getEntity();
                    org.apache.http.Header ceheader = entity.getContentEncoding();
                    if (ceheader != null) {
                        org.apache.http.HeaderElement[] codecs = ceheader.getElements();
                        for (int i = 0; i < codecs.length; i++) {
                            if (codecs[i].getName().equalsIgnoreCase("gzip")) {
                                response.setEntity(
                                        new GzipDecompressingEntity(response.getEntity()));
                                return;
                            }
                        }
                    }
                }
     
            });
     
     
     
     
     
            // ======================================================================================
     
            HttpGet httpget = new HttpGet("http://monsite.com/export/List.xml.gz");
     
             httpget.addHeader("Accept-Encoding","gzip,deflate");
     
            httpclient.getCredentialsProvider().setCredentials(
                    new AuthScope("monsite.com", 80),
                    new UsernamePasswordCredentials("user", "password"));
     
            HttpResponse response = httpclient.execute(httpget);
     
            HttpEntity entity = response.getEntity();
     
     
            System.out.println("Accept-Encoding : " + response.getLastHeader("Accept-Encoding") );
     
            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
            }
     
            if(entity != null){
            	BufferedReader in = new BufferedReader(new InputStreamReader(entity.getContent()));
            	BufferedWriter out = new BufferedWriter(new FileWriter("F:/donnees_xml/List.xml.gz"));
            	String chaine = null;
    		    chaine = in.readLine();
    		    while(chaine != null)
    		    {
    		    	out.write(chaine);
     
    		    	chaine = in.readLine();
    		    }
     
    		    in.close ();
    		    out.close();
            }
     
     
            if (entity != null) {
                entity.consumeContent();
            }
     
           //======================================================================================================
     
            // When HttpClient instance is no longer needed,
            // shut down the connection manager to ensure
            // immediate deallocation of all system resources
            httpclient.getConnectionManager().shutdown();
     
            decompresseGZ("F:/donnees_xml/List.xml.gz","C:/dossier/");
        	}catch(Exception e){
        		e.printStackTrace();
        	}
        }
     
     
     
        /**
             * Cette méthode permettra de décompresser les fichier zip pour les 
             * @param FichierZippe
             * @param DossierFichiersDezippes
             */
    	public static void DeZipperUnFichier(String FichierZippe, String DossierFichiersDezippes){
    		int TAILLE_BUFFER = 20000;
    		byte[] tabByte = new byte[TAILLE_BUFFER];
    		int nbLecture = 0;
    		try {
    			System.out.println("Test de décompression");
    			File fichier = new File(FichierZippe);
     
    			FileInputStream FichierADezipper = new FileInputStream(fichier);
    			CheckedInputStream cis =new CheckedInputStream(FichierADezipper,new Adler32());
    			BufferedInputStream Buff = new BufferedInputStream(cis);
     
     
    			ZipInputStream FichierADecompresser = new ZipInputStream(Buff);
     
     
    			ZipEntry  Entree = FichierADecompresser.getNextEntry();
     
    			BufferedOutputStream fichierACreer;
     
    			while(Entree!=null){
    				System.out.println(DossierFichiersDezippes + Entree.getName());
    				fichierACreer = new BufferedOutputStream(new FileOutputStream(DossierFichiersDezippes + Entree.getName()),TAILLE_BUFFER);
    				nbLecture = FichierADecompresser.read(tabByte);
     
    				while(nbLecture > 0){
    					fichierACreer.write(tabByte,0,nbLecture);
    					nbLecture = FichierADecompresser.read(tabByte);
    				}
     
    				fichierACreer.close();
    				FichierADecompresser.closeEntry();
     
    				Entree = FichierADecompresser.getNextEntry();
     
    			}
     
    			FichierADecompresser.close();
    			Buff.close();
    			cis.close();
    			FichierADezipper.close();
     
     
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
     
    	}
     
     
        public static void decompresseGZ(String FichierZippe, String DossierFichiersDezippes){
     
    		 try{
     
    			 System.out.println(FichierZippe);
     
    			InputStream is = new FileInputStream(FichierZippe);
    			CompressorInputStream in = new CompressorStreamFactory().createCompressorInputStream("gz", is);
    			IOUtils.copy(in, new FileOutputStream("F:/donnees_xml/List.xml"));
    			in.close();
    			}
    		catch(Exception e){
    			e.printStackTrace();
    		}
    	}
     
        static class GzipDecompressingEntity extends HttpEntityWrapper {
     
            public GzipDecompressingEntity(final HttpEntity entity) {
                super(entity);
            }
     
            //@Override
            public InputStream getContent()
                throws IOException, IllegalStateException {
     
                // the wrapped entity's getContent() decides about repeatability
                InputStream wrappedin = wrappedEntity.getContent();
     
                return new GZIPInputStream(wrappedin);
            }
     
            //@Override
            public long getContentLength() {
                // length of ungzipped content is not known
                return -1;
            }
     
        }
     
    }
    Le fichier est probablement corrompu suite au téléchargement .

    Cordialement .

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            	BufferedReader in = new BufferedReader(new InputStreamReader(entity.getContent()));
            	BufferedWriter out = new BufferedWriter(new FileWriter("F:/donnees_xml/List.xml.gz"));
    Les readers/writer, c'est pour du texte, pas du binaire!

  7. #7
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2007
    Messages
    365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mars 2007
    Messages : 365
    Par défaut
    Merci

    Je vais essayer de retrouver le code pour écrire le fichier téléchargé en binaire et reviendrais vers vous .

  8. #8
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2007
    Messages
    365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mars 2007
    Messages : 365
    Par défaut
    D'accord,

    J'ai effectué un essai sur le téléchargement des fichiers compressés j'arrive à les décrompresser par Winrar ou Java sans difficultés et même les ouvrir. J'ai fait appèle aux classes de DataOutPutStream et DataInputStream

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    DataInputStream in = new DataInputStream(entity.getContent());
    DataOutputStream out =  new DataOutputStream(new FileOutputStream(REPERTOIRE_DESTINATAIRE + FICHIER_XML + ".gz"))  ;
    Pour gérer les fichiers binaires.

    En vous remerciant.

  9. #9
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    quelle est l'utilité des DAtaInput/Output dans ton cas, les InputStream et OutpuStream brut son largement suffisants!!

Discussions similaires

  1. modifier/sauvegarder un fichier en format XML
    Par LN(a) dans le forum Delphi
    Réponses: 6
    Dernier message: 07/12/2006, 11h17
  2. Réponses: 3
    Dernier message: 28/11/2006, 08h44
  3. [XML]lire un gros fichier de format xml et l'envoyer
    Par diamonds dans le forum XML/XSL et SOAP
    Réponses: 1
    Dernier message: 17/10/2006, 15h33
  4. [java][xml] Peut-on convertir un fichier au format XML?
    Par Penelope333 dans le forum Format d'échange (XML, JSON...)
    Réponses: 4
    Dernier message: 10/02/2006, 21h20
  5. Lecture de fichier au format XML ??
    Par nico0007 dans le forum Langage
    Réponses: 1
    Dernier message: 07/07/2005, 15h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo