本文共 3918 字,大约阅读时间需要 13 分钟。
字节流://本文代码大多都是摘录自网络 自己敲怕有纰漏 还请见谅
先来理解一下字节流的含义 听名字 顾名思义 字节流是通过传输字节的流 操作单位是一个个的字节 优点很明显:因为是操作字节 所以任何文件都可以操作 比如图片 视频 音乐等 缺点也很明显:因为是一个一个操作 所以速度低下 不过我们可以创建个缓冲速度来提高效率 下面会提到 知识背景:一个字节byte=8个位bit 一个二进制就是一个位
比如一个 int 97 其实代表着a (ASCLL为前提) 而在计算机中是以二进制形式保存着 System.currentTimeMillis();了解一下 获取当前系统的时间 接下来会用来检测代码运行的时间来比较效率 Arrays.toString(buffer) 可以检查返回的值的内容 read返回byte 却用int存储 read返回的是无符号的int 文本中换行符号 read读取过来是空的
计算机存储的内容都是二进制 计算机的内存IC是用来存储数据的
如果你的计算机是64位 那么地址存储的大小也是64位即8字节 内存IC中一个引脚就是一个位(扯远了) 信息都保存再内存IC中File file = new File("c:\\a.txt"); // 创建字节输出流 FileOutputStream fos = new FileOutputStream(file); // 创建文件输入流 FileInputStream fis = new FileInputStream(file); 注意:1.每次对同一个文件进行FileOutputStream 操作的时候 都是会先清除原来的内容然后重新写入 除非加上true举例:FileOutputStream fos = new FileOutputStream(file,true);//意思就是像该文件追加内容
写入和读出由字节流的write和read来操作 先来谈一下写入:
write有两个输出格式
一个无参:fos.write(‘a’);//其实也可以传入97 也代表着’a’
一个有参 byte[] buf = new byte[1024]; fos.write(buf); 也可以 fos.write(“我是字符串”.getBytes);
无参的时候一次只能传输一个字节
有参的时候一次可以传输多个字节 注意: 1. 最后这个流要close()关闭掉如果一个应用程序打开了过多的流而没有关闭它们,那么系统资源将被耗尽. 2. 题外话:Scanner比较特别 只能关闭一次 因为它是常量流 3. 如果输入的是一个汉字的话就不可以无参而是要用有参因为字节流一次只能传输一个字节 而汉字是两个字节 无法传输会乱码 4. 传输汉字之类的不用字节流 下面会介绍字符流接下来是读出数据:
字节流的读入也是一个字节一个字节读入的
用的是reader方法 :一次读取一个字节,读到文件末尾返回-1. 也有两个方法 1. 第一个是无参的 返回的是得到的值// 打开流 FileInputStream fis = new FileInputStream(path); int len=0; while ((len = fis.read()) != -1) { System.out.print((char) len); } // 使用完关闭流 fis.close();
//找到目标文件 File file = new File(“D:\呵呵.png”); //建立数据的输入通道
FileInputStream fileInputStream = new FileInputStream(file); //建立缓冲数组配合循环读取文件的数据。 int length = 0; //保存每次读取到的字节个数。 byte[] buf = new byte[1024]; //存储读取到的数据 缓冲数组 的长度一般是1024的倍数,因为与计算机的处理单位。 理论上缓冲数组越大,效率越高 while((length = fileInputStream.read(buf))!=-1){ // read方法如果读取到了文件的末尾,那么会返回-1表示。 System.out.print(new String(buf,0,length)); } //关闭资源 fileInputStream.close();
**总结: 东西有点多 请耐心看完 总结了基本全部的字节流细节
1. 流最后都要关闭 关闭顺序最好是从下往上开始 2. 字节流是用来读取类似图片之类的 纯二进制 而不是文件之类的(有中文 会有乱码问题存在) 3. 字节流reader的时候一般都是自己创建一个缓冲流 使用write(byte[] b),或者write(“字符串”.getBytes())就是使用缓冲.提高效率. 然后接受数据 这个效率要比接下来讲的缓冲流效率要高 (具体的 缓冲流等下了解) 4. 字节流传输单位是一个字节 字母是一个字符 而中文是两个字节 5. 返回的其实是int类型 要显示字符就需要char或者String强转 6. windows的换车和换行是”\r\n” 对应码表是13和10 但是如果读入的话输出结果是空 原因我也不知道为什么 7. 使用FileOutputStream 的时候,如果目标文件不存在,那么会自动创建目标文件对象。 8. 使用FileOutputStream写数据的时候,如果目标文件已经存在,那么会先清空目标文件中的数据,然后再写入数据。 9. 使用FileOutputStream写数据的时候, 如果目标文件已经存在,需要在原来数据基础上追加数据的时候应该使用new FileOutputStream(file,true)构造函数,第二参数为true。 10. while((len=fileInputStream.read(buffer))!=-1)中buffer是覆盖的 而不是清空 11. 使用FileOutputStream的write方法写数据的时候,虽然接收的是int类型参数,但是write的常规协定是:向输出流写入一个字节。要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。 输入 97代表a 49代表1 int代表4个字节 char字母代表1个字节 如:00000000-000000000-00000001-11111111 511 结果只是输出11111111**根据第11条可以牵扯出来点东西 那就是二进制的补码问题
负数的二进制显示方式 最高位为1
正数的二进制显示方式 最高位为0 负数的二进制怎么求? 负数的绝对值转换成正数 该正数的二进制取反 然后+1就是负数的二进制值
在本文中的当我们读入11111111的时候 其实read返回的是无符号的int类型 按照权值来 而不是补码 所以他的值是255 而不是所谓的-1 write(-1)答案也是255
为什么InputStream.read()读取一个byte确返回一个int呢?
java 字节读取流的read方法一次读一个byte但返回int的原因读取二进制数据按字节读取,每次读一个字节(byte)。
read()的底层是由C++实现的,返回的是unsigned byte,取值范围为[0~255],
在java中没有对应的类型,所以只能用int类型接收,由Java接收得到的就是int[0、255]。举一个经典的例子:
图片拷贝:
/*
需求: 拷贝一张图片。 */ public class CopyImage {public static void main(String[] args) throws IOException { //找到目标文件 File inFile = new File("F:\\美女\\1.jpg"); File destFile = new File("E:\\1.jpg"); //建立数据的输入输出通道 FileInputStream fileInputStream = new FileInputStream(inFile); FileOutputStream fileOutputStream = new FileOutputStream(destFile); //追加数据.... //每新创建一个FileOutputStream的时候,默认情况下FileOutputStream 的指针是指向了文件的开始的位置。 每写出一次,指向都会出现相应移动。 //建立缓冲数据,边读边写 byte[] buf = new byte[1024]; int length = 0 ; while((length = fileInputStream.read(buf))!=-1){ //最后一次只剩下了824个字节 fileOutputStream.write(buf,0,length); //写出很多次数据,所以就必须要追加。 } //关闭资源 原则: 先开后关,后开先关。 fileOutputStream.close(); fileInputStream.close();}
}
转载地址:http://qgxsa.baihongyu.com/