java-IO

2017-06-02

IO基础

[TOC]

1.File类

1-1.概念

表示文件和目录路径名的抽象表示形式

可以实现文件创建/删除/重命名/得到路径/创建时间

1-2.方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
File(String path) //创建文件实例
separator() //表示路径分隔号"\"
createNewFile() //创建新文件
mkdir() //创建新文件夹
delete() //删除文件&文件夹(如果是文件夹,内部必须为空)
renameTo() //重命名

isDirectory() //判断是否为文件夹
isFile() //判断是否为文件
exists() //判断文件是否存在

list() //String[] 列出当前目录文件&&文件夹名
listFiles() //String[] 列出当前目录文件信息(绝对路径+文件名)
getName() //获取文件名
getPath() //获取相对路径
getParent() //获得当前文件父路径
getAbsolutePath() //获取绝对路径
lastModified() //最后修改时间
...见名知意

2.各种输入输出流

3.分割合并文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package com.demo.file;

import java.io.*;
import java.util.*;

/**
* @author DonY15
* @description 简易版I/O切割合并,流媒体概念
* @create 2018\10\23 0023
*/
public class DemoFile {
public static void main(String[] args) {
String srcPathHttpUser="F:\\websevice.wmv"; //假定该文件来自上传
File srcFile = new File(srcPathHttpUser);
// segmentation(srcFile,1024*1024*50); //切割目标文件

String srcPathDatabase=srcPathHttpUser; //假定该文件目录来自数据控
merge(srcPathDatabase); //合并目标文件

}

/**
* 切割文件
* @param srcFile 来源File
* @param cutSize 单体文件切割大小
*/
private static void segmentation(File srcFile,long cutSize) {
if(srcFile==null){return;}
int num=srcFile.length()%cutSize==0?(int)(srcFile.length()/cutSize):(int)(srcFile.length()/cutSize+1);
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
byte[] bytes=null; //每次读取字节数
int len=-1; //每次实际读取长度
int count=0; //每个文件读取次数
String[] fileName=srcFile.getName().split("[.]"); //分割文件名
try {
bis = new BufferedInputStream(new FileInputStream(srcFile));
for (int i = 0; i < num; i++) { //文件个数
bos= new BufferedOutputStream(new FileOutputStream(new File(srcFile.getParent()+fileName[0]+"-temp-"+ (i + 1)+"."+fileName[1])));
if (cutSize<=1024){ //如果文件小于1024字节,则缓冲区大小为文件大小
bytes=new byte[(int)cutSize];
count=1;
}else{ //如果该文件大于1024,则缓冲区大小为1024,进行分割
bytes=new byte[1024];
count=(int)cutSize/1024;
}
while(count>0&&(len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
count--;
}
if (cutSize/1024!=0){ //如果文件大小有余数,则再读一次剩余大小,节省缓冲区开销
bytes = new byte[(int) cutSize % 1024];
len=bis.read(bytes);
bos.write(bytes,0,len);
bos.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}


}

/**
* 合并
* @param mergeFileName 合并生成文件路径
*/
private static void merge(String mergeFileName){
//适配文件名
String[] split = mergeFileName.split(File.separator+File.separator );
String parentPath = mergeFileName.split(split[split.length - 1])[0];
String fileFirstName=split[split.length-1].split("[.]")[0];
String fileLastName=split[split.length-1].split("[.]")[1];
System.out.println(parentPath+fileFirstName+fileLastName);
File fileDir = new File(parentPath);
String[] list = fileDir.list();

TreeMap mergeTarget = new TreeMap();
for (int i = 0; i < list.length; i++) {
if (list[i].contains(fileFirstName)){
if (list[i].contains("."+fileLastName)){
mergeTarget.put(list[i],list[i]);
}
}
}
Vector<InputStream> vector = new Vector<>();
for (int i = 0; i < list.length; i++) {
if (list[i].contains(fileFirstName)){
if (list[i].contains("."+fileLastName)){
System.out.println(list[i]);
BufferedInputStream bis=null;
String fileName = (String) mergeTarget.get(list[i]);
try {
bis= new BufferedInputStream(new FileInputStream(parentPath + File.separator + fileName));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
vector.add(bis);
}
}
}
//输入流枚举
Enumeration<InputStream> es = vector.elements();

//合并流
SequenceInputStream sis = new SequenceInputStream(es);
BufferedOutputStream bos=null;
try {
bos= new BufferedOutputStream(new FileOutputStream(mergeFileName));
byte[] bytes = new byte[1024];
int len=-1;
while ((len=sis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}

} catch (IOException e) {
e.printStackTrace();
}finally {
try {
bos.close();
sis.close();
System.out.println("合并完成");
} catch (IOException e) {
e.printStackTrace();
}

}

}
}

4.I/O装饰者模式

利用各种Buffered包装真实的输入输出流,从而获得不同的扩展功能(如:缓存/打印等)

防止类爆炸问题(继承的子类过多,当添加一个子类时(该子类的功能,可能其他各种子类都需要))

以装饰者模式,来动态包装各种子类并扩展功能,降低添加大量子类导致的管理难度.

组件的形式动态扩展被装饰者,复用性高

  1. Component(被装饰对象基类) 具有功能1接口
  2. ConcreteComponent(具体被装饰对象) 具有功能1实现
  3. Decorator(装饰者抽象类) 具有功能1抽象类
  4. ConcreteDecorator(具体装饰者) 具有功能1(方法内部+具体装饰者特有的功能)实现
1
Component dec=new ConcreteDecorator(new Component()); //实现模式

4-1.豆浆计价器功能示例

需求:饮品:纯豆浆价格10元,加一份糖1元,加一份鸡蛋1.5元,加一份黑豆2元

目录:
1
2
3
4
5
6
7
8
9
-----------[被装饰者分支]-----------
interface Drink 饮品(被装饰者基类) [总接口]
class SoyaBeanMilk implements Drink 豆浆(具体被装饰者) 实现类

------------[装饰者分支]------------[需要实现总接口]
abstract class Decorator implements Drink (装饰者基类) 实现抽象类
class BlackBeanDecorator extends Decorator 加黑豆组件(具体装饰者) 实现类
class SugarDecorator extends Decorator 加糖组件(具体装饰者) 实现类
class EggDecorator extends Decorator 加鸡蛋组件(具体装饰者) 实现类
被装饰者基类
1
2
3
4
5

public interface Drink {
float cost(); //价格
String desc(); //描述
}
被装饰者具体类
1
2
3
4
5
6
7
8
9
10
11
public class SoyaBeanMilk implements Drink {
@Override
public float cost() {
return 10f;
}

@Override
public String desc() {
return "纯豆浆";
}
}
装饰者基类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class Decorator implements Drink {

private Drink drink;

public Decorator(Drink drink) {
this.drink = drink;
}

@Override
public float cost() {
return drink.cost();
}

@Override
public String desc() {
return drink.desc();
}
}
装饰者具体类-加黑豆
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class BlackBeanDecorator extends Decorator {

public BlackBeanDecorator(Drink drink) {
super(drink);
}

@Override
public float cost() {
return super.cost()+2.0f;
}

@Override
public String desc() {
return super.desc()+"+黑豆";
}
}
装饰者具体类-加鸡蛋
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class EggDecorator extends Decorator {

public EggDecorator(Drink drink) {
super(drink);
}

@Override
public float cost() {
return super.cost()+1.5f;
}

@Override
public String desc() {
return super.desc()+"+鸡蛋";
}
}
装饰者具体类-加糖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SugarDecorator extends Decorator {

public SugarDecorator(Drink drink) {
super(drink);
}

@Override
public float cost() {
return super.cost()+1.0f;
}

@Override
public String desc() {
return super.desc()+"+糖";
}
}
计价器实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public static void main(String[] args) {
Drink drink = new SoyaBeanMilk(); //纯豆浆
System.out.println("------------------购买收据------------------");
System.out.println(drink.cost()+"元");
System.out.println(drink.desc());

Drink sugarDecorator = new SugarDecorator(drink); //加糖

System.out.println(sugarDecorator.cost()+"元");
System.out.println(sugarDecorator.desc());

Drink eggDecorator = new EggDecorator(sugarDecorator); //加鸡蛋

System.out.println(eggDecorator.cost()+"元");
System.out.println(eggDecorator.desc());

Drink blackBeanDecorator = new BlackBeanDecorator(eggDecorator); //加豆浆
System.out.println("------------------共计金额------------------");
System.out.println("共计:"+blackBeanDecorator.cost()+"元");
System.out.println("配方:"+blackBeanDecorator.desc());

/*
------------------购买收据------------------
10.0元
纯豆浆
11.0元
纯豆浆+糖
12.5元
纯豆浆+糖+鸡蛋
------------------共计金额------------------
共计:14.5元
配方:纯豆浆+糖+鸡蛋+黑豆
*/
}

1.文件上传方案一

CommonsMultipartFile

CommonsMultipartFile常用方法通过spring管理后实现文件上传,具体过程百度很多,如下

https://www.2cto.com/kf/201412/360788.html

https://www.cnblogs.com/liaohongbin/p/7904536.html

较为完整的原生上传下载

https://blog.csdn.net/madun/article/details/8001266