Question

Pourquoi la méthode suivante est-elle bloquée?

public void pipe(Reader in, Writer out) {
    CharBuffer buf = CharBuffer.allocate(DEFAULT_BUFFER_SIZE);
    while( in.read(buf) >= 0 ) {
      out.append(buf.flip());
    }
}
Était-ce utile?

La solution

Répondant à ma propre question: vous devez appeler buf.clear () entre lu . Vraisemblablement, read est suspendu car le tampon est saturé. Le code correct est

public void pipe(Reader in, Writer out) {
    CharBuffer buf = CharBuffer.allocate(DEFAULT_BUFFER_SIZE);
    while( in.read(buf) >= 0 ) {
      out.append(buf.flip());
      buf.clear();
    }
}

Autres conseils

Je suppose que c'est une impasse. In.read (buf) verrouille le CharBuffer et empêche l’appel out.append (buf).

Cela suppose que CharBuffer utilise des verrous (d'une certaine sorte) dans la mise en œuvre. Que dit l'API à propos de la classe CharBuffer?

Edit: Désolé, une sorte de court-circuit dans mon cerveau ... je l'ai confondu avec autre chose.

Les CharBuffers ne fonctionnent pas avec les lecteurs et les rédacteurs aussi proprement qu'on pourrait le croire. En particulier, il n'y a pas de méthode Writer.append (CharBuffer buf) . La méthode appelée par l'extrait de question est Writer.append (CharSequence seq) , qui appelle simplement seq.toString () . La méthode CharBuffer.toString () renvoie la valeur de chaîne du tampon, mais ne le vide pas. L'appel ultérieur à Reader.read (CharBuffer buf) obtient un tampon déjà plein et renvoie donc 0, forçant la boucle à se poursuivre indéfiniment.

Bien que cela ressemble à un blocage, il s'agit en fait d'ajouter le contenu du tampon de la première lecture à l'écrivain à chaque passage dans la boucle. Donc, vous allez commencer à voir beaucoup de sorties dans votre destination ou la mémoire tampon interne du rédacteur augmentera, en fonction de la manière dont le rédacteur est implémenté.

Aussi ennuyeux qu'il soit, je recommanderais une implémentation char [], ne serait-ce que parce que la solution CharBuffer crée au moins deux nouveaux char [] à chaque passage dans la boucle.

public void pipe(Reader in, Writer out) throws IOException {
    char[] buf = new char[DEFAULT_BUFFER_SIZE];
    int count = in.read(buf);
    while( count >= 0 ) {
        out.write(buf, 0, count);
        count = in.read(buf);
    }
}

Je vous recommande de ne l'utiliser que si vous devez prendre en charge la conversion entre codages à deux caractères. Sinon, une implémentation ByteBuffer / Channel ou byte [] / IOStream serait préférable, même si vous utilisiez des caractères de piping.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top