java 字节输入流_JavaIO流(一)-字节输入流与字符输入流

IO流详解

一、输入流

字节输入流

FileInputSteam

1、构造方法:public FileInputStream(File file) {}

public FileInputStream(FileDescriptor fdObj){}

public FileInputStream(String name){}

2、read方法:// 每次读取一个字节

public int read(){}

// 读取b.length个字节到byte数组中

public int read(byte b[]){}

// 从输入流中读取len个字节到字节数组中

public int read(byte b[], int off, int len){}

3、文件读取:

1、read()每次读取一个字节数据,返回字节数,如果到达文件末尾,返回-1。

文本abcpublic static void method_01(String filePath) throws IOException {

FileInputStream inputStream = null;

try {

inputStream = new FileInputStream(filePath);

// 每次读取一个字节

for (int i = 0; i < 4; i++) {

int read = inputStream.read();

System.out.println(read);

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} finally {

if (null != inputStream) {

// 关闭IO流

inputStream.close();

}

}

}

执行结果:97

98

99

-1

从执行结果可以看出,前三次读取到了数据,返回了对应的ASCII码,当读取到文件末尾的时候,则返回-1。

2、read(byte[] b)读入缓冲区的字节总数,如果到达文件末尾,则返回-1。

文本:abcdefg

声明一个大于真实数据的byte数组读取数据。public static void method_02(String filePath) throws IOException {

FileInputStream inputStream = null;

try {

inputStream = new FileInputStream(filePath);

// 声明的长度大于真实数据长度

byte[] bytes = new byte[20];

int length = inputStream.read(bytes);

System.out.println("字节数组长度:" + bytes.length + " 读取到的数据字节长度:" + length);

for (byte b : bytes) {

System.out.print(b + " | ");

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} finally {

if (null != inputStream) {

inputStream.close();

}

}

}

执行结果:字节数组长度:20 读取到的数据字节长度:7

97 | 98 | 99 | 100 | 101 | 102 | 103 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |

可以看出,当我们byte数组的长度大于字节数组的真实长度之后,那么后面的空间全部使用0做补位,这也恰恰反映了另外一个问题,我们在使用byte[]数组读取文件的时候,千万不要说我设置足够大的长度,就可以高枕无忧提高读取效率,如果遇到小文件,那么也是很容易造成效率低下的。

3、read(byte b[], int off, int len)读入缓冲区的字节总数,如果读取到文件末尾,则返回-1;

文本:abcdefg

声明一个固定大小的byte数组,循环读取数据

我们的文本有七个字节,声明了一个2个长度的数组,应该循环四次,第五次读取的时候返回-1。public static void method_03(String filePath) throws IOException {

FileInputStream inputStream = null;

try {

inputStream = new FileInputStream(filePath);

// 声明2个长度

byte[] bytes = new byte[2];

int i = 0;

while (i < 5) {

int length = inputStream.read(bytes, 0, bytes.length);

System.out.println("第" + (i + 1) + "次读取,length: " + length);

System.out.println("开始输出:");

for (int j = 0; j < length; j++) {

System.out.print(bytes[j] + " | ");

}

System.out.println();

i++;

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} finally {

if (null != inputStream) {

inputStream.close();

}

}

}

执行结果:第1次读取,length: 2

开始输出:

97 | 98 |

第2次读取,length: 2

开始输出:

99 | 100 |

第3次读取,length: 2

开始输出:

101 | 102 |

第4次读取,length: 1

开始输出:

103 |

第5次读取,length: -1

开始输出:

注意:

可能有的朋友会遇到我之前遇到的问题,他的文本里面写了汉字或者标点符号,会出现乱码,我们给文本最后再追加一个中文,并且把每次读取到的byte数组转换成String进行输出,看会出现什么情况。public static void method_03(String filePath) throws IOException {

FileInputStream inputStream = null;

try {

inputStream = new FileInputStream(filePath);

byte[] bytes = new byte[2];

int i = 0;

while (i < 5) {

inputStream.read(bytes, 0, bytes.length);

// 将byte[]转换成string

String s = new String(bytes, StandardCharsets.UTF_8);

System.out.println(s);

i++;

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} finally {

if (null != inputStream) {

inputStream.close();

}

}

}

结果:ab

cd

ef

g�

��

刚开始脑子抽了,感觉这是什么问题,怎么会乱码呢,如果稍微上点心的都会发现,中文占3个byte字节,你用2个存储那铁定乱码呀。那么你肯定想过那我把数组声明大一点不就好了,如果你这么想过,那你可能还不知道社会的险恶。

那么到底怎么办呢?真的就没办法了吗?接下来我们用一个例子来学习如何解决这种问题。

一个🌰:将文本中的内容读取出来,输出到控制台。

既然我们知道,上面的乱码是因为英文和中文占用的字节数不同引起的,那我们要是知道了整个文件占用的字节长度,那么不就一次性可以读取出来了。恰好FileInputStream提供了这样一个方法(available),让我们可以获取到整个文件所占用的字节数。public static void printConsole(String filePath) throws IOException {

FileInputStream inputStream = null;

try {

inputStream = new FileInputStream(filePath);

// 获取到整个文本占用的整个字节数

int available = inputStream.available();

// 声明数组

byte[] bytes = new byte[available];

// 读取数据

int readLength = inputStream.read(bytes, 0, available);

String s = new String(bytes, StandardCharsets.UTF_8);

System.out.println("读取到的长度:" + readLength + " available:" + available);

System.out.println("读取到的内容: " + s);

} catch (FileNotFoundException e) {

e.printStackTrace();

} finally {

if (null != inputStream) {

inputStream.close();

}

}

}

结果:读取到的长度:30 available:30

读取到的内容: abcdef一个程序员的成长

这样的话,我们就可以读取到文本中完整的内容了。只有了解了这些,那么才会了解我们的写文件下载的时候为什么要判断 读取到的字节数 !=-1 这样的操作,不然真的很难记住。

字符输入流

FileReader

1、构造方法:public FileReader(String fileName){};

public FileReader(File file){};

public FileReader(FileDescriptor fd){};

2、read方法:public int read(){};

public int read(char cbuf[], int offset, int length){};

public int read(char cbuf[]){};

3、文件读取:

FileReader的read方法读取出来的是一个独立的字符(char),所以面对英文和中文的混合,我们不会因为占用字节的不同从而导致出现乱码的情况。

文本:abcdef一个程序员的成长

读取内容的代码:public static void method_01(String filePath) throws IOException {

FileReader fr = null;

try {

fr = new FileReader(filePath);

int c;

// 每次读取一个字符,等于-1即表示文件读取到末尾

while ((c = fr.read()) != -1) {

System.out.println((char) c);

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} finally {

if (null != fr) {

fr.close();

}

}

结果:a

b

c

d

e

f

根据结果可以看出,read()读取出来的每次就是一个单独的字符,那么另外两个read方法跟字节流读取都是一样的。

更多内容请关注微信公众号:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值