web-dev-qa-db-fra.com

InputStream à servletInputStream

J'ai ce InputStream:

InputStream inputStream = new ByteArrayInputStream(myString.getBytes(StandardCharsets.UTF_8));

Comment puis-je convertir cela en ServletInputStream?

J'ai essayé:

ServletInputStream  servletInputStream = (ServletInputStream) inputStream;

mais ne travaille pas.

MODIFIER:

Ma méthode est la suivante:

private static class LowerCaseRequest extends HttpServletRequestWrapper {

        public LowerCaseRequest(final HttpServletRequest request) throws IOException, ServletException {
            super(request);
        }

        @Override
        public ServletInputStream getInputStream() throws IOException {

            ServletInputStream servletInputStream;

            StringBuilder jb = new StringBuilder();
            String line;
            String toLowerCase = "";

            BufferedReader reader = new BufferedReader(new InputStreamReader(super.getInputStream()));
            while ((line = reader.readLine()) != null) {
                toLowerCase = jb.append(line).toString().toLowerCase();
            }

            InputStream inputStream = new ByteArrayInputStream(toLowerCase.getBytes(StandardCharsets.UTF_8));

            servletInputStream = (ServletInputStream) inputStream;

            return servletInputStream;

        }
 }

J'essaie de convertir toute ma demande en minuscule.

10
Goldbones

Essayez ce code.

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(myString.getBytes(StandardCharsets.UTF_8));
    ServletInputStream servletInputStream=new ServletInputStream(){
        public int read() throws IOException {
          return byteArrayInputStream.read();
        }
      }
9
aksappy

Mon conseil: ne créez pas la ByteArrayInputStream, utilisez simplement le tableau d'octets que vous avez déjà obtenu avec la méthode getBytes. Cela devrait suffire à créer une ServletInputStream.

Solution la plus basique

Malheureusement, la réponse de aksappy ne remplace que la méthode read. Bien que cela puisse suffire dans Servlet API 3.0 et versions ultérieures, il existe dans les versions ultérieures de l'API Servlet des méthodes three more que vous devez implémenter.

Voici mon implémentation de la classe, bien qu’elle devienne assez longue (en raison des nouvelles méthodes introduites dans l’API Servlet 3.1), vous voudrez peut-être envisager de la factoriser dans une classe imbriquée ou même de niveau supérieur.

    final byte[] myBytes = myString.getBytes("UTF-8");
    ServletInputStream servletInputStream = new ServletInputStream() {
        private int lastIndexRetrieved = -1;
        private ReadListener readListener = null;

        @Override
        public boolean isFinished() {
            return (lastIndexRetrieved == myBytes.length-1);
        }

        @Override
        public boolean isReady() {
            // This implementation will never block
            // We also never need to call the readListener from this method, as this method will never return false
            return isFinished();
        }

        @Override
        public void setReadListener(ReadListener readListener) {
            this.readListener = readListener;
            if (!isFinished()) {
                try {
                    readListener.onDataAvailable();
                } catch (IOException e) {
                    readListener.onError(e);
                }
            } else {
                try {
                    readListener.onAllDataRead();
                } catch (IOException e) {
                    readListener.onError(e);
                }
            }
        }

        @Override
        public int read() throws IOException {
            int i;
            if (!isFinished()) {
                i = myBytes[lastIndexRetrieved+1];
                lastIndexRetrieved++;
                if (isFinished() && (readListener != null)) {
                    try {
                        readListener.onAllDataRead();
                    } catch (IOException ex) {
                        readListener.onError(ex);
                        throw ex;
                    }
                }
                return i;
            } else {
                return -1;
            }
        }
    };

Ajout de méthodes attendues

En fonction de vos besoins, vous pouvez également vouloir remplacer d'autres méthodes. Comme Romfret l'a souligné, il est conseillé de remplacer certaines méthodes, telles que close et available. Si vous ne les implémentez pas, le flux signalera toujours qu'il y a 0 octet à lire, et la méthode close n'affectera en rien l'état du flux. Vous pouvez probablement vous en sortir sans surcharger skip, car l'implémentation par défaut appellera simplement read plusieurs fois.

    @Override
    public int available() throws IOException {
        return (myBytes.length-lastIndexRetrieved-1);
    }

    @Override
    public void close() throws IOException {
        lastIndexRetrieved = myBytes.length-1;
    }

Ecrire une meilleure méthode proche

Malheureusement, en raison de la nature d'une classe anonyme, il vous sera difficile d'écrire une méthode close efficace car, tant qu'une instance du flux n'a pas été collectée par Java, elle conserve une référence au tableau d'octets. , même si le flux a été fermé.

Cependant, si vous factorisez la classe dans une classe imbriquée ou de niveau supérieur (ou même une classe anonyme avec un constructeur appelé à partir de la ligne dans laquelle elle est définie), la variable myBytes peut être un champ non final plutôt qu'un champ. variable locale finale, et vous pouvez ajouter une ligne comme celle-ci:

myBytes = null;

à votre méthode close, qui permettra à Java de libérer de la mémoire occupée par le tableau d'octets.

Bien sûr, cela vous obligera à écrire un constructeur, tel que:

    private byte[] myBytes;

    public StringServletInputStream(String str) {
        try {
            myBytes = str.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException("JVM did not support UTF-8", e);
        }
    }

Marquer et réinitialiser

Vous pouvez également vouloir remplacer mark, markSupported et reset si vous souhaitez prendre en charge mark/reset. Cependant, je ne suis pas sûr qu'ils soient effectivement appelés par votre conteneur.

    private int readLimit = -1;
    private int markedPosition = -1;

    @Override
    public boolean markSupported() {
        return true;
    }

    @Override
    public synchronized void mark(int readLimit) {
        this.readLimit = readLimit;
        this.markedPosition = lastIndexRetrieved;
    }

    @Override
    public synchronized void reset() throws IOException {
        if (markedPosition == -1) {
            throw new IOException("No mark found");
        } else {
            lastIndexRetrieved = markedPosition;
            readLimit = -1;
        }
    }

    // Replacement of earlier read method to cope with readLimit
    @Override
    public int read() throws IOException {
        int i;
        if (!isFinished()) {
            i = myBytes[lastIndexRetrieved+1];
            lastIndexRetrieved++;
            if (isFinished() && (readListener != null)) {
                try {
                    readListener.onAllDataRead();
                } catch (IOException ex) {
                    readListener.onError(ex);
                    throw ex;
                }
                readLimit = -1;
            }
            if (readLimit != -1) {
                if ((lastIndexRetrieved - markedPosition) > readLimit) {
                    // This part is actually not necessary in our implementation
                    // as we are not storing any data. However we need to respect
                    // the contract.
                    markedPosition = -1;
                    readLimit = -1;
                }
            }
            return i;
        } else {
            return -1;
        }
    }
20
Kidburla

Vous pouvez seulement lancer quelque chose comme ceci:

ServletInputStream  servletInputStream = (ServletInputStream) inputStream;

si le inputStream que vous essayez de convertir est déjà un ServletInputStream. Il se plaindra s'il s'agit d'une autre implémentation de InputStream. Vous ne pouvez pas lancer un objet sur quelque chose qu'il n'est pas.

Dans un conteneur Servlet, vous pouvez obtenir un ServletInputStream à partir d'un ServletRequest:

ServletInputStream  servletInputStream = request.getInputStream();

Alors, qu'essayez-vous réellement de faire?

MODIFIER

Je suis intrigué par la raison pour laquelle vous souhaitez convertir votre requête en minuscule. Pourquoi ne pas simplement rendre votre servlet insensible à la casse? En d'autres termes, votre code pour mettre en minuscule les données de la demande peut être copié dans votre servlet, il peut alors le traiter là-bas ... cherchez toujours la solution la plus simple!

0
NickJ