版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/a6145055/article/details/53893404
java.io.file类用于宝石文件目录
IO流 是java做输入输出的基础 分为 输入流 输出流
字节流 字符流
java当中读文件或者写文件的时候可以 以字节为单位 也可以以字符为单位
1.字节流 对应读和写 有2个抽象的父类
1) InputStream 和 OutputStream
其中InputStream抽象类 抽象了应用程序读取数据的方式
OutputStream抽象类 抽象了应用程序写出数据的方式
2)文件结尾我们称之为EOF
EOF=End 读到-1就读到结尾
3)输入流 基本的方法 主要是用来读
键盘就是输入 他是用来读的
int b=in.read();读取一个字节无符号填充到int的低八位. -1是EOF
他也可以直接读到字节数组里面去 这个in就代表输入流的对象
read的方法 就是 你可以直接读到一个字节数组出来
in.read(byte[] buf) 读取数据直接填充到字节数组buf
把读到的东西直接填充到这个字节数组里面
int.read(byte[] buf,int start,int size) 读取数据到字节数组buf从buf的start位置开始存放size长
第start个位置开始放 放size个
4)输出流基本方法 主要是用来写的操作
他和上面输入都会去对应
out.write(int b) 写出一个byte到流,b的低8位
也可以直接写个
out.write(byte[] buf) 将buf字节数组都写入到流
out.write(byte[] buf,int start,int size) 字节数组buf从start位置开始写size长度的字节到流
输入数出流都有关闭的方式最终都要关闭
只要把↑几个方法弄清楚了那么剩下的操作就好做了
InputStream 和 OutputStream一般都会搭配使用
5)FileInputSteam 这样的子类 他继承InputStream抽象父类
FileInputSteam --->具体实现在文件上读取数据 所以他的构造方法也比较方便
第一步读文件 把一个文件作为一个字节流来进行读操作
下面写一个案例 新建class 写一个工具类
IOUtil
package com.imooc.io;
import java.io.FileInputStream;
import java.io.IOException;
public class IOUtil {
/**
* 方法1
* 读取指定文件内容,按照16进制输出到控制台
* 并且没输出10个byte换行
* 第一步读文件 把一个文件作为一个字节流来进行读操作
* 首先要构造FileInputStream的对象
* @param fileName
* @throws FileNotFoundException
*/
public static void printHex(String fileName) throws IOException{
//把文件作为字节流进行读操作
FileInputStream in=new FileInputStream(fileName); //所有io类都会有异常 所以要抛出回避一下
int b;//专门来读
int i=1; //用来计数每10个换一行
//循环 文件 他要不等于 -1因为等于-1就读到文件结尾了
while((b=in.read())!=-1){ //这样就读到一个字节了
if(b<=0xf){ //如果这个字节是一个单位数 如61 73 65 2e 72 65 70 6f a← 23 看箭头
//则在单位数前面补0
System.out.print("0"); //61 73 65 2e 72 65 70 6f 0a← 23 看箭头
}
System.out.print(Integer.toHexString(b)+" ");//然后以16进制的方式输出
if(i++%10==0){//如果i++ 求余10 等于0我们就换行 相当于每读10次换一行
System.out.println();
}
}
in.close();//读取完文件必须用到和这个关闭方法
//接下来对它进行一个测试 创建一个类IOUtilTest1
}
/**
* 方法2
* 把一个文件已字节的方式读出来之后 以6进制的方式打印到控制台
* 先抛出io异常
*/
public static void printHexByByteArray(String fileName) throws IOException{
//构造FileInputStream 对象in 参数 字符串 文件路径文件名
FileInputStream in=new FileInputStream(fileName);
//可以把这个字节数组空间开的足够大 1024就是1个字节 1k 乘以20就是20k 的空间
byte[] buf=new byte[20*1024];
//读取文件的数据
//从in中批量读取字节,放入到buf字节数组中 ,从第0个位置开始放,最多放buf.length个 就是20K个
//返回的是读到的字节的个数
//有这样一种情况第1他可能读不满 第2他可能不够放 因为数组定义的20k的空间
//返回的是读到的字节的个数 有可能这个字节数组足够大我并没有读满所以要返回读到的字节的个数
//还有一种情况可能字节数组都不够放 我现在要把字节数组打印出来
/*int bytes=in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大
int j=1;//用j来计数
for(int i=0;i
if(buf[i]<=0xf){//如果数组里面这个数据 小于等于十六进制的 15
System.out.print("0");//就要在前面补0 否则就会显示单位数
}
System.out.print(Integer.toHexString(buf[i])+" ");//输出16进制的 数据
if(j++%10==0){//如果计数j 求余10等于0 证明已经有十次了
System.out.println();//那么就换一行显示
}
}
in.close();//读取完文件必须用到和这个关闭方法
*/
/**
* 方法3
*/
int bytes=0;
int j=1;
while((bytes=in.read(buf,0,buf.length))!=-1){
for(int i=0;i
if(buf[i]<=0xf){//如果数组里面这个数据 小于等于十六进制的 15
System.out.print("0");//就要在前面补0 否则就会显示单位数
}
//byte类型为8位 int类型为32位 为了避免数据转换错误,通过& 0xff将高24位清零
System.out.print(Integer.toHexString(buf[i] & 0xff)+" ");
if(j++%10==0){
System.out.println();
}
}
}
//接下来对它进行一个测试 创建一个类IOUtilTest2
}
}
/*上面是将byte[]转化十六进制的字符串,注意这里buf[i] & 0xFF将一个byte和 0xFF进行了与运算,然后使用Integer.toHexString取得了十六进制字符串,可以看出
buf[i] & 0xFF运算后得出的仍然是个int,那么为何要和 0xFF进行与运算呢?直接 Integer.toHexString(buf[i]);,将byte强转为int不行吗?答案是不行的.
其原因在于:
1.byte的大小为8bits而int的大小为32bits
2.java的二进制采用的是补码形式
==================以下文字貌似有问题===================
在这里先温习下计算机基础理论
byte是一个字节保存的,有8个位,即8个0、1。
8位的第一个位是符号位,
也就是说0000 0001代表的是数字1
1000 0000代表的就是-1
所以正数最大位0111 1111,也就是数字127
负数最大为1111 1111,也就是数字-128
上面说的是二进制原码,但是在java中采用的是补码的形式,下面介绍下什么是补码
1、反码:
一个数如果是正,则它的反码与原码相同;
一个数如果是负,则符号位为1,其余各位是对原码取反;
2、补码:利用溢出,我们可以将减法变成加法
对于十进制数,从9得到5可用减法:
9-4=5 因为4+6=10,我们可以将6作为4的补数
改写为加法:
9+6=15(去掉高位1,也就是减10)得到5.
对于十六进制数,从c到5可用减法:
c-7=5 因为7+9=16 将9作为7的补数
改写为加法:
c+9=15(去掉高位1,也就是减16)得到5.
在计算机中,如果我们用1个字节表示一个数,一个字节有8位,超过8位就进1,在内存中情况为(100000000),进位1被丢弃。
⑴一个数为正,则它的原码、反码、补码相同
⑵一个数为负,刚符号位为1,其余各位是对原码取反,然后整个数加1
- 1的原码为 10000001
- 1的反码为 11111110
+ 1
- 1的补码为 11111111
0的原码为 00000000
0的反码为 11111111(正零和负零的反码相同)
+1
0的补码为 100000000(舍掉打头的1,正零和负零的补码相同)
Integer.toHexString的参数是int,如果不进行&0xff,那么当一个byte会转换成int时,由于int是32位,而byte只有8位这时会进行补位,
例如补码11111111的十进制数为-1转换为int时变为11111111111111111111111111111111好多1啊,呵呵!即0xffffffff但是这个数是不对的,这种补位就会造成误差。
和0xff相与后,高24比特就会被清0了,结果就对了。
----
Java中的一个byte,其范围是-128~127的,而Integer.toHexString的参数本来是int,如果不进行&0xff,那么当一个byte会转换成int时,对于负数,会做位扩展,举例来说,一个byte的-1(即0xff),会被转换成int的-1(即0xffffffff),那么转化出的结果就不是我们想要的了。
而0xff默认是整形,所以,一个byte跟0xff相与会先将那个byte转化成整形运算,这样,结果中的高的24个比特就总会被清0,于是结果总是我们想要的。
*/
测试类
package com.imooc.io;
import java.io.IOException;
public class IOUtilTest2 {
public static void main(String[] args) {
//调用IOUtil IO工具类的 把一个文件已字节的方式读出来之后 以6进制的方式打印到控制台方法
try {
IOUtil.printHexByByteArray("e:\\linux\\CentOS6-Base-163.repo");
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} //捕获异常
}
}