以前在课堂上学习Java 读写文件的时候,并没有对于Java体系有一个很好的认知,因此学习起来的时候并没有很好的理解Java的文件操作形式。也导致我总是记不住Java的文件操作代码。后来工作后,也一直用网上的文件工具类,或者是同事的工具类。在一次空闲的时间里,重新看了下自己的代码,发现File工具类写的什么奇葩玩意,于是自己重新尝试去理解Java的IO。
File
我相信如果初学Java的人应该会有一个疑问,为什么Java的File类里面没有直接对其进行操作的方法,比如File.read()这种操作。答案当然是Java的设计者非常的深思熟虑,而且结合Java的类和实例的关系,并且根据实际的流的应用复用而进行如此设计。File类也仅是作为一个文件或者文件夹,在Java中,File的定义非常的底层,在我们常人的认知里面,文件和文件夹并不是同一类型,而在Java的File中File包含了 文件、文件夹、系统盘。这里就不展开讲述,在File类中,并没有包含对于文件的读写操作。
Steam
想要对文件的读写操作,在java里面是使用Stream,读取操作使用的是输入流(FileInputStream),写操作使用的是输出流(FileOutputStream)。在Java中FileInputStream是InputStream的子类,而InputStream 没有实例方法。
而在其中,Java还提供了各种流的处理器,这些处理器中,包含了对于文件的一些编码处理,以及文件中的字符处理,和文件头处理等。例如常规的字符读写,用的是FileReader 和 FileWriter,像FileReader的实例中,便提供了读取一行的操作。而FileReader|FileWriter这种读写器实例需要填入的参数便是以上的输入输出流,如果仅是单纯的要对文件进行文本字符读写,则直接使用FileReader 和 FileWriter中的 .read() | writer 会更为的简单方便。
但是实际上这种流处理器的存在,导致了网上代码错综复杂,每个人都有自己独特的写法,一样的功能,有些人用这个处理器,有的人用这个处理器。但是实际上那些人基本上都是没有一个好的理解,大部分都是看到就照搬,然后自己再转来转去编码,显得十分的愚蠢。
对于实际上的项目需求而言,例如读取文件操作的FileInputStream实例该类需要填入一个文件的参数。此后,便可以通过InputStream中的.read()来进行读取文件操作。
那么关于.read()的方法很多人都是模糊的应用。
实际上FileInputStream,read()分为三个重载,分别是 int read()
| int read(byte b[])
| int read(byte[] b, int off, int len)
int read()
该方法最为基础方法,仅进行读取操作。但是没有提供任何的存储和记录数据的形式,一般都不会使用该方法。
int read(byte b[])
该方法比较常用,填入的参数为 将读取到的数据放在传入的参数中。返回值int是一次读取的byte[]长度。如果读取失败,或者读取到结尾,则返回-1。
例如:
File file = new File("test.txt");
FileInputStream inputStream = new FileInputStream(file);
byte[] bufferContent = new byte[1024];
int readLength = inputStream.read(bufferContent);
在上面的代码中bufferContent开辟的大小为1024 ,在一次read()中最多读取到1024字节大小,剩下的内容,将会在下一次read()中继续读取,如果下一次的read中的长度不满足1024,那么bufferContent的实际有意义的数值仅为readLength的大小,即它的read操作实际上等于System.arraycopy();
的操作形式。
大部分的实际情况是通过循环持续读取,直至readLength=-1为止。
int read(byte b[], int off, int len)
该方法总体和上面的差不多,区别在于额外多了两个传入参数,第一个是存放至byte[]变量的偏移值,也可也称为起始值,第二个为长度,即读取多少长度。
那么在实际应用用,我们可能需要将这个文件全部读取完,并且该方法返回一个没有多余长度的byte[]数据,应该如何去实现?参考下面代码,如果能完整的看懂,那么相信你已经对读写已经完全理解。
public byte[] fileRead(File file) throws IOException{
FileInputStream fileInputStream = new FileInputStream(file);
int readLength;
int countLength = 0;
byte[] bufferContent = new byte[1048576];
while (true) {
readLength = fileInputStream.read(bufferContent, countLength, 1024);
if (readLength == -1) {
break;
}
countLength += readLength;
}
byte[] result = new byte[countLength];
System.arraycopy(bufferContent,0,result,0,countLength);
return result;
}
如果你想将byte[]转成String仅需要new String(byte b[])
即可,new String()提供了两个参数,第一个参数填入byte[] ,第二个参数可以选填编码类型例如 “gbk” | “utf-8” 等
注意如果是读取一般的txt文件,首字节会出现有文本头的数据,需要你自行处理。