以前老师讲C++中的I/O机制时,听得似懂非懂,对什么字节流仅有一些浅显的认识。听胡哥讲了java中的I/0机制后,才对这些概念有了进一步的深入。
首先,先介绍一些基本概念吧:
字节(Byte)是计算机信息技术用于计量存储容量和传输容量的一种计量单位,1个字节等于8位二进制(8bit)
在ASCII码中,一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。
注意:MiB和MB,KiB和KB等的区别:
1KiB(kilobyte)=1024byte
1KB(kibibyte)=1000byte
1MiB(megabyte)=1048576byte
1MB(mebibyte)=1000000byte
基本数据类型与bit的关系如下表所示:
基本数据类型
占用空间
boolean
1bit
char
16bit /2 byte
byte
8bit
short
16bit/2byte
int
32bit/4byte
long
64bit /8byte
float
32bit/4byte
加入在记事本中写入数字123后,它的大小是3字节,而它所占的空间大小是4KB,为什么会是这样的结果呢???我觉得这应该和计算机内部的存储机制有关,具体为什么,等我查完相关的资料后,再来解答这个问题,言归正传,说说我们的I/0机制吧。
I/0机制正如平常所见的水龙头中的水流出来一样,有流出的水,亦有流进的水。水正如数据,水龙头就如数据所在的文件。java中的数据流按方向分为输入流和输出流。输入流是以InputStream抽象类为继承类的各个子类,输出流是以OutputStream抽象类为继承类的各个子类。InputStream是基于字节读取的输入流,InpuStream类中主要定义了以下几个方法:
1.int available():返回流中可读取的有效字节 长度;
2、int read():返回流中的下一个字节作为一部byte指,注意此方法返回虽为int型,实际上是从流中读取的一个byte值,即8bit;
3、int read(byte[]b)用于流中读到的byte数组
如果要从文件中读取数据,那么就要用到FileStream类了
具体的用法如下代码:
public void ReadFile()
{
String FileName="c:\\deci.txt";
try {
InputStream Ins=new FileInputStream(FileName);
try {
int byteCount=Ins.available(); // 获得输入文件的字节数
byte [] stringByte=new byte[byteCount]; //新建字节数组
Ins.read(stringByte); //读入数组
String readstr=new String(stringByte); //将字节数组转换为字符串
System.out.println(readstr); //输出读入文件的内容
Ins.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
上面的例子仅仅使用于读取字节,加入我们要读入字符串,int,double,float这些数据对象呢,总不能又一个一个字节的读吧,这时我们就要用到另外一个输入类DataInputStream,具体用法如下:
//读文件
public void ReadFile()
{
try{
//用DataInputStream类
InputStream is=new FileInputStream("testComputer.txt");
DataInputStream ios=new DataInputStream(is);
//字符串读取时,先读取存储的长度,再读取其内容
byte Scount=ios.readByte(); //先读取其长度
System.out.println(Scount);
byte [] rts=new byte[Scount]; //读取内容
ios.read(rts);
String aa=new String(rts);
System.out.println(aa);
byte sscount= ios.readByte(); //与上面类似
byte[]rsp=new byte[sscount];
ios.read(rsp);
String bb=new String(rsp);
System.out.println(bb);
byte a=ios.readByte(); //读取存储的byte
System.out.println(a);
int count=ios.readInt(); //读取存储的int
System.out.println(count);
double sell=ios.readDouble(); //读取存储的double
System.out.println(sell);
ios.close();
} catch(Exception e)
{
e.printStackTrace();
}
}
介绍完了输入流之后,接下来介绍我们的输出流OutputStream,OutputSteam主要定义了以下几个方法:
1、void close():关闭流,与输入流类似;
2、void flush():强制输出到目标中
3、void write(byte[]b):将byte数组中的内容输出到流中:
具体用法如下:
public void WriteFile(String str)
{
String FileName="WriteFile.txt"; //文件路径为当前文件的库文件
try {
OutputStream os=new FileOutputStream(FileName);
byte[] WriteByte=str.getBytes();
try {
os.write(WriteByte);
os.flush(); //强制写出
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
类似的道理:如果要将int,double等数据写进文件,就需要用到DataOutputStream类了,具体用法如下:
//写入文件操作
public void testWrite(Computer cp)
{
try{
//先写入文件
OutputStream os=new FileOutputStream("testComputer.txt");
DataOutputStream dos=new DataOutputStream(os);
//对于字符串而言,先存储其长度,再存储字节数组
int len=cp.type.length();
byte [] ts=cp.type.getBytes(); //存储字符串时,可有意识地对字符串进行一系列操作,对数据加密,但注意读取时,要先消去相应的操作
dos.writeByte(len);
dos.write(ts);
//对于字符串而言,先存储其长度,再存储字节数组
int lens=cp.ProduceDate.length();
byte[] sp=cp.ProduceDate.getBytes();
dos.writeByte(lens);
dos.write(sp);
//存入其他类型的变量
dos.writeByte(cp.ProduceCount); //写入byte
dos.writeInt(cp.SellCount); //写入int //注意查看源代码自己写相应函数
dos.writeDouble(cp.YunXing); //写入double
//刷新,关闭
dos.flush();
dos.close();
} catch(Exception e)
{
e.printStackTrace();
}
}