java输入输出流单向性(单向性可能表述不太正确)

输出流只能使用一次, 比如FileInputStream read到文件末尾, 这个 FileInputStream 就 相当于失效了 不能继续从头read了,列子代码如下

E:\test.txt: 文件内容:test test test

public static void main(String[] args) throws Exception{
        InputStream ips = new FileInputStream("E:\\test.txt");

        String s = copyToString(ips, Charset.forName("UTF-8"));
        System.out.println("first::::" + s);

        String s1 = copyToString(ips, Charset.forName("UTF-8"));
        System.out.println("second::::" + s1);
    }

    public static String copyToString(InputStream in, Charset charset) throws IOException {
        if (in == null) {
            return "";
        } else {
            StringBuilder out = new StringBuilder();
            InputStreamReader reader = new InputStreamReader(in, charset);
            char[] buffer = new char[4096];
            boolean var5 = true;

            int bytesRead;
            while((bytesRead = reader.read(buffer)) != -1) {
                out.append(buffer, 0, bytesRead);
            }

            return out.toString();
        }
    }

输出结果:
first::::test test test
second::::

怎么可以一个输入流读取两次呢?
后来百度了一下,发现了两个方法 ips.mark(0); ips.reset();
然后把main代码改成下面

public static void main(String[] args) throws Exception{
        InputStream ips = new FileInputStream("E:\\test.txt");
        ips.mark(0);
        String s = copyToString(ips, Charset.forName("UTF-8"));
        System.out.println("first::::" + s);
        ips.reset();
        String s1 = copyToString(ips, Charset.forName("UTF-8"));
        System.out.println("second::::" + s1);
    }

输出结果:
first::::test test test
Exception in thread “main” java.io.IOException: mark/reset not supported
at java.io.InputStream.reset(InputStream.java:348)
at TestMain.main(TestMain.java:15)

发现原来BufferedInputStream代码才支持这两个方法:
代码改成如下:

 public static void main(String[] args) throws Exception{
        InputStream ips = new BufferedInputStream(new FileInputStream("E:\\test.txt"));
        ips.mark(0);
        String s = copyToString(ips, Charset.forName("UTF-8"));
        System.out.println("first::::" + s);
        ips.reset();
        String s1 = copyToString(ips, Charset.forName("UTF-8"));
        System.out.println("second::::" + s1);
    }

输出结果:
first::::test test test
second::::test test test

做到了想要的效果,做了标记之后读取了两次。

//稍微看一下源码:
InputStream reset()方法源码:

 public synchronized void mark(int readlimit) {}

 public synchronized void reset() throws IOException {
        throw new IOException("mark/reset not supported");
    }

再看看BufferInputStream源码

   public synchronized void mark(int readlimit) {
        marklimit = readlimit;
        markpos = pos;
    }
  public synchronized void reset() throws IOException {
        getBufIfOpen(); // Cause exception if closed
        if (markpos < 0)
            throw new IOException("Resetting to invalid mark");
        pos = markpos;
    }

再对比FileInputStream 和 BufferInputStream 的read()实现方法
**FileInputStream的read()方法的实现 ** :

   public int read() throws IOException {
        return read0();//read0是native 方法。
    }
     private native int read0() throws IOException;

BufferInputStream的read()方法的实现

protected volatile byte buf[];
 public synchronized int read(byte b[], int off, int len)
        throws IOException
    {
        getBufIfOpen(); // Check for closed stream
        if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        int n = 0;
        for (;;) {
            int nread = read1(b, off + n, len - n);
            if (nread <= 0)
                return (n == 0) ? nread : n;
            n += nread;
            if (n >= len)
                return n;
            // if not closed but no bytes available, return
            InputStream input = in;
            if (input != null && input.available() <= 0)
                return n;
        }
    }

总结: FileInputStream 根本就不支持读取两次, BufferedInputStream 支持 是因为读取 的输出放到了 buf[] 里面, 所以 它mark(0) , 就是 从buf[0] 读取。

转载:https://blog.csdn.net/fsdf8sad7/article/details/88707878

 

-----------------------------------------------------

今天在zuul上面获取返回值后,接口获取不到数据
主要代码如下:

RequestContext ctx = RequestContext.getCurrentContext();
InputStream stream = ctx.getResponseDataStream();
String body = StreamUtils.copyToString(stream, Charset.forName("UTF-8"));
//根据body做某些逻辑处理

RequestContext ctx = RequestContext.getCurrentContext();
InputStream stream = ctx.getResponseDataStream();
String body = StreamUtils.copyToString(stream, Charset.forName("UTF-8"));
//根据body做某些逻辑处理
 

 ctx.setResponseDataStream(new ByteArrayInputStream(body.getBytes()));

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值