字节流操作:InputStream类 读取文件的操作(三种 read 方法)

article/2025/8/12 0:51:59

字节流操作:InputStream类 和 OutputStream类

文章目录

  • 字节流操作:InputStream类 和 OutputStream类
  • 观前提醒:
  • InputStream类 读取文件的操作(三种 read 方法)
    • 1. 不带参数的 read( )方法,返回值是:int 类型
      • 例子1(以英文字符为例):
      • 例子2(以中文字符为例):
      • 总结:
    • 2. 带 byte[ ] 参数的 read( )方法,返回值是:int
      • 此方法的注意事项:
      • 输出型参数:
      • 带 byte[ ] 参数的 read( )方法的读取演示:
    • 3. 带 三个参数的 read( )方法,返回值是:int
      • 演示:
    • 4. 读取文件的操作(三种 read方法)的简单总结
  • 总结:

观前提醒:

这篇博客是从 Java 文件操作 和 IO(3)-- Java文件内容操作(1)-- 字节流操作 这篇博客分离出来的,目的是减少博客字数。

如果你是第一次点击进来的,需要你将上面这个博客,阅读到这篇博客的连接,再点击进来看这篇文章。

InputStream类 读取文件的操作(三种 read 方法)

读取文件的最核心方法,就是:read方法

对于 InputStream类 ,Java提供了三种 read方法:

1. 不带参数的 read( )方法,返回值是:int 类型

在这里插入图片描述

这个方法的作用是:调用一次,读取一个字节

关于返回值的解释:返回的是int,不是 byte,当返回值为 -1 时,表示文件已经读取完毕

例子1(以英文字符为例):

现在在我本人的java项目路径当中,存在 test.txt 文件,文件当中,写的是 hello ,现在我使用循环,使用字节读取的方式,将里面的内容读取出来:
在这里插入图片描述
演示代码:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;public class demo1 {public static void main(String[] args) throws IOException {try(InputStream inputStream = new FileInputStream("./test.txt")) {// 读取文件操作:while (true) {int data = inputStream.read();// 返回 -1 ,说明文件内容已经读取完毕if (data == -1) {break;}System.out.println(data);}}}
}

运行结果演示:
在这里插入图片描述
相信你读到这样的结果,肯定会有疑惑:不是哥们,我文件里明明写的是 hello 啊,怎么给我输出的是 104,101… …这样的数字呢?

原因的话,就是说:我们这里是按照 字节的方式进行读取的,同时根据程序代码,是一个一个字节读取出来,分别进行打印的,而每个字节的范围,是:0 ~ 255。

hello 是由五个英文字母构成的一个英文字母在计算机中的存储大小为1个字节(byte)。所以,每个英文字母有对应的一个字节码,所以显示出来的就是五个字节码(数字)

而 hello 是纯英文的方式,是根据 ASCII码 进行编码的。我们可以查一下 ASCII码表,看看 h 在其中的表示:
在这里插入图片描述
至于其他的,你可以自己去 百度 搜查 ASCII码表,然后对照一下,运行结果中的那5个十进制数字,就正好是 hello 的对应的 ASCII码

特别提醒一下:
10 进制是正常的
8 进制是 0 开头的
16 进制是 0x 开头的

例子2(以中文字符为例):

现在在我本人的java项目路径当中,存在 test.txt 文件,文件当中,写的是 “你好” ,现在我使用循环,使用字节读取的方式,将里面的内容读取出来:
在这里插入图片描述
演示代码,还是例子1 的那个代码:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;public class demo1 {public static void main(String[] args) throws IOException {try(InputStream inputStream = new FileInputStream("./test.txt")) {// 读取文件操作:while (true) {int data = inputStream.read();// 返回 -1 ,说明文件内容已经读取完毕if (data == -1) {break;}System.out.println(data);}}}
}

运行结果:
在这里插入图片描述
这里显示的有 6 个字节,而我的文件里面写的只有 2 个汉字,所以,可以知道, 1 个汉字占 3 个字节
一个汉字占三个字节,是属于 utf-8 的编码集
我们可以看看 utf-8 的码表,去对比一下。

通过这个网站:查看字符码表 UTF-8,可以查看到 utf-8 码表中,对应汉字的字节码构成。

在码表,输入 你好 ,进行查询,结果:
在这里插入图片描述
三个字节是放到一起的,不是分开的显示,不是像我们程序当中,是分开显示的,所以,不好观察。我们可以使用 16 进制,进行打印,然后对比
十六进制,一个十六进制数字,表示 4 个 bit(比特位),两个十六进制的数字,表示 8 个bit(比特位),就是 1 个字节

那么,问题来了:Java里面,怎么打印 十六进制?
答:使用 C语言当中的 printf( )%x 或者 %X 表示的是十六进制的占位符。这两个占位符,也是有区别的。
%x小写的字母 x,表示输出出来的十六进制数中,英文字符,全部都以小写形式出现
%X大写的字母 X,表示输出出来的十六进制数中,英文字符,全部都以大写形式出现

为了与网站上查到的字符的十六进制相等,我们下面就是用 %X 来进行演示结果:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;public class demo1 {public static void main(String[] args) throws IOException {try(InputStream inputStream = new FileInputStream("./test.txt")) {// 读取文件操作:while (true) {int data = inputStream.read();// 返回 -1 ,说明文件内容已经读取完毕if (data == -1) {break;}// 以十六进制的方式,打印读取到的字节数// \n 表示的是换行符// %x 表示的是十六进制的占位符System.out.printf("%X\n",data);}}}
}

运行结果:
在这里插入图片描述
与网站上查到的十六进制编码进行比较:
在这里插入图片描述
通过对比发现,代码输出的结果的六个十六进制数字,和网上 UTF-8 编码表中,你好两个汉字所对应的十六进制数字,是一样的!!!

总结:

  1. 读取英文字符的时候,按照一个一个字节读出来的,打印的结果,是 英文字符所代表的 ASCII码
  2. 读取中文字符的时候,按照字节读取,结果以十六进制的形式表示,可以证明,是 UTF-8 字符集 中所表示的汉字

2. 带 byte[ ] 参数的 read( )方法,返回值是:int

在这里插入图片描述
这个方法的作用:调用一次,读取若干个字节读取到的数据放到定义的 字节数组 当中。

此方法的注意事项:

  1. 首先,此 read( ) 方法,带有 byte[ ] b 参数,使用之前,我们需要先定义一个这样的字节数组对象。
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class demo2 {public static void main(String[] args) throws IOException {try(InputStream inputStream = new FileInputStream("./test.txt")) {while (true) {//读取文件操作//一次读取多个字节,字节数组的长度,自行定义byte[] bytes = new byte[1024];
//            这个代码里面,有两个返回值,一个是 n,一个是 bytes数组(输出型参数)int n = inputStream.read(bytes);}}}
}

定义的这个字节数组的长度,根据自己的需要来进行自定义就可以了。

进行读操作的时候,会尽可能的把这个字节数组(字节数组的长度需要自定义)给填满,填不满的话,能填几个就是几个!

  1. 返回值,是 int 类型的数据

当返回值为 -1 时,表示文件已经读取完毕

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class demo2 {public static void main(String[] args) throws IOException {try(InputStream inputStream = new FileInputStream("./test.txt")) {while (true) {//读取文件操作//一次读取多个字节,字节数组的长度,自行定义byte[] bytes = new byte[1024];
//            这个代码里面,有两个返回值,一个是 n,一个是 bytes数组(输出型参数)int n = inputStream.read(bytes);}}}
}

以这一句代码为例子,此处的 n 表示实际 read()方法 读取到的字节数,比如,读取了 6 个字节,n 的结果就是 6

  1. 这个read( )方法,使用 参数 作为方法的返回值,有两个返回值

第一个返回值:第二点讲到的 n (int类型的返回值)
第二个返回值:括号里面的参数,读取到的字节数据,会放到read( )方法括号里的字节数组引用指向的字节数组。

输出型参数:

这种写法,叫做“ 输出型参数 ” ,在 Java 当中,并不是很常见,在 C++ 中比较常见
什么意思呢?

不知道你们对于 Java 当中的方法(也就是 C语言 中的函数)是怎么理解的?
一般来说,我们可以把 函数/方法 想象成一座工厂参数就是原材料返回值就是产品。
在这里插入图片描述
可以根据上面这个图,对方法(也可以称为 函数)进行理解。

函数的参数,是原材料,函数的返回值,是输出的产品。
对于输出型参数来说:有的时候,我们也会使用参数来接收返回值。

在java中,如果参数是引用类型(数组,String,自定义类等),方法内部修改对象内容,能够影响到方法的外部。

在 C语言 当中,最典型的例子就是:交换两个变量的值。
如果你直接传入的是数值,形参是实参的拷贝,直接交换,就只会在方法内部生效,方法外没有影响。故而有了指针,可以传入该变量的指针,交换变量的指针所指向的值,就可以在方法外部也生效,真正实现了两个变量的值。

在Java中,没有指针了,但是有引用的概念,对于引用类型,有这么个语法特点:方法内部的修改,可以影响到方法外部 你所指向的对象。
正是由于这样的语法特点,使得引用类型的参数,可以作为输出型参数

以上,你能理解多少就理解多少,上面所述,只是扩展,哪怕你理解不了,你只需要记住:
第一个返回值:n,记录的是 read( ) 方法,这一次的读取,读到了多少个字节
第二个返回值:bytes,是数组的引用,既是参数,也是方法执行结束后,存放了读取数据的字节数组的引用。

再举一个例子:这个过程有点像 食堂打饭!!
食堂打饭,就是你拿个空的餐盘,来到窗口,你把空的餐盘递给打饭阿姨,让阿姨给你打饭,打完饭以后,餐盘给你,餐盘里面,还有饭菜。

//读取文件操作
byte[] bytes = new byte[1024];
//这个代码里面,有两个返回值,一个是 n,一个是 bytes数组(输出型参数)
int n = inputStream.read(bytes);

就拿这两句代码来进行举例:

byte[] bytes = new byte[1024];

bytes就相当于一个空餐盘

int n = inputStream.read(bytes);

inputStream.read()相当于阿姨给你打饭,你把空餐盘bytes,递给阿姨inputStream.read(bytes),打完饭后,阿姨给你的是盛满了饭菜的餐盘bytesn表示的就是你餐盘饭菜的量。

在这里插入图片描述
输出型参数的出现,本质上来说,还是语法上有限制。
Java,C++ 中,硬性要求:一个方法,只能有一个返回值,如果希望返回多个数据
(上述read()方法,就是希望同时返回,长度 和 内容数组),就只能通过引用类型的参数来凑了。

但是,同样的问题,在 Python 和 Go语言 上,就没有这样的限制了,他们都支持,一个方法,返回多个值。

带 byte[ ] 参数的 read( )方法的读取演示:

仍然是以 test.txt 文件,文件当中的 “你好” ,来进行读取打印:

具体思路:带 byte[ ] 参数的 read( )方法,可以一次读取多个字节,所以,每读一次,就需要循环遍历 bytes 数组一次,格式化输出里面的字节System.out.printf("%X\n",data),直至读取到的字节数 n 为 -1,表示文件数据已经读完,跳出 while()循环,结束读取文件操作。
这里有一个注意的点,遍历读取 bytes 数组内容的时候,不是使用 bytes.length去当作循环条件,而是使用 n,因为 n 才是真正反映此次读取到的有效字节数

演示代码:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class demo2 {public static void main(String[] args) throws IOException {try(InputStream inputStream = new FileInputStream("./test.txt")) {while (true) {//读取文件操作byte[] bytes = new byte[1024];
//            这个代码里面,有两个返回值,一个是 n,一个是 bytes数组(输出型参数)int n = inputStream.read(bytes);
//            判断文件是否已经读取完毕if (n == -1) {break;}for (int i = 0; i <n; i++) {System.out.printf("%X\n",bytes[i]);}}}}
}

运行结果:
在这里插入图片描述
这里显示的就是 你好,所对应的 UTF-8 编码中,对应的十六进制数。

我们之前说,这个read()方法,会尽可能的去读取文件中的数据,放到你所定义的空白字节数组里面,读取到的字节数据的大小,取决于你空白字节数组的大小,现在,我们上面代码所定义的空白字节数组 bytes 的大小,由 1024 改为 3 ,同时,输出字节的时候,我们加个分隔符,以便进行区分。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class demo2 {public static void main(String[] args) throws IOException {try(InputStream inputStream = new FileInputStream("./test.txt")) {while (true) {//读取文件操作byte[] bytes = new byte[3];
//            这个代码里面,有两个返回值,一个是 n,一个是 bytes数组(输出型参数)int n = inputStream.read(bytes);
//            判断文件是否已经读取完毕if (n == -1) {break;}for (int i = 0; i <n; i++) {System.out.printf("%X\n",bytes[i]);}System.out.println("======================");}}}
}

运行结果:
在这里插入图片描述
所以,这个 read()方法一次能读取到多少个字节,跟你自己定义的空白字节数组的大小是有关系的。

3. 带 三个参数的 read( )方法,返回值是:int

在这里插入图片描述

对这三个参数进行解释:

byte[ ] b :就是你定义的空白字节数组,调用 read()方法,后,读取到的字节,存放到这个数组里面。

int off :off --> offset 表示的是 偏移量(数组下标),本次读取到的字节数据,从空白字节数组的 off下标 开始存放,限制存放的起始位置

int len :表示你本次读取,想读取多少个字节往空白字节数组 b 中的哪个起始位置 off开始存放,限制了你本次可以读取到的字节len 往往会和返回值的大小(本次读取到了多少个字节)是一样的。

所以这个read()方法的作用就是:想读取多少(len)个字节往空白字节数组 b 中的哪个起始位置 off下标 开始存放

这个方法的使用场景通常是:你有一个非常大的字节数组,每次读操作,都把数据放到数组的某个部分,就会使用到这个 带有三个参数的 read()方法

演示:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class demo3 {public static void main(String[] args) throws IOException {
//使用 try with resource 的语法,打开文件,并程序结束的时候,自动执行 close()方法try(InputStream inputStream = new FileInputStream("./test.txt")) {while (true) {
//              操作文件
//              定义空白字节数组byte[] bytes = new byte[1024];//                读取文件int n = inputStream.read(bytes,0,3);
//                查看你本次读取到了多少个字节System.out.println("n = " + n);
//                判断是否已经读取结束if (n == -1) {break;}
//                输出读取后,存放到字节数组中的内容for (int i = 0; i < n; i++) {System.out.printf("%X\n",bytes[i]);}System.out.println("===================");}}}
}

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

代码的解释:
首先,我们还是先定义一个空白字节数组,大小为 1024个字节。

然后读取文件,使用带有三个参数的 read(bytes,0,3)方法,表示:把读取到的字节,存放到空白字节数组里面去,从字节数组的 0 下标,开始存放,同时 len 为 3,也就是,限制每一个读取的字节的数量为 3,哪怕你空白字节数组一次性能装下 1024 个字节,len 的大小,和 返回值 n 的大小是一样的,都是 3,从输出结果可以看出。

最后,当 n 等于 -1 时,表示文件已经读取完毕,结束while循环,整个java程序结束。

4. 读取文件的操作(三种 read方法)的简单总结

其实,文件内容操作,就那么几个步骤打开文件操作文件中的内容(读或者写),关闭文件

在实际开发过程当中,这三种read方法需要根据具体的情况来进行使用。

总结:

这篇博客,主要是讲解 使用字节流操作:InputStream类 读取文件的操作(三种 read 方法)。

看完这篇博客,请点击这个链接:Java 文件操作 和 IO(3)-- Java文件内容操作(1)-- 字节流操作

继续学习 OutputStream类 写数据的操作(三种 write 方法)。

最后,如果这篇博客能帮到你的,请你点点赞,有写错了,写的不好的,欢迎评论指出,谢谢!


http://www.hkcw.cn/article/PwgYvsuaAJ.shtml

相关文章

day13 leetcode-hot100-22(链表1)

160. 相交链表 - 力扣&#xff08;LeetCode&#xff09; 1.哈希集合HashSet 思路 &#xff08;1&#xff09;将A链的所有数据存储到HashSet中。 &#xff08;2&#xff09;遍历B链&#xff0c;找到是否在A中存在。 具体代码 /*** Definition for singly-linked list.* pu…

《在人间》葛铮:以无言演绎孤独,肢体语言传递情绪

如何塑造一个全剧中几乎没有台词的角色?葛铮认为关键在于认真体验角色的内心,由心而发地去感受,在镜头前自然地表现。5月28日,他出演的高概念意象情感剧《在人间》播出,他在剧中饰演铁林一角,多数镜头中只能用肢体语言、面部表情等方式传递角色的情绪,这对葛铮来说无疑是…

【docker部署】 Windows版docker部署harbor镜像

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ Windows版docker部署harbor镜像 Windows版dock…

TopCode之手撕快排

题目链接 912. 排序数组 - 力扣&#xff08;LeetCode&#xff09; 题目解析 算法原理 使用数组分三块的思想 i用来遍历整个数组 left用来标记<key的边界 right用来标记>key的边界 然后i进行遍历,数组就分成了四块 [l,left]<key [left1,i-1]key [i,right-1]未…

vue2使用node版本启动差异

node 14.21.3启动 无需添加去除ssl的环境变量&#xff0c;npm run dev即可 node 20.12.2 版本需要添加 SET NODE_OPTIONS–openssl-legacy-provider && "dev": "SET NODE_OPTIONS--openssl-legacy-provider && vue-cli-service serve"其…

母亲多种工具打孩子10多次被立案 强制报告制度显效

近日,司法部发布了一起未成年人法律援助典型案例。江苏省某小学老师发现学生胡某某身上有多处新旧伤痕,询问后得知胡某某因不愿意上学等问题被母亲多次殴打。老师随即按照强制报告制度要求向检察机关报告。经鉴定,胡某某挫伤面积达体表面积8%,已构成轻伤一级。随后,其母亲…

多家银行5年期定存利率跌破1.3% “存5年不如存1年”现象频现

离新一轮存款降息仅过去10天,部分中小银行存款利率开始出现剧烈调整。5月30日,多家农商行、村镇银行集体宣布下调定期存款利率。五年期整存整取利率最低降至1.20%,已低于六家国有大行、招商银行等大行1.30%的存款挂牌利率水平。“存5年不如存1年”这样的现象在中小银行中并不…

塞尔维亚一军工厂突发爆炸致7人受伤 工人制作炸药时意外引爆

当地时间30日早上7时40分,塞尔维亚军工企业“克鲁希克”位于瓦列沃市的工厂发生爆炸事故,导致7名工人受伤送医。伤者均为轻伤,已出院居家休养。事故发生在工人制作军用炸药过程中,压机上的引信被意外激活引发爆炸。有1名工人头部受伤,4人出现耳鸣症状。爆炸发生后厂区秩序…

专家解读印度“阵风”折翼背后较量 体系战斗力的较量

印巴冲突中,双方出动了大批战机进行猛烈交火。过去,印巴冲突多为地面战斗,而此次出现了大规模空中作战。这不仅是双方作战平台性能的直接较量,更是两国空战体系的深层碰撞。5月7日,印度武装部队发起代号为“朱砂”的行动,打击巴基斯坦和巴控克什米尔地区的设施。随后,巴…

长沙有花店将艾草花束卖到98元 节日氛围推高需求

端午节除了吃粽子,中国人还有在门口挂艾草的习俗。为了了解长沙市场上艾草的供应情况和价格,记者进行了走访。主打节日氛围的艾草出现在了超市和花店,经过商家精心搭配后成为一束束艾草花束。在河西的一家盒马超市内,摆放着多款艾草花束,价格从19.9元到39.9元不等。盒马相…

买到演唱会铁窗视角票被退款 视野不良引争议

近日,网友小鱼在京观看某明星演唱会时遭遇了视野被遮挡的问题。她表示,自己花费1960元购买了两张票,但到达现场后发现看台边缘的护栏遮住了大半个舞台,导致视线受阻。小鱼立即向工作人员反映情况并要求换座,但被告知没有空位。随后,小鱼录下了座位视角的视频,并找到多名…

王毅会见瑞士联邦委员兼外长卡西斯 共促国际调解院发展

2025年5月30日下午,中共中央政治局委员、外交部长王毅在香港会见了出席国际调解院公约签署仪式的瑞士联邦委员兼外长卡西斯。王毅表示,卡西斯专程来港参加此次活动,体现了瑞士对建立国际调解院的支持以及在多边主义和对话协商化解分歧方面的积极态度。中方赞赏瑞士在国际事务…

顺丰回应5万元手镯仅赔67元 未保价引发争议

5月30日,话题“顺丰寄丢价值5万元手镯仅赔67元”引发热议,登上微博热搜。近日广东佛山陈小姐网购了一只价值4.98万元的翡翠手镯,收到货后不太满意,选择了退货退款。因为商家赠送了运费险,5月22日10点由指定的顺丰速运上门取件。23日晚,陈小姐接到快递员电话,称快件丢失了…

长沙有花店将艾草花束卖98元 节日氛围带动热销

端午节期间,除了吃粽子,中国人还有在门口挂艾草的习俗。5月29日,对长沙市场进行了走访。主打节日氛围的艾草出现在了超市、花店,商家将其精心搭配成一束束艾草花束。河西的一盒马超市内,角落摆放着多款艾草花束,价格从19.9元到39.9元不等。盒马相关人士表示,艾草花束这周…

腾讯高管辟谣微信已读及访客功能 反复翻炒流量引质疑

腾讯高管辟谣微信已读及访客功能 反复翻炒流量引质疑!腾讯公关总监张军针对“微信如果推出朋友圈访客”和“如果微信推出已读功能”两个热门话题进行了辟谣。他表示,不明白为何总有人反反复复地创造“如果”,前两天所谓的朋友圈访客功能也是缘起于此。他甚至怀疑,有人在特意…

男子在商场猥亵女店员 店长飞身锁喉一招制服 正义店长挺身而出

男子在商场猥亵女店员店长飞身锁喉一招制服!在湖北襄阳的一家烧烤店,一名女店员正在门口发传单迎接客人时,一名戴着头盔的黑衣男子停下脚步,突然伸出“咸猪手”摸向她的腰。女子质问对方为何碰她,却反被殴打。监控视频显示,女子推开男子并质问他,但对方不仅没有道歉,反…

中国学生在哈佛毕业典礼发表演讲 传递多元包容理念

中国学生在哈佛毕业典礼发表演讲 传递多元包容理念!5月29日,哈佛大学举行毕业典礼,来自中国青岛的江玉蓉作为毕业生代表之一发表演讲。江玉蓉成长于普通家庭,通过自身努力和天赋获得了威尔士卡迪夫一所高中的全额奖学金,并在杜克大学完成本科教育后进入哈佛大学肯尼迪学院…

博主解读福建舰核心数据,福建舰第八次海试传来硬货!

博主解读福建舰核心数据。5月24日,央视新闻正式官宣:福建舰第八次海试传来硬货!电磁弹射系统直接让美军福特号成了"反面教材"。咱用的中压直流技术有多狠?美军福特号磨了7年还在修弹射故障,福建舰测试效率直接快3倍,故障率还不到他们的1/5。甲板上歼-15T挂着实…

日本店铺整理玩具枪射出真子弹!

日本店铺整理玩具枪射出真子弹。日本店铺回收顾客旧“玩具枪” 店员整理时射出一发真子弹。日本朝日电视台5月29日报道,近日,松山市一家回收店铺发生惊险一幕。店员在收拾一箱旧“玩具枪”时,突然射出一发子弹,打穿店内隔板。店员发现弹夹和子弹都是真的,立刻报警。店员…

青海13岁少年放学后失踪已51天

4月9日,青海省海东市民和回族土族自治县13周岁的冶某鹏,在放学回家途中走失,至今已51天。孩子父亲着急万分,通过网络社交媒体求助寻找。5月29日,冶某鹏的父亲告诉记者,孩子是民和县四中学生,身高167厘米左右。当时身穿蓝色校服黑色裤子黑白色板鞋,没有带手机、身份证和…