您的位置 首页 > 数码极客

java如何读取byte数组长度 java inputstream读取byte数组!

一、IO流,什么是IO?

I :Input

O:Output

通过IO可以完成硬盘文件的读和写

二、IO流的分类

有多种分类方式:

1. 按照流的方向进行分类(输入流、输出流):

以内存作为参照物

往内存中去,叫做输入(Input),或者叫做读(Read)。

从内存中出来,叫做输出(Output),或者叫做写(Write)。

2. 按照读取数据方式不同进行分类(字节流、字符流):

  • 按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制。这种流是万能的,什么类型的文件都可以读取。包括:文本文件、图片、声音文件、视频文件等。

假设文件,采用字节流的话是这样读的:

文件内容:

a我是中国人

第一次读:一个字节,正好读到 ‘a’

第二次读:一个字节,正好读到’中’字符的一半

第三次读:一个字节,正好读到’中’字符的另外一半

……

  • 按照字符的方式读取数据,一次读取一个字符,这种流是为了方便读取普通文本文件而存在的,这种流不能读取:图片、声音、视频等文件,只能读纯文本文件(能用 .txt 打开的文件,没有特殊格式,文件名后缀不一定是.txt,比如.java文件也属于纯文本文件),word文件不属于纯文本文件。

假设文件,采用字符流的话是这样读的:

文件内容:

a我是中国人

第一次读:一个字符,正好读到 ‘a’(‘a’字符在Windows系统中占用1个字节)

第二次读:一个字节,正好读到’中’('中’字符在Windows系统中占用2个字节)

……

三、IO流的四大家族

首先,Java中所有的流都是在java.io.*下

四大家族:


Tips:如何分辨字节流和字符流:在Java中只要“类名”以Stream结尾的都是字节流;以“Reader/Writer”结尾的都是字符流

两点注意:

1、所有的流都实现了java.io.closeable接口,都是可关闭的,都有close()方法。流是一个管道,连接内存和硬盘,用完之后一定要关闭,不然会耗费(占用)很多资源。

2、所有的输出流都实现了java.io.Flushable接口,都是可刷新的,都有flush()方法。在输出流的最终输出之后,一定要记得flush()刷新一下,这个刷新表示将通道/管道当中剩余未输出的数据强行输出完(清空管道),如果没有flush()可能会导致丢失数据。

四、需要掌握的流

java.io包下需要掌握的流有16个


文件流专属:

  • java.io.FileInputStream
  • java.io.FileOutputStream
  • java.io.FileReader
  • java.io.FileWriter

转换流:(将字节流转换成字符流)

  • java.io.InputStreamReader
  • java.io.OutputStreamReader

缓冲流专属:

  • java.io.BufferedReader
  • java.io.BufferedWriter
  • java.io.BufferedInputStream
  • java.io.BufferedOutputStream

数据流专属:

  • java.io.DataInputStream
  • java.io.DataOutputStream

标准输出流:

  • java.io.PrintWriter
  • java.io.PrintStream

对象专属流:

  • java.io.ObjectInputStream
  • java.io.ObjectOutputStream

五、代码详解

  • 接下来的代码演示中,我把很多重点直接放在了注释中,方便大家理解
  • 先展示一下示例文档的内容,接下来我们开始对其读取


1、最原始,逐字节读取(使用java.io.FileInputStream)

package JavaIO;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

public class Test {

public static void main(String[] args) {

//创建一个输入流

FileInputStream fileInputStream = null;

try {

fileInputStream = new FileInputStream("Text");

int readData = 0;

//逐字节读取,当文档被读完时,read()方法返回-1,循环结束

while ((readData = ()) != -1)

{

Sy(readData);

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}finally {

//在finally块中关闭流

if (fileInputStream != null) {

try {

();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

运行结果:

可见读到了文档每个字符的ASCII码值


2、上述方法内存和硬盘之间的交互过于频繁,每个字节都要交互一次,效率极低,所以接下来我们使用int read(byte[] b)方法,一次读取多个字符,减少硬盘和内存的交互,提高程序的执行效率。(使用java.io.FileInputStream)

package JavaIO;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

public class Test {

public static void main(String[] args) {

//创建一个输入流

FileInputStream fileInputStream = null;

try {

//这里说明一下,工程Project的根就是IDEA的默认当前路径,注意相对路径和绝对路径的区别

fileInputStream = new FileInputStream("Text");

//准备一个4个长度的byte数组,一次最多读取4个字节,这里大小可以任意定

//这里再次说明,数组开的太大会导致内存溢出,所以一定要合理选择

byte[] bytes = new byte[4];

//用来记录每次读到的字节数,很重要!

int readCount = 0;

//每4个字节读取一次,当文档被读完时,read()方法返回-1,循环结束

while ((readCount = (bytes)) != -1)

{

//把byte转换为字符串,读到多少个转换多少个

Sy(new String(bytes,0,readCount));

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}finally {

//在finally块中关闭流

if (fileInputStream != null) {

try {

();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

运行结果:

通过String类将字节转换成字符串输出,输出达到预期


这里必须要解释一下int read(byte[] b)方法的运行机制,大家就能明白readCount这个变量的重要性了


根据上图,如果把readCount换成数组长度

Sy(new String(bytes,0,readCount));

换成

Sy(new String(bytes,0,by));

则运行结果如下图,显然不符合我们的要求,所以要注意int read(byte[] b)方法返回值的使用:


在这里我们再介绍两种常用方法:

// @return an estimate of the number of remaining bytes that can be read

// (or skipped over) from this input stream without blocking.

//此方法可以返回此文件还有多少字节没有读,可以做为while循环终止条件使用

public int available() throws IOException {

return available0();

}

//This method may skip more bytes than what are remaining in the backing file.

//此方法可以跳过几个字节不读取,比如一些文件有规定好的读取方式,跳过几个字节读几个字节才是正确的读入

public long skip(long n) throws IOException {

return skip0(n);

}

3、FileOutputStream的使用和FileOutputStream类似,这里举一个文件复制的例子(使用java.io.FileInputStream和java.io.FileOutputStream;)

package JavaIO;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

public class Test2 {

public static void main(String[] args) {

//创建一个输入流

FileInputStream fileInputStream = null;

//创建一个输出流

FileOutputStream fileOutputStream = null;

try {

//这里说明一下,工程Project的根就是IDEA的默认当前路径,注意相对路径和绝对路径的区别

fileInputStream = new FileInputStream("Text");

//下面如果写成这样,就会在原文档之后累加,之后的输出流也一样

//fileOutputStream = new FileOutputStream("Ou;,true);

fileOutputStream = new FileOutputStream("Ou;);

//准备一个4个长度的byte数组,一次最多读取4个字节,这里大小可以任意定

//这里再次说明,数组开的太大会导致内存溢出,所以一定要合理选择

byte[] bytes = new byte[4];

//用来记录每次读到的字节数,很重要!

int readCount = 0;

//每4个字节读取一次,当文档被读完时,read()方法返回-1,循环结束

while ((readCount = (bytes)) != -1)

{

//最核心的:一边读,一边写

(bytes,0,readCount);

}

//输出流最后要刷新

();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}finally {

//在finally块中关闭流

//两部分要分开写,否则发生异常可能会导致有通道没有关闭

if (fileInputStream != null) {

try {

();

} catch (IOException e) {

e.printStackTrace();

}

}

if (fileOutputStream != null) {

try {

();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

  • 运行结果:


被复制到了

4、FileReader的使用,只不过是按字符读,和fileInputStream没什么区别

package JavaIO;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

public class Test3 {

public static void main(String[] args) {

//创建一个输入流

FileReader fileReader = null;

try {

//这里说明一下,工程Project的根就是IDEA的默认当前路径,注意相对路径和绝对路径的区别

fileReader = new FileReader("Text");

//准备一个char数组

//这里再次说明,数组开的太大会导致内存溢出,所以一定要合理选择

char[] chars = new char[4];

//往char数组中读

int readCount = 0;

while ((readCount = (chars)) != -1)

{

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

Sy(chars[i]);

}

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}finally {

//在finally块中关闭流

if (fileReader != null) {

try {

();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

运行结果:

可见是逐个读取的字符

5、再讲讲BufferedReader缓冲流

这个流说白了就是无需我们自己定义byte[]数组来承接,其自带缓冲

这里还要明白节点流和包装流的概念,这两个概念往往是相对的

package JavaIO;

import java.io.*;

public class Test4 {

public static void main(String[] args) throws Exception{

//这里对异常不再处理只是为了演示方便,实际情况千万不要这么做

FileReader fileReader = new FileReader("Text");

// 当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流

// 外部负责包装的这个流,叫做:包装流,或者叫处理流

// 像当前这个程序来说:FileReader就是一个节点流,BufferedReader就是包装流/处理流

BufferedReader bufferedReader = new BufferedReader(fileReader);

//readLine()方法读取一个文本行,但不带换行符

String s = null;

while ((s = bu()) != null)

{

Sy(s);

}

//对于包装流来说,只需关闭最外层流就行,里面的节点流会自动关闭。

bu();

}

}

运行结果:

成功读取

6、唠唠转换流

转换流的作用就是三层套娃中间的二娃

这里对异常不再处理只是为了演示方便,实际情况千万不要这么做

package JavaIO;

import java.io.*;

public class Test5 {

public static void main(String[] args) throws Exception{

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("Text2")));

out.write("我们都有一个家");

out.write("名字叫中国!");

//刷新

out.flush();

//关闭最外层即可

out.close();

}

}

运行结果:

7、再谈谈数据流

能干什么:DataOutputStream写的文件,只有DataInputStream去读,并且已知读取规则,才可以正常取出数据

package JavaIO;

import java.io.*;

public class Test6 {

public static void main(String[] args) throws Exception{

DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream("Text3"));

byte b = 100;

short s = 200;

int i = 300;

long l = 400L;

float f = 3.0F;

double d = 3.14;

boolean flag = false;

char c = 'a';

//开始写,把数据以及数据的类型一并写入到文件当中

da(b);

da(s);

da(i);

da(l);

da(f);

da(d);

da(flag);

da(c);

da();

da();

DataInputStream dataInputStream = new DataInputStream(new FileInputStream("Text3"));

//开始读

byte b1 = da();

short s1 = da();

int i1 = da();

long l1 = da();

float f1 = da();

double d1 = da();

boolean flag1 = da();

Sy(b1);

Sy(s1);

Sy(i1);

Sy(l1);

Sy(f1);

Sy(d1);

Sy(flag1);

da();

}

}

运行结果:


8、标准输出流

本质是向控制台输出,但是我们可以改变输出方向,一般将其作为日志工具类

定义Logger类

package JavaIO;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.PrintStream;

import java.;

import java.u;

public class Logger {

public static void log(String msg) {

try {

//指向一个日志文件

PrintStream printStream = new PrintStream(new FileOutputStream("log.txt", true));

//改变输出方向

Sy(printStream);

//取当前日期和时间

Date date = new Date();

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String str = (date);

Sy(date + ":" + msg);

();

} catch (FileNotFoundException e) {

e.printStackTrace();

}

}

}

定义测试类

package JavaIO;

public class Test7{

public static void main(String[] args) {

//测试工具类

Logger.log("程序运行正常");

Logger.log("xxxxxx");

}

}

运行结果:


责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“java如何读取byte数组长度,java,inputstream读取byte数组,java读取文件byte数组,java循环读取byte数组”边界阅读