新手如何学习java的IO(一)
前言,对于java本人是个小白,不过有点其他语言的经验,知道java是面向对象的,也就这么多。刚开始学习java,我也是蒙头啃书,啃完《Java核心编程一卷》的前8章,看着好像都懂,但是合上书回忆自己到底学了些什么,又好像一片空白。ps:我也有过打书上的代码,但是感觉这本书还是实例太少,缺少那种可实际操作的问题吧(仅对于我,勿喷!)。于是,我就去网上查查看看别人是如何学习java的,第一站就是知乎了,翻了好几个帖子,都说这本书是基础,要细心啃,然后就是列出了一些关键点集合,泛型,IO,多线程,类加载机制,反射,代理。下一步,我就去网上找以上类似的资源了,找到一个对于我这种小白特别合适的线上资源,底下有介绍。
读写文件
把文件里的内容读入内存,这里有两种方法,一种是字节型的,一种是字符型的,详细如下图。另外,这是一个Java IO 的 Tutorial,虽然是英文的,但是很详细。
image.png读文件
// 创建文件对象
File f = new File("/Users/tofu/Downloads/javatext.txt");
// 创建文件输入流
FileInputStream fis = new FileInputStream(f);
// 创建byte数组
byte[] fileContent = new byte[(int)f.length()];
//读入文件内容到fileContent数组中
fis.read(fileContent);
for(byte b:fileContent){
System.out.println(b);
}
//关闭输入流
fis.close();
如果指定文件存在的话,就成功把文件里的内容以byte格式读入数组。
把内容写入指定文件
Question:创建指定目录下的文件。(如果如果该文件的上一层目录不存在呢?,上上一层也不存在呢?)
public void StringToFile(path){
File f = new File(path);
//获取该文件的父目录
File dir = f.getParentFile();
//System.out.println(dir);
// 如果该父目录不存在,则创建
if (!dir.exists()) {
dir.mkdirs();
System.out.println("dir is not exits");}
try {
// 创建文件
if (!f.exists()) f.createNewFile();
// 创建输出流
FileOutputStream fout = new FileOutputStream(f);
byte[] tt = {88,89,32,32,43,54,88,89};
//写入文件
fout.write(tt);
// 关闭文输出流
fout.close();
}catch(IOException e){
e.printStackTrace();
}
}
文件夹遍历
顾名思义,就是使用java查看在某个目录下存在的文件,分两种情况,即包含子文件夹的文件,和不包含子文件夹的文件。
找出其中最大、最小文件(一)
Attention:不包含子文件夹里的文件
这个比较简单,主要就是知道,Java中File类里有个listFiles()函数,同时file.length()可以计算文件大小,主要代码如下:
//创建一个File类型的数组,把该文件夹下的文件全部放入该数组中,之后遍历数组,并比较即可
File dir = new File(path);
File[] allFiles = dir.listFilse();
for(File f : allFiles){
if(f.isDirectory()) continue;
else{
.
}
}
找出其中最大、最小文件(二)
Attention:包含子文件夹里的文件
看似差不多的问题,其实难度还是相差很多的,因为上个问题,我们只需在指定目录下列出所有文件即可,但是这个问题不行,我们无法知道,该目录下还有多少个子目录,就像拨洋葱,一层又一层。这里,就很容易想到使用递归去解决问题了,不过本文不打算使用递归的方法,本文采用广度优先搜索的方法来解决该问题。
广度优先搜索,简单来说就是按层级搜索,第一层遍历完了,遍历第二层。如图所示,遍历的顺序就是1>2>3>4>5>6>7>8。主要思想为:
- 创建两个队列,一个队列用来装所有文件计作q1,一个用来装所有目录计作q2
- q2每弹出一个目录,遍历其下所有文件及文件夹,把文件按顺序放入q1,目录按顺去放入q2
- 循环上述操作,直至q2为空,遍历结束
- q1里存放的即为所有文件
- 这里没讲文件的比较,因为比较简单,就不讲了,贴了代码。
public void getAllFiles(){
String path = "/Users/tofu/Downloads";
File root = new File(path);
//存放所有的文件
LinkedList<File> fileList = new LinkedList<File>();
//存放所有的目录
LinkedList<File> DirList = new LinkedList<File>();
DirList.add(root);
long maxLength = Long.MIN_VALUE;
long minLength = Long.MAX_VALUE;
//记录当前最大文件和最小文件
File[] fillNames = new File[2];
File queue = null;
//判断目录是否为空
while(DirList.size()>0){
//弹出一个目录
queue = DirList.remove();
File[] filesInQueue = queue.listFiles();
for (File f:filesInQueue){
if(f.isFile()) {
fileList.add(f);
long tmpLength = f.length();
if(tmpLength>maxLength){
fillNames[0] = f;
maxLength = tmpLength;
}
if(tmpLength < minLength){
fillNames[1] =f;
minLength = tmpLength;
}
}
if(f.isDirectory()) {
DirList.add(f);
System.out.println(f + "is a Directory");
}
}
}
System.out.println("the maximum file name is" + fillNames[0]+" the size is "+maxLength);
System.out.println("the minimum file name is" + fillNames[1]+" the size is "+minLength);
}
文件拆分
Question:找到一个大于100k的文件,按照100k为单位,拆分成多个子文件,并且以编号作为文件名结束。
public void splitFile(String toSplitFile){
File sourceFile = new File(toSplitFile);
byte[] fileContent = new byte[(int) sourceFile.length()];
int fileNum = 0;
FileInputStream fis=null;
try(fis = new FileInputStream(sourceFile)){
fis.read(fileContent);
}catch(IOException e){
e.printStackTrace();
}
//存储每个小文件的内容
byte[] eachContent;
//计算文件个数
if(sourceFile.length()%blockSize==0){
fileNum = fileContent.length/blockSize;
}
else{
fileNum = fileContent.length/blockSize+1;
}
FileOutputStream fout =null;
for(int i=0;i<fileNum;i++){
File f = new File(sourceFile.getParent(),sourceFile.getName()+"_"+i);
if (i!=fileNum-1){
eachContent = Arrays.copyOfRange(fileContent,i*blockSize,(i+1)*blockSize);
}
else{
eachContent = Arrays.copyOfRange(fileContent,i*blockSize,fileContent.length);
}
try(fout = new FileOutputStream(f)){
fout.write(eachContent);
}catch(IOException e){
e.printStackTrace();
}
System.out.printf("the no %d is create\n",i);
}
}
文件合并
Question:合并上述已拆分的文件
public void mergeFile(String floder, String name){
File allFiles = new File(floder,name);
try(FileOutputStream fout = new FileOutputStream(allFiles)){
int i = 1;
while(true){
File f = new File(floder,name+"_"+i++);
if(!f.exists()) break;
byte[] each = new byte[(int)f.length()];
try(FileInputStream fis =new FileInputStream(f)){
fis.read(each);
}catch(IOException e){
e.printStackTrace();
}
fout.write(each);
}
}catch(IOException e){
e.printStackTrace();
}
System.out.println("the file is create");
}
流的两种关闭方式
在finally中关闭
- 首先把流的引用声明在try的外面,如果声明在try里面,其作用域无法抵达finally.
- 在finally关闭之前,要先判断该引用是否为空
- 关闭的时候,需要再一次进行try catch处理
public static void main(String[] args) {
File f = new File("/Users/tofu/Downloads/javaTest.txt");
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
byte[] all = new byte[(int) f.length()];
fis.read(all);
for (byte b : all) {
System.out.println(b);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 在finally 里关闭流
if (null != fis)
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
在try中关闭
File f = new File("d:/lol.txt");
//把流定义在try()里,try,catch或者finally结束的时候,会自动关闭
try (FileInputStream fis = new FileInputStream(f)) {
byte[] all = new byte[(int) f.length()];
fis.read(all);
for (byte b : all) {
System.out.println(b);
}
} catch (IOException e) {
e.printStackTrace();
}
网站介绍
我是在这个网站上学习的,感觉站长很厉害,讲的很清楚,例子也很好。网站一部分是收费的,一部分是免费的,目前我还在学习免费的,可能下次学spring框架时就去购买收费的了。这里不是打广告,只是感谢站长让我有收获了。