Netty之文件编程
目录
一、FileChannel
FileChannel只能在阻塞模式下工作
1. 获取方法
FileChannel不能直接打开,必须通过以下方法来获取FileChannel,他们都有getChannel方法。
代码如下(示例):
/*
* 通过FileInputStream获取的channel只能读
*/
try {
FileInputStream fileInputStream = new FileInputStream("test.txt");
FileChannel channel = fileInputStream.getChannel();
} catch (IOException e) {
e.printStackTrace();
}
/*
* 通过FileOutputStream获取的channel只能写
*/
try {
FileOutputStream fileOutputStream = new FileOutputStream("test.txt");
FileChannel channel = fileOutputStream.getChannel();
} catch (IOException e) {
e.printStackTrace();
}
/*
* 通过RandomAccessFile是否能读写根据构造RandomAccessFile时的读写模式决定
*/
try (FileChannel channel = new RandomAccessFile("test.txt", "r").getChannel()){
} catch (IOException e) {
e.printStackTrace();
}
2. 读取方法
代码如下(示例):
int bytes = channel.read(buffer);
3. 写入方法
代码如下(示例):
channel.write(buffer);
提示:channel.write()方法并不能一次将buffer中的内容全部写入channel
4. 关闭方法
channel必须关闭,不过调用了FileInputStream、FileOutputStream、RandomAccessFile的close方法会间接地调用close方法。
5. 位置方法
代码如下(示例):
// 获取当前位置
long position = channel.position();
// 设置当前位置
long newPos = 3;
channel.position(newPos);
若将当前位置时设置在文件末尾,读取时会返回 -1 。这时写入会追加内容,但是如果position超过了文件末尾,再写入时原内容末尾和新内容开头之间会有空洞(00)。
6. 大小方法
代码如下(示例):
long size = channel.size();
7. 强制写入方法
操作系统出于性能的考虑,会将数据缓存,部署立刻写入磁盘。可以调用foce(teue)方法将文件内容和元数据(文件的权限等信息立刻写入磁盘)
二、两个Channel传输数据
代码如下(示例):
public static void main(String[] args) {
try {
FileChannel from = new FileInputStream("data.txt").getChannel();
FileChannel to = new FileInputStream("to.txt").getChannel();
/*
* transferTo()效率高,底层会利用操作系统的零拷贝进行优化,但是最大只能传输2G数据
* position: 起始位置,count: 传输的数据量,target: 目前位置
*/
from.transferTo(0, from.size(), to);
/*
* 解决只能传输2G的方法
*/
for (long i = from.size(); i > 0; ) {
i -= from.transferTo((from.size() - i), from.size(), to);
}
} catch (IOException e) {
e.printStackTrace();
}
}
三、Path
jdk7 引入了 Path 和 Paths 类
- Path 表示文件路径
- Path 表示工具类,用来获取 Path 实例
- .代表当前路径,…代表了上一级路径
public static void main(String[] args) {
Path path = Paths.get("data.txt"); //相对路径,使用user.dir环境变量来定位data.txt
Path path1 = Paths.get("d:\\data.txt"); //绝对路径,代表了d:\data.txt
Path path2 = Paths.get("d:/data.txt"); //绝对路径,代表了d:\data.txt
Path path3 = Paths.get("d:\\data","project"); //代表了d:\data\project
}
四、Files
1.检查文件是否存在
代码如下(示例):
Path path = Paths.get("data.txt");
System.out.println(Files.exists(path));
2.创建目录
代码如下(示例):
public static void main(String[] args) {
try {
/*
* 创建一级目录
* 如果目录存在会抛异常FileAlreadyExistsException
* 不能一次创建多级目录,否则会抛异常NoSuchFileException
*/
Files.createDirectory(Paths.get("hello/data"));
/*
* 创建多级目录
*/
Files.createDirectory(Paths.get("hello/data/paths"));
} catch (IOException e) {
e.printStackTrace();
}
}
3.拷贝文件
代码如下(示例):
public static void main(String[] args) {
try {
Path source = Paths.get("hello/data.txt");
Path target = Paths.get("hello/target.txt");
/*
* 如果文件已经存在,会抛异常FileAlreadyExistsException。
* 如果要用source覆盖掉target,需要用StandardCopyOption来控制
*/
Files.copy(source,target, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
}
4.移动文件
代码如下(示例):
public static void main(String[] args) {
try {
Path source = Paths.get("hello/data.txt");
Path target = Paths.get("hello/target.txt");
/*
* StandardCopyOption.ATOMIC_MOVE保证文件移动的原子性
*/
Files.copy(source,target, StandardCopyOption.ATOMIC_MOVE);
} catch (IOException e) {
e.printStackTrace();
}
}
5.删除文件/目录
代码如下(示例):
public static void main(String[] args) {
try {
/*
* 删除文件
*/
Path source = Paths.get("hello/data.txt");
Files.delete(source); // 文件不存在会抛异常NoSuchFileException
/*
* 删除目录,只能删除空目录
*/
Path target = Paths.get("hello/data");
Files.delete(target); // 如果目录存在内容,会抛异常DirectoryNotEmptyException
} catch (IOException e) {
e.printStackTrace();
}
}
6.遍历目录文件
代码如下(示例):
public static void main(String[] args) throws IOException {
// 统计文件总数
AtomicInteger dirCount = new AtomicInteger();
AtomicInteger fileCount = new AtomicInteger();
// 访问者模式
Files.walkFileTree(Paths.get("E:\\environment\\java"), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
System.out.println("文件夹----------》"+dir);
dirCount.incrementAndGet();
return super.preVisitDirectory(dir, attrs);
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("文件----------》"+file);
fileCount.incrementAndGet();
return super.visitFile(file, attrs);
}
});
System.out.println("文件夹数量:"+dirCount);
System.out.println("文件数量"+fileCount);
}
查找指定 jar 文件代码示例:
public static void main(String[] args) throws IOException {
// 统计总数
AtomicInteger jarCount = new AtomicInteger();
Files.walkFileTree(Paths.get("E:\\environment\\java"), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (file.toString().endsWith(".jar")) {
System.out.println("文件----------》" + file);
}
jarCount.incrementAndGet();
return super.visitFile(file, attrs);
}
});
System.out.println("jar包数量:" + jarCount);
}
7.删除多级目录
代码如下(示例):(危险代码)
public static void main(String[] args) throws IOException {
Files.walkFileTree(Paths.get("E:\\environment\\java"), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
System.out.println("进入文件----->"+dir);
return super.preVisitDirectory(dir, attrs);
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("文件是-------->"+file);
Files.delete(file);
return super.visitFile(file, attrs);
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
System.out.println("----->退出文件"+dir);
return super.postVisitDirectory(dir, exc);
}
});
}
8.拷贝多级目录
代码如下(示例):
public static void main(String[] args) throws IOException {
String source = "E:\\environment\\java";
String target = "D:\\data\\java";
Files.walk(Paths.get(source)).forEach(path -> {
try {
String targetName = path.toString().replace(source, target);
//是目录
if (Files.isDirectory(path)) {
Files.createDirectory(Paths.get(targetName));
}else if (Files.isRegularFile(path)){
// 是文件
Files.copy(path,Paths.get(targetName));
}
} catch (Exception e) {
e.printStackTrace();
}
});
}