读取流的内容,首个字符不见了?数据不完整?解决

前言:

这几天大神开始教我弄安全方面的东西了,主要是数据防篡改的。今天就遇到一个很怪异的事,页面的数据流传过来,我接收到之后首个字符缺失了。123拿到却是23。记录一下今天的收获,算是收获很多的一天。

找原因:

  1. 很快就能定位到是接收流的时候出问题了,因为在ajax拦截器中,我打印了参数的值,F12查看请求也是没问题的。
  2. 百度,面向百度编程~。还真找到了博客,上面说的是BufferReader.read()方法会”吞“调一个字符,即循环取数据的时候:
int a = 0;
while((a = bufferReader.read()) != -1)

这样就会吃调掉最前面的一个字符。

  1. 博客上说用readLine()就能解决,经过多次修改测试,失败!
  2. 我就找来大神一起商量,大神也觉得很奇怪,开始怀疑是不是JDK1.6的缺陷(超级老项目~~)
  3. 忙活一阵之后,我发现我的代码是先判断数据是不是以流的方式传进来的,然后再用上面的代码取值,于是我是这样判定的:
if(inputStream.read() != -1){
    
    }
如果能读到,说明是流;

看到这句代码,我恍然大悟:应该是这句出了问题

6.找到问题点,就开始修改测试,果然是它的问题

结论:

没了的原因其实是,read方法没指定一次读多少就是一个一个字符读的,我们如果不把while或者if中的read读的值取出来,加到字符串上去,就会造成少一个字符,如果是readLine就会少一行。因为read方法返回的是int没法加到字符串上去,所以使用readLine它返回一行数据(字符串),只要处理在while中或if中的那一次读取,就能保证数据不会缺。所以使用read的时候应该指定一次读多少字节(byte数组),并将这个byte数组加到字符串上去:

byte b[] = new byte[512];
String content = null;
//read
if((len = bufferReader.read(b))!=-1){
    
    
	stringBuilder.append(b,0,len)  //StringBuilder的append方法不知道的可以去了解下,或者评论私信问我
//readLine
if((content = bufferReader.readLine())!=-1){
    
    
	stringBuilder.append(content)
}

这样就能保证数据不会丢失了
别像我那样,不然第一个字符就没了

下面是我做的一个实验:输入字符12345

package com.xp.test;

import java.io.*;

public class Read {
    
    
    public static void main(String[] args) {
    
    
        //初始化输入流
        InputStream inputStream = null;
        //初始化缓冲区
        BufferedReader bufferedReader = null;
        //使用StringBuilder来拼接原数据
        StringBuilder builder = new StringBuilder();
        //每次读取的内容
        String content = null;

        try {
    
    
            //将字符串12345转为输入流
            inputStream=new ByteArrayInputStream("12345".getBytes());
            //指定输入流到缓冲区
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            
            if((inputStream.read())!=-1){
    
    
                //行读取数据
                while((content = bufferedReader.readLine())!=null){
    
    
                    builder.append(content);
                }
                //输出结果
                System.out.println(builder.toString());
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
                if(bufferedReader==null){
    
    
                    bufferedReader.close();
                }
                inputStream.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
    }

}

结果:
在这里插入图片描述

额外收获:会有用的,收好

请求的contentType:

  1. application/json : 这是json数据,使用request payload(而且这玩意也是用流传的)的方式也是采用的这种
  2. application/x-www-form-urlencoded : 这是表单(form data)的默认格式
  3. multipart/form-data : 传文件(是流)的方式

如有错误或不足,欢迎指正,一起交流学习!

猜你喜欢

转载自blog.csdn.net/qq_42682745/article/details/120336767