java InputStream 到 servletInputStream

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30484388/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 17:12:13  来源:igfitidea点击:

InputStream to servletInputStream

javainputstream

提问by Goldbones

I have this InputStream:

我有这个 InputStream:

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

How can I convert this to ServletInputStream?

如何将其转换为 ServletInputStream?

I have tried:

我努力了:

ServletInputStream  servletInputStream = (ServletInputStream) inputStream;

but do not work.

但不工作。

EDIT:

编辑:

My method is this:

我的方法是这样的:

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;

        }
 }

I′m trying to convert all my request to lowercase.

我正在尝试将我的所有请求转换为小写。

采纳答案by aksappy

Try this code.

试试这个代码。

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

回答by Adam Burley

My advice: don't create the ByteArrayInputStream, just use the byte array you got from the getBytesmethod already. This should be enough to create a ServletInputStream.

我的建议:不要创建ByteArrayInputStream,只需使用您已经从getBytes方法中获得的字节数组。这应该足以创建一个ServletInputStream.

Most basic solution

最基本的解决方案

Unfortunately, aksappy's answer only overrides the readmethod. While this may be enough in Servlet API 3.0 and below, in the later versions of Servlet API there are threemore methods you have to implement.

不幸的是,aksappy 的回答只覆盖了该read方法。虽然这在 Servlet API 3.0 及以下版本中可能就足够了,但在 Servlet API 的更高版本中,您还需要实现另外三个方法。

Here is my implementation of the class, although with it becoming quite long (due to the new methods introduced in Servlet API 3.1), you might want to think about factoring it out into a nested or even top-level class.

这是我对该类的实现,尽管它变得很长(由于 Servlet API 3.1 中引入的新方法),您可能需要考虑将其分解为嵌套类甚至顶级类。

    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;
            }
        }
    };

Adding expected methods

添加预期方法

Depending on your requirements, you may also want to override other methods. As romfret pointed out, it's advisable to override some methods, such as closeand available. If you don't implement them, the stream will always report that there are 0 bytes available to be read, and the closemethod will do nothing to affect the state of the stream. You can probably get away without overriding skip, as the default implementation will just call reada number of times.

根据您的要求,您可能还想覆盖其他方法。正如 romfret 指出的那样,建议覆盖一些方法,例如closeand available。如果不实现它们,流将始终报告有 0 个字节可供读取,并且该close方法不会影响流的状态。您可能无需覆盖就可以逃脱skip,因为默认实现只会调用read多次。

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

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

Writing a better close method

编写更好的关闭方法

Unfortunately, due to the nature of an anonymous class, it's going to be difficult for you to write an effective closemethod because as long as one instance of the stream has not been garbage-collected by Java, it maintains a reference to the byte array, even if the stream has been closed.

不幸的是,由于匿名类的性质,您将很难编写有效的close方法,因为只要流的一个实例未被 Java 垃圾收集,它就会维护对字节数组的引用,即使流已关闭。

However, if you factor out the class into a nested or top-level class (or even an anonymous class with a constructor which you call from the line in which it is defined), the myBytescan be a non-final field rather than a final local variable, and you can add a line like:

但是,如果您将类分解为嵌套类或顶级类(甚至是具有从定义它的行调用的构造函数的匿名类),则myBytes可以是非最终字段而不是最终字段局部变量,您可以添加如下一行:

myBytes = null;

to your closemethod, which will allow Java to free memory taken up by the byte array.

到您的close方法,这将允许 Java 释放字节数组占用的内存。

Of course, this will require you to write a constructor, such as:

当然,这需要你写一个构造函数,比如:

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

Mark and Reset

标记和重置

You may also want to override mark, markSupportedand resetif you want to support mark/reset. I am not sure if they are ever actually called by your container though.

您可能还需要重写markmarkSupportedreset如果你想支持标记/复位。我不确定它们是否真的被你的容器调用过。

    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;
        }
    }

回答by NickJ

You can only cast something like this:

你只能投射这样的东西:

ServletInputStream  servletInputStream = (ServletInputStream) inputStream;

if the inputStream you are trying to cast is actually a ServletInputStream already. It will complain if it's some other implementation of InputStream. You can't cast an object to something it isn't.

如果您尝试投射的 inputStream 实际上已经是一个 ServletInputStream 。如果它是 InputStream 的其他一些实现,它会抱怨。你不能将一个对象投射到它不是的东西上。

In a Servlet container, you can get a ServletInputStream from a ServletRequest:

在 Servlet 容器中,您可以从 ServletRequest 获取 ServletInputStream:

ServletInputStream  servletInputStream = request.getInputStream();

So, what are you actually trying to do?

那么,你究竟想做什么?

EDIT

编辑

I'm intrigued as to why you want to convert your request to lower-case - why not just make your servlet case-insensitive? In other words, your code to lower-case the request data can be copied into your servlet, then it can process it there... always look for the simplest solution!

我很好奇您为什么要将请求转换为小写 - 为什么不让您的 servlet 不区分大小写?换句话说,您的小写请求数据的代码可以复制到您的 servlet 中,然后它可以在那里处理它......总是寻找最简单的解决方案!