Comment puis-je obtenir un java.io.InputStream à partir d’un java.lang.Ssortingng?

J’ai une Ssortingng que je veux utiliser en tant que InputStream . Dans Java 1.0, vous pouvez utiliser java.io.SsortingngBufferInputStream , mais cela a été @Deprecrated (avec raison – vous ne pouvez pas spécifier le codage du jeu de caractères):

Cette classe ne convertit pas correctement les caractères en octets. À partir de JDK 1.1, la méthode préférée pour créer un stream à partir d’une chaîne est la classe SsortingngReader .

Vous pouvez créer un java.io.Reader avec java.io.SsortingngReader , mais il n’y a pas d’adaptateurs pour prendre un Reader et créer un InputStream .

J’ai trouvé un ancien bug demandant un remplacement approprié, mais rien de tel n’existe – pour autant que je sache.

La solution souvent suggérée consiste à utiliser java.lang.Ssortingng.getBytes() comme entrée de java.io.ByteArrayInputStream :

 public InputStream createInputStream(Ssortingng s, Ssortingng charset) throws java.io.UnsupportedEncodingException { return new ByteArrayInputStream(s.getBytes(charset)); } 

mais cela signifie matérialiser l’intégralité de la Ssortingng en mémoire sous la forme d’un tableau d’octets et vaincre l’objective d’un stream. Dans la plupart des cas, ce n’est pas un gros problème, mais je cherchais quelque chose qui préserverait l’intention d’un stream – le moins de données possible étant (re) matérialisées dans la mémoire.

Mise à jour: Cette réponse est précisément ce que le PO ne veut pas. Veuillez lire les autres réponses.

Pour les cas où nous ne nous soucions pas de la re-matérialisation des données en mémoire, veuillez utiliser:

 new ByteArrayInputStream(str.getBytes("UTF-8")) 

Si vous ne vous souciez pas de la dépendance au paquetage commons-io , vous pouvez utiliser la méthode IOUtils.toInputStream (texte texte) .

À mon avis, le moyen le plus simple de le faire est de transmettre les données à un rédacteur:

 public class SsortingngEmitter { public static void main(Ssortingng[] args) throws IOException { class DataHandler extends OutputStream { @Override public void write(final int b) throws IOException { write(new byte[] { (byte) b }); } @Override public void write(byte[] b) throws IOException { write(b, 0, b.length); } @Override public void write(byte[] b, int off, int len) throws IOException { System.out.println("bytecount=" + len); } } SsortingngBuilder sample = new SsortingngBuilder(); while (sample.length() < 100 * 1000) { sample.append("sample"); } Writer writer = new OutputStreamWriter( new DataHandler(), "UTF-16"); writer.write(sample.toString()); writer.close(); } } 

L'implémentation de la machine virtuelle Java par laquelle j'utilise les données générées par paquets de 8 Ko, mais vous pourriez avoir une incidence sur la taille de la mémoire tampon en réduisant le nombre de caractères écrits en même temps et en appelant le vidage.


Une alternative à l'écriture de votre propre wrapper CharsetEncoder pour utiliser un Writer pour encoder les données, même si cela peut s'avérer difficile. Cela devrait être une implémentation fiable (si inefficace):

 /** Inefficient ssortingng stream implementation */ public class SsortingngInputStream extends InputStream { /* # of characters to buffer - must be >=2 to handle surrogate pairs */ private static final int CHAR_CAP = 8; private final Queue buffer = new LinkedList(); private final Writer encoder; private final Ssortingng data; private int index; public SsortingngInputStream(Ssortingng sequence, Charset charset) { data = sequence; encoder = new OutputStreamWriter( new OutputStreamBuffer(), charset); } private int buffer() throws IOException { if (index >= data.length()) { return -1; } int rlen = index + CHAR_CAP; if (rlen > data.length()) { rlen = data.length(); } for (; index < rlen; index++) { char ch = data.charAt(index); encoder.append(ch); // ensure data enters buffer encoder.flush(); } if (index >= data.length()) { encoder.close(); } return buffer.size(); } @Override public int read() throws IOException { if (buffer.size() == 0) { int r = buffer(); if (r == -1) { return -1; } } return 0xFF & buffer.remove(); } private class OutputStreamBuffer extends OutputStream { @Override public void write(int i) throws IOException { byte b = (byte) i; buffer.add(b); } } } 

Il existe un adaptateur de Apache Commons-IO qui s’adapte de Reader à InputStream, nommé ReaderInputStream .

Exemple de code:

 @Test public void testReaderInputStream() throws IOException { InputStream inputStream = new ReaderInputStream(new SsortingngReader("largeSsortingng"), StandardCharsets.UTF_8); Assert.assertEquals("largeSsortingng", IOUtils.toSsortingng(inputStream, StandardCharsets.UTF_8)); } 

Référence: https://stackoverflow.com/a/27909221/5658642

Eh bien, une façon possible est de:

  • Créer un PipedOutputStream
  • Pipe-le sur un PipedInputStream
  • Enroulez un OutputStreamWriter autour du PipedOutputStream (vous pouvez spécifier le codage dans le constructeur)
  • Et voilá, tout ce que vous écrivez dans OutputStreamWriter peut être lu depuis PipedInputStream !

Bien sûr, cela semble être une façon plutôt malicieuse de le faire, mais au moins c’est un moyen.

Une solution consiste à déployer vos propres, en créant une implémentation InputStream qui utiliserait probablement java.nio.charset.CharsetEncoder pour encoder chaque caractère ou bloc de caractères sur un tableau d’octets pour le InputStream si nécessaire.

Je sais que c’est une vieille question mais j’ai eu le même problème aujourd’hui, et c’était ma solution:

 public static InputStream getStream(final CharSequence charSequence) { return new InputStream() { int index = 0; int length = charSequence.length(); @Override public int read() throws IOException { return index>=length ? -1 : charSequence.charAt(index++); } }; } 

Vous pouvez prendre l’aide de la bibliothèque org.hsqldb.lib.

 public SsortingngInputStream(Ssortingng paramSsortingng) { this.str = paramSsortingng; this.available = (paramSsortingng.length() * 2); }