输出流只能使用一次, 比如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()));