JDK1.7 中新增了nio包,基于此包可实现java程序基于操作系统的情况下对文件或文件夹进行CRUD操作,同时支持跨系统间的文件操作。
一、对文件操作代码
1、在java中基于IO对系统文件进行操作
public static void oldCopyFileList(){ long begin = System.currentTimeMillis(); FileInputStream input = null; FileOutputStream output = null; try { File file = new File("D:/1"); String newPath = "D:/2"; if(!file.isFile()){ for(int i=0;i<file.listFiles().length;i++){ File fileSun = file.listFiles()[i]; input = new FileInputStream(file.listFiles()[i]); output = new FileOutputStream(newPath + "/"+(fileSun.getName()).toString()); byte[] b = new byte[1024 * 5]; int len; while ((len = input.read(b)) != -1) { output.write(b, 0, len); } output.flush(); } } } catch (IOException e) { e.printStackTrace(); }finally{ if(null !=input ){ try { input.close(); } catch (IOException e) { } } if(null !=output ){ try { output.close(); } catch (IOException e) { } } } System.err.println("time:"+(System.currentTimeMillis()-begin)); }
2、java中基于nio对文件进行操作
public static void newFileList(){ long begin = System.currentTimeMillis(); try { Path path = Paths.get("D:/1"); String newPath = "D:/2/"; DirectoryStream<Path> streamList = Files.newDirectoryStream(path); for (Path pathSun : streamList){ Files.copy(pathSun, Paths.get(newPath+pathSun.getFileName()) , StandardCopyOption.COPY_ATTRIBUTES); } } catch (IOException e) { e.printStackTrace(); } System.err.println("time:"+(System.currentTimeMillis()-begin)); }
3、在Files工具类中同样提供了基于InputStream的文件操作方式,代码如下所示:
public static void oldCopyFileList(){ long begin = System.currentTimeMillis(); FileInputStream input = null; try { File file = new File("D:/1"); String newPath = "D:/2/"; if(!file.isFile()){ for(int i=0;i<file.listFiles().length;i++){ File fileSun = file.listFiles()[i]; System.err.println(fileSun.getName()); input = new FileInputStream(file.listFiles()[i]); Files.copy(input, Paths.get(newPath+fileSun.getName()), StandardCopyOption.REPLACE_EXISTING); } } } catch (IOException e) { e.printStackTrace(); }finally{ if(null !=input ){ try { input.close(); } catch (IOException e) { } } } System.err.println("time:"+(System.currentTimeMillis()-begin)); }
这种方式可用于上传的图片添加水印,但是只有想法,未投入到生产使用,不知道是否有什么后遗症。
比较
在处理单个大文件的拷贝时使用IO的效率要高于nio。nio在进行多个小文件拷贝时效率远远高于IO。
二、源码分析
window系统源码(与上方代码相对应这里只针对copy源码)
1、Files.copy
public static Path copy(Path paramPath1, Path paramPath2, CopyOption[] paramArrayOfCopyOption)throws IOException{ FileSystemProvider localFileSystemProvider = provider(paramPath1); if (provider(paramPath2) == localFileSystemProvider){ localFileSystemProvider.copy(paramPath1, paramPath2, paramArrayOfCopyOption); }else { //这里有支持其他系统的意思,我还未细研究写出应用实例 CopyMoveHelper.copyToForeignTarget(paramPath1, paramPath2, paramArrayOfCopyOption); } return paramPath2; }
通过以下代码来获得是当前是什么系统的,具体为什么还没有想通?
public static FileSystem getDefault(){ return DefaultFileSystemHolder.defaultFileSystem; } private static class DefaultFileSystemHolder { static final FileSystem defaultFileSystem = defaultFileSystem(); private static FileSystem defaultFileSystem(){ FileSystemProvider localFileSystemProvider = (FileSystemProvider)AccessController.doPrivileged(new PrivilegedAction(){ public FileSystemProvider run() { return FileSystems.DefaultFileSystemHolder.access$000(); } }); return localFileSystemProvider.getFileSystem(URI.create("file:///")); } }
2、WindowsFileSystemProvider.copy 在linux下的实现类为UnixFileSystemProvider
public void copy(Path paramPath1, Path paramPath2, CopyOption[] paramArrayOfCopyOption) throws IOException{ WindowsFileCopy.copy(WindowsPath.toWindowsPath(paramPath1), WindowsPath.toWindowsPath(paramPath2), paramArrayOfCopyOption); }
这里将公用的Path转为WindowsPath,linux下转为了UnixPath,还有相应的ZipPath,对zip文件操作。
3、WindowsFileCopy.copy() 这个方法操作非常复杂,这里只是最简单列了一种情况,而且其中好多异常捕获和线程的开关都删除掉了,有兴趣的请查看源码
WindowsFileAttributes localWindowsFileAttributes1 = null; WindowsFileAttributes localWindowsFileAttributes2 = null; //获得文件属性 比如只读 等等 long l1 = 0L; l1 = paramWindowsPath1.openForReadAttributeAccess(bool); localWindowsFileAttributes1 = WindowsFileAttributes.readAttributes(l1); //获得文件属性 比如只读 等等 long l2 = 0L; l2 = paramWindowsPath2.openForReadAttributeAccess(false); localWindowsFileAttributes2 = WindowsFileAttributes.readAttributes(l2); //获得文件路径 String str1 = asWin32Path(paramWindowsPath1); String str2 = asWin32Path(paramWindowsPath2); int i2 = ((paramWindowsPath1.getFileSystem().supportsLinks()) && (!bool)) ? 2048 : 0; try { WindowsNativeDispatcher.CopyFileEx(str1, str2, i2, 0L); } catch (WindowsException localWindowsException6) { localWindowsException6.rethrowAsIOException(paramWindowsPath1, paramWindowsPath2); }
4、WindowsNativeDispatcher 与操作系统对接的文件操作类
static void CopyFileEx(String paramString1, String paramString2, int paramInt, long paramLong) throws WindowsException{ NativeBuffer localNativeBuffer1 = asNativeBuffer(paramString1); NativeBuffer localNativeBuffer2 = asNativeBuffer(paramString2); try { CopyFileEx0(localNativeBuffer1.address(), localNativeBuffer2.address(), paramInt, paramLong); } finally { localNativeBuffer2.release(); localNativeBuffer1.release(); } } private static native long CreateFile0(long paramLong1, int paramInt1, int paramInt2, long paramLong2, int paramInt3, int paramInt4) throws WindowsException;
此类中还提供了CreateFile、DeleteFile、CreateDirectory等方法。
由于Jdk中添加了nio包,同时新增加了用以遍历文件目录的迭代器DirectoryStream继承于Iterable。
官方解释如下:
An object to iterate over the entries in a directory. A directory stream allows for the convenient use of the for-each construct to iterate over a directory.
其特点:其中定义了一个interface Filter<T> 静态内部接口。
相关推荐
在Java中,可以使用`java.nio.file.Files`和`java.nio.charset.Charset`类读取和写入文件。以下是一个简单的例子,展示了如何遍历目录,找到所有.txt文件并替换其中的特定字符串: ```java import java.io....
`java.nio.file.Files` 类提供了很多静态方法用于执行文件操作,如 `Files.copy()`, `Files.delete()`, `Files.readAllBytes()` 等。 7. **Path**:`java.nio.file.Path` 表示文件系统的路径,提供了创建、解析、...
Java提供了一系列用于文件和目录操作的类,主要包括`java.io`包下的`File`类以及`java.nio.file`包下的`Path`和`Files`等类。这些类提供了创建、删除、重命名文件和目录的功能,同时也支持读写文件内容的操作。 - *...
3. **DirectoryStream类**:在Java 7及以上版本,`java.nio.file.DirectoryStream`接口提供了一种更现代且灵活的方式来遍历目录中的文件。我们可以使用`Files.newDirectoryStream()`方法,配合`Path`对象,来创建一...
`java.nio.file`包中的`DirectoryStream`接口用于遍历目录,`Files.walkFileTree()`方法可以递归地遍历整个目录树。这种实现方式更适合深度遍历和并行处理,可以利用多核CPU的优势,进一步提升速度。 在这三种方法...
4. **NIO.2**:从Java 7开始,引入了NIO.2,增加了对文件系统操作的更多支持,如Path类、Files类和DirectoryStream接口。NIO.2还引入了WatchService,可以监控文件系统的变更事件。 5. **套接字编程**:讲解了TCP和...
通过`java.nio.file.FileVisitOption`和`Files.walkFileTree()`,我们可以过滤出特定类型的文件,如只列出所有的`.txt`文件。 在实际应用中,这些技术可能会结合使用,以满足不同的需求。例如,可以使用`Files....
3. **DirectoryStream**:Java 7引入了`java.nio.file.DirectoryStream`接口,用于流式处理目录内容。使用`Files.newDirectoryStream()`方法,我们可以更方便地遍历目录,而无需显式使用递归。 4. **预定义的文件...
- **文件系统API**:提供了一种面向对象的方式来处理文件系统,如`java.nio.file.Files`和`java.nio.file.Paths`。 - **Path接口**:用于表示文件系统的路径。 - **WatchService**:监视文件系统事件,如文件创建...
以下是一个简单的Java示例,使用`java.nio.file`包遍历目录和搜索文件: ```java import java.io.BufferedReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import ...
5. **文件复制与移动**: `Files.copy()`方法可以方便地复制文件,而`Files.move()`则用于移动或重命名文件。这两个方法都提供了原子性操作的选项,保证在多线程环境下不会出现数据丢失。 6. **文件权限管理**: Java...
1. 文件系统API(JSR 203):增加了新的文件API,如Path,Files和DirectoryStream,使得文件操作更加方便。 2. 多线程Fork/Join框架:基于工作窃取算法,用于高效地执行并行任务。 3. 并发工具类改进:如`java....
首先,遍历目录通常涉及到对文件系统进行操作,Java的`java.nio.file`包提供了丰富的API来处理文件和目录。`Files.list()`方法用于获取指定目录下的所有文件名,返回一个`Stream<String>`。例如,以下代码会打印当前...
在Java中,我们可以使用`java.io`和`java.nio.file`包来遍历文件,第三方库如Apache Commons Compress处理多种压缩格式。以下是一个简单的Java代码片段: ```java import org.apache.commons.compress.archivers....
此外,`java.io.File`类和`java.nio.file.Files`类可以帮助我们操作文件和目录,例如获取指定目录下的所有文件。下面的代码片段演示了如何遍历一个目录下的所有文件: ```java File directory = new File("path/to/...