java文件操作
java文件操作
-
使用File类,常用API有:(如 new File("a/b/c.txt"))
File类是不分文件还是文件夹的,两个都可以用来生成File对象。
-
getPath:得到的是初始化时的路径,即"a/b/c.txt"
-
getParentFile:得到上一层级File对象,即File("a/b")
-
getName:得到的是文件名,即"c.txt"
-
listFiles:得到的是File[]数组,即当前路径下所有文件/文件夹。
list()得到的是Sting[]文件名数组
// 使用FileFilter对listFiles()进行过滤,也可以替换为lambda表达式 File[] files = dir.listFiles(pathname -> pathname.getPath().endsWith(".txt")); File[] files = dir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.getPath().endsWith(".txt"); // 只要.txt后缀的文件 } });
-
renameTo(参数是File对象):若原文件是存在的,则真的是会对原文件重命名,不存在也不报错。
-
createNewFile:文件所在文件夹不存在会报错
-
isFile、isDirectory、getAbsolutePath、exists、mkdir、mkdirs(递归创建)、delete、deleteOnExit、canRead/canWrite/canExecute、setReadOnly、getTotalSpace、getUsableSpace、toURI、toPath等
-
-
文件复制/移动
文件的移动在复制后调用delete即可,或者用java7的NIO包中的Files类的move方法
-
1、FileStream文件二进制流;2、使用nio的FileChannel的transferFrom方法,较FileStream方式高效;3、使用java7的Files类;4、使用Apache Commons IO提供拷贝文件方法在其FileUtils类,本质还是使用了NIO的FileChannel
// 拷贝单个文件:方式1:FileStream文件二进制流 try { is = new FileInputStream(inPath); os = new FileOutputStream(outPath); byte[] b = new byte[1024]; while (is.read(b) != -1) { os.write(b); } } catch (Exception e) {e.printStackTrace();} // 拷贝单个文件:方式2:使用nio的FileChannel的transferFrom方法,较FileStream方式高效 try { inputChannel = new FileInputStream(inPath).getChannel(); outputChannel = new FileOutputStream(outPath).getChannel(); outputChannel.transferFrom(inputChannel, 0, inputChannel.size()); } catch (Exception e) {} // 拷贝单个文件:方式3:使用java7的nio包新增的Files类 try { Files.copy(new File(inPath).toPath(), new File(outPath).toPath()); return true; } catch (IOException e) {} // 拷贝单个文件:方式4:使用Apache Commons IO提供拷贝文件方法在其FileUtils类,本质还是使用了NIO的FileChannel // public void copyFileUsingApacheCommonsIO(File source, File dest) { // FileUtils.copyFile(source, dest); // }
-
-
文件压缩和解压
-
Apache Commons Compress
-
zip4j
-
自定义压缩解压,利用nio包优化字节流传输效率。
自己写则使用ZipOutputStream,每次用流写入前都要putNextEntry放入一个入口路径。
直接缓冲区:直接缓冲区不在JVM中开辟,由操作系统决定何时写入。当线程处于内核空间称之为内核态,处于用户空间则属于用户态。java的线程操作java内置数组,内置数组在用户空间属于用户态,也就是:操作系统磁盘IO操作要先经过内核空间,再传递给用户空间,还需要和内核空间交互,因此速度较慢。若使用直接缓冲区,开辟的是JVM外的直接物理空间,操作系统IO直接由内核写入直接缓冲区,不必再传递给jvm的内存空间,操作完毕再通知java,因此速度较快。
但直接缓冲区也有缺点:因为不在JVM的内存模型中,所以不安全;消耗多;JVM对数据的管理权限下降
- 利用非直接缓冲区,即java的字节数组作为中间人,写入数据。若不用BufferedInputStream字节数组,会慢很多倍!
- 利用FileChannel的直接缓冲区,效率更高。
- 利用FileChannel.transferTo,直接连通2个channel通过直接换乘写入。
- 利用内存映射文件MappedByteBuffer,NIO新特性。
// 方式1:利用非直接缓冲区,即java的字节数组作为中间人,写入数据。若不用BufferedInputStream字节数组,会慢很多倍! private void zipSingleFileUsingZipStream(File file, ZipOutputStream zos) { try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) { byte[] b = new byte[bufferSize]; while (bis.read(b) != -1) zos.write(b); } catch (Exception ignored) {} } // 利用FileChannel的直接缓冲区,直接缓冲区不在JVM中开辟,由操作系统决定何时写入。效率更高 private void zipSingleFileUsingChannel(File file, WritableByteChannel zoc) { try (FileChannel fileInChannel = new FileInputStream(file).getChannel()) { // 方式2:利用FileChannel.transferTo,直接连通2个channel通过直接换乘写入。 fileInChannel.transferTo(0, fileInChannel.size(), zoc); // 方式3:利用内存映射文件,NIO新特性。也是开辟直接缓冲区,和方式2效率差不多。 // MappedByteBuffer mbb = fileInChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileInChannel.size()); // zoc.write(mbb); } catch (Exception ignored) {} }
-
-
操作excel
- POI
- 导出步骤? 创建工作簿对象,若是小表XSSFWorkbook就行,若是大表用SXSSFWorkbook(支持百万级,原理就是利用缓冲区,达到指定大小就自动刷新写入磁盘,避免内存溢出);创建sheet对象,设置行、列数等其他样式;创建标题单元格(即表头);写入数据时,每次换行调用createRow(),每次写单元格就调用createCell()
- 导入步骤?和导出类似,使用ExcelReader对象读取excel,使用getRow和getCell读取行和单元格。如果要读大表,普通读取会全表扫描进内存,应该使用SAX技术(一边加载一边解析),方法是修改SheetContentsHandler接口源码或者继承DefaultHandler(推荐),使用DefaultHandler就是事件驱动,重写end/startElement方法
- JXL
- POI