IO操作
Java对数据的操作都是通过流的方式,IO流用来处理设备之间的数据传输,文件上传和文件下载,Java用于操作流的对象都在IO包,NIO(New IO)包中。
创建文件
Java创建文件的方式有三种方式,我们接下来一个一个来介绍。
-
File.createFile()
java.io.file能够创建新的文件。创建一个File对象后,可以通过File对象的createNewFile方法创建文件,如果创建成功就返回true,如果创建失败就返回false。创建成功的文件是一个空文件,创建失败会抛出IO异常。创建File对象时是需要传入文件文件目录和名称,可以是绝对路径也可以是相对路径(相对当前工程的根目录内,和src同级别).
public class CreateFile { public static void main(String[] args) { // 方法一:File.createFile() File file= new File("./file.txt"); try { boolean success = file.createNewFile(); if (success) { System.out.println("Cretea File Success"); } else { System.out.println("Cretea File Fail"); } } catch (IOException e) { e.printStackTrace(); } }}
-
FileOutputStream.write(byte[] b)
当创建文件是还想加入一些数据在文件中去,就可以使用FileOutputStream.write这个方法。代码如下
public class CreateFile { public static void main(String[] args) { String data = "Hello world!"; try { FileOutputStream outputStream = new FileOutputStream("./Hello.txt"); // 创建文件 outputStream.write(data.getBytes()); // 写入数据 outputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
-
**NIO Files.write(Path path, byte[] bytes, OpenOption… options) **
NIO就是New IO 的意思,是一个可以替代标准Java IO API的API,提供的和标准IO 不同的工作方式。链接, 这里只做简单的介绍,会用专门的章节进行介绍。
第一个参数Path表示的是一个路径,可以指向一个路径或者一个文件夹,也可以是绝对路径和相对路径。 例如
Paths.get("/Users/Johnny/Documents/hello.txt")
使用的就是一个绝对路径,Paths.get("/Users/Johnny", "Documents", "hello.txt")
使用的就是一个相对路径,相对路径把所有路径用目录分隔符拼接在一起。
第二个参数是写入的数据。
第三个参数是打开的方式,OpenOption是一个接口,NIO提供了一个StandardOpenOption枚举类,有READ, WRITE, APPEND, CREATE等。
public class CreateFile { public static void main(String[] args) { String data = "Hello world!"; try { Files.write(Paths.get("./Hello"), data.getBytes(), StandardOpenOption.CREATE); } catch (IOException e) { e.printStackTrace(); } }}
Paths在nuix系统上文件名没有大小写之分。
删除文件
上面我们学习了如何创建文件,接下来我们学习如何删除文件和文件夹。
-
删除文件和空目录File.delelte()
如果删除成功则返回true,文件或者空目录不存在就会返回false。
File file = new File("./test2");if (file.delete()) { System.out.println("删除成功");} else { System.out.println("删除失败");}
-
如果不是空目录需要遍历目录中的文件,删除文件,再删除目录
如果不是空文件需要把目录里面的文件先删除掉,然后再删除空的目录
File dir = new File("./test"); if (!dir.isDirectory()) { System.out.println("不是文件夹");} else {File[] files = dir.listFiles();for (File file: files) { System.out.println(file.getName()); file.delete();}System.out.println("删除文件夹"+ dir.delete());}
-
如果目录中有目录,目录中还有目录,多层级,就可以用NIO包中的
Files.walkFileTree(Path start, FileVisitor<? super Path> visitor)
循环遍历,逐个删除
第一个参数是路径。
第二个参数是一个接口,接口定义了四个方法用来指定当你访问一个节点之前、之中、之后、失败时应该采取什么行为。
public interface FileVisitor<T> { FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs) // 访问一个目录前要干啥 throws IOException; FileVisitResult postVisitDirectory(T dir, IOException exc) // 访问一个目录后要干啥 throws IOException; FileVisitResult visitFile(T file, BasicFileAttributes attrs) // 正在访问一个文件时要干啥 throws IOException; FileVisitResult visitFileFailed(T file, IOException exc) // 访问一个文件失败时要干啥 throws IOException;}
接口返回的是一个FileVisitResult枚举,分别是
CONTINUE:继续遍历
SKIP_SIBLINGS:继续遍历,但忽略当前节点的所有兄弟节点直接返回上一层继续遍历
SKIP_SUBTREE:继续遍历,但是忽略子目录,但是子文件还是会访问;
TERMINATE:终止遍历
遍历删除的代码如下:
public static void main(String[] args) { Path path = Paths.get("./test"); try { Files.walkFileTree(path, new SimpleFileVisitor<Path>(){ @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Files.delete(file); // 删除文件 return FileVisitResult.CONTINUE; //继续遍历 } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { Files.delete(dir); //删除目录 return FileVisitResult.CONTINUE; // 继续遍历 } @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { // TODO Auto-generated method stub return super.preVisitDirectory(dir, attrs); } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { // TODO Auto-generated method stub return super.visitFileFailed(file, exc); } }); } catch (IOException e) { e.printStackTrace(); } }
分割符
-
文件分隔符(File.separator):Windows 系统为
\
, unix为/
; -
文件分隔符(File.separatorChar):同上;
-
文件路径分割符(File.pathSeparator):Windows 系统为
;
, unix为:
;主要用于PATH,CLASSPATH等系统变量。 -
文件路径分割符(File.pathSeparatorChar):同上;
为了让代码不依赖系统,一般路径应该使用文件分隔符。
Path path = Paths.get("./test"); // 只适应于Unix系统Path path = Paths.get(".\test"); // 只适应于windows系统Path path = Paths.get("."+File.separator+"test"); // 不依赖于系统
重命名文件(移动文件)
可以用File.renameTo去重命名或者移动文件. Unix 系统中如果目标文件存在,则会用源文件覆盖目标文件。
public static void main(String[] args) { File sourceFile = new File("."+File.separator+"Source.txt"); File desFile = new File("." + File.separator + "Des.txt"); if (sourceFile.renameTo(desFile)) { // 必须判断是否成功,因为这个方法不会抛出异常 System.out.println("重命名成功"); } else { System.out.println("重命名失败"); } }
获取文件大小
-
IO包中的File.Length
可以用IO包中文件的length方法获取文件大小,计算的得到的结果单位是byte,需要注意的是确保不是目录和不存在的文件。
File file = new File("." + File.separator + "test.txt");System.out.println(file.length()); if (!file.exists() || file.isDirectory()) { System.out.println("不是文件,计算的长度不正确");}
-
NIO包中的FileChannel.size()
Path path = Paths.get("."+File.separator+"file.txt"); FileChannel fileChannel; try { fileChannel = FileChannel.open(path, StandardOpenOption.READ); // 打开 long fileSize = fileChannel.size(); System.out.println(fileSize + "bytes"); fileChannel.close();} catch (IOException e) { e.printStackTrace();}
获取文件扩展名
有时候需要根据不同的文件类型做不同的操作,我们可以通过文件名来获得文件的扩展名。
private static String getFileName(File file) { String fileName = file.getName(); if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) { // 如果有(.)且(.)不在第一个字符即不是隐藏文件 return fileName.substring(fileName.lastIndexOf(".") + 1); } return null;}
文件的创建时间、最后更改时间、最后访问时间
修改时间
File file = new File("." + File.separator + "file.txt"); long createTime = file.lastModified(); // 最后的修改时间戳--距离1970年一月一日的毫秒数,如果文件不存在则返回0 Calendar calendar = Calendar.getInstance(); // 由于Calendar是一个抽象类,不能用new实例化对象,getInstance获得了一个子类。https://www.cnblogs.com/huangminwen/p/6041168.html calendar.setTimeInMillis(createTime); // 根据毫秒数得到时间, SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //时间格式化 System.out.println(formatter.format(calendar.getTime())); //2018-09-30 10:57:29
Java7提供了Files.getFileAttributeView(可以获得最后修改时间,创建时间,文件大小,是否为目录等等)
private static String createTime(String fileName) { // 获取将要操作的文件 Path path = Paths.get(fileName); // 获取访问基本属性的BasicFileAttributeView // 两个参数:1,文件 2,指明一个类,BasicFileAttributeView是指访问文件的一些基本信息 BasicFileAttributeView attributeView = Files.getFileAttributeView(path, BasicFileAttributeView.class); BasicFileAttributes attributes; Calendar calendar = Calendar.getInstance(); try { attributes = attributeView.readAttributes(); // 获取信息 calendar.setTimeInMillis(attributes.creationTime().toMillis()); // 创建时间 } catch (IOException e) { e.printStackTrace(); calendar.setTimeInMillis(0); } SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return dateFormat.format(calendar.getTime());}
attributes.lastAccessTime() 最后获取时间
attributes.lastModifiedTime() 最后修改时间
attributes.size() 文件大小
getPath()、getAbsolutePath()、getCanonical()
-
getPath()返回定义时的路径,(就是你写什么路径,他就返回什么路径)
-
getAbsolutePath()返回绝对路径,但不会处理“.”和“..”的情况
-
getCanonicalPath()返回的是规范化的绝对路径,相当于将getAbsolutePath()中的“.”和“..”解析成对应的正确的路径
File file = new File("." + File.separator + "file.txt");System.out.println(file.getPath()); // ./file.txtSystem.out.println(file.getAbsolutePath()); // /Users/Johnny/Documents/./file.txttry { System.out.println(file.getCanonicalPath()); // /Users/Johnny/Documents/file.txt} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}
设置文件权限PosixFilePermission
java7以上用这种方法,可读性也非常强。
Set<PosixFilePermission> perms = new HashSet<PosixFilePermission>();// 添加用户权限perms.add(PosixFilePermission.OWNER_READ);perms.add(PosixFilePermission.OWNER_WRITE);perms.add(PosixFilePermission.OTHERS_EXECUTE);//添加群权限perms.add(PosixFilePermission.GROUP_READ);perms.add(PosixFilePermission.GROUP_WRITE);perms.add(PosixFilePermission.GROUP_EXECUTE);// 添加其他人员的权限perms.add(PosixFilePermission.OTHERS_READ);perms.add(PosixFilePermission.OTHERS_WRITE);perms.add(PosixFilePermission.OTHERS_EXECUTE); try { Files.setPosixFilePermissions(Paths.get("." + File.separator + "file.txt"), perms);} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}
复制文件
-
Stream的方式:创建一个源文件和一个目标文件,从源文件建立一个输入流,用输出流写入目标文件
private static void copyFileUsingStream(File source, File dest) { FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream(source); fileOutputStream = new FileOutputStream(dest); //定义一个字节数组,相当于缓存 byte[] buffer = new byte[1024]; int length; //循环读取 while ((length = fileInputStream.read(buffer)) != -1) { //把fileInputStream里的东西读到bytes数组里去 fileOutputStream.write(buffer, 0, length); // 把字节写入文件中 } } catch (IOException e) { e.printStackTrace(); } finally { //一定要关闭文件流, 并且关闭文件流必须放在finally里面 try { fileInputStream.close(); fileOutputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
-
NIO 的 FileChannel 的 transform()
private static void copyFileUsingFileChannel(File source, File dest) { FileChannel sourceChannel = null; FileChannel desChannel = null; try { sourceChannel = new FileInputStream(source).getChannel(); desChannel = new FileOutputStream(dest).getChannel(); desChannel.transferFrom(sourceChannel, 0, source.length()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { sourceChannel.close(); desChannel.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
-
Files的copy方法 — Java7 以上可以用,它使用FileSystemProvider来复制文件
try { Files.copy(source.toPath(), dest.toPath());} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}
读取文本内容
-
java.nio.file.Files
Files能够把内容读取出来变成一个byte数组,也可以把所有的行变成变成字符串数组。这些方法适合于把不是太大的文件读入内存中。
Path path = Paths.get("." + File.separator + "source.txt"); try { //Java7 读取所有的内容,默认以UTF-8编码读入文件,故文件的编码如果不是UTF-8,那么中文内容会出现乱字符 byte[] bytes = Files.readAllBytes(path); System.out.println(new String(bytes)); // Java8 List<String> lists = Files.readAllLines(path); System.out.println(lists); // [string1, string2, ...] } catch (IOException e) { e.printStackTrace();}
-
java.io.FileReader
可以通过FileReader获得BufferedReader,然后一行一行的读取文件。
File file = new File("." + File.separator + "source.txt"); try { FileReader reader = new FileReader(file); BufferedReader bufferedReader = new BufferedReader(reader); String line; while ((line = bufferedReader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}
-
java.io.BufferedReader
BufferedReader适合于大文件,且是线程安全的特点,默认的缓存大小是8KB。
File file = new File("." + File.separator + "source.txt");BufferedReader bufferedReader = null;try { FileInputStream inputStream = new FileInputStream(file); InputStreamReader reader = new InputStreamReader(inputStream); bufferedReader = new BufferedReader(reader); String line; while((line = bufferedReader.readLine()) != null){ //process the line System.out.println(line); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();} finally { try { bufferedReader.close(); // 关闭流 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }}
-
Files.BufferedReader
try { BufferedReader bufferedReader = Files.newBufferedReader(Paths.get("." + File.separator + "source.txt")); String line; while ((line = bufferedReader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}
-
Scanner
Path path = Paths.get("." + File.separator + "source.txt"); try { Scanner scanner = new Scanner(path); while (scanner.hasNextLine()) { String line = scanner.nextLine(); System.out.println(line); } scanner.close();} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}
打开文件(DeskTop)
java.awt.Desktop
这个类能打开文件,但是调用之前需要判断是否支持java.awt.Desktop.
File sourceFile = new File("."+File.separator+"source.txt");if (!Desktop.isDesktopSupported()) { System.out.println("Desktop is not supported"); return;} Desktop desktop = Desktop.getDesktop(); try { desktop.open(sourceFile); // 打开文件} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}
读取文本文件成为字符串
-
BufferedReader
String pathname = "." + File.separator + "source.txt"; try { FileReader fileReader = new FileReader(new File(pathname)); BufferedReader bufferedReader = new BufferedReader(fileReader); // bufferreader StringBuilder stringBuilder = new StringBuilder(); String line = null; String ls = System.getProperty("line.separator"); // 换行符 while ((line = bufferedReader.readLine()) != null) { // 读取的每行的数据 stringBuilder.append(line); // 写入数据 stringBuilder.append(ls); // 写入换行符 } stringBuilder.deleteCharAt(stringBuilder.length()-1); // 删除最后一个换行符 bufferedReader.close(); // 关流 String content = stringBuilder.toString(); // 字符 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}
-
FileInputStream
String pathname = "." + File.separator + "source.txt"; try { FileInputStream inputStream = new FileInputStream(new File(pathname)); byte[] bytes = new byte[10]; StringBuffer stringBuffer = new StringBuffer(); while (inputStream.read(bytes) != -1) { stringBuffer.append(new String(bytes)); bytes = new byte[10]; } inputStream.close(); String content = stringBuffer.toString(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}
-
Files
String content = new String(Files.readAllBytes(Paths.get(fileName)));
写文件(会覆盖原有内容)
-
FileWriter
File file = new File("." + File.separator + "des.txt"); String data = "Writed Data using FileWriter"; FileWriter fw = null;try { fw = new FileWriter(file); fw.write(data); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();} finally { try { fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }}
-
BufferedWriter
File file = new File("." + File.separator + "des.txt"); String data = "Write using bufferwriter"; FileWriter fWriter = null;BufferedWriter bWriter = null; try { fWriter = new FileWriter(file); bWriter = new BufferedWriter(fWriter); bWriter.write(data); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();} finally { try { bWriter.close(); fWriter.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
-
FileOutputStream
File file = new File("." + File.separator + "des.txt");String data = "Write using outputstream";FileOutputStream outputStream = null; try { outputStream = new FileOutputStream(file); outputStream.write(data.getBytes(), 0, data.length());} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();} finally { try { outputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
-
Files
String data = "Write using Files"; try { Files.write(Paths.get("." + File.separator + "des.txt"), data.getBytes());} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}
给文件增加内容
-
FileWriter
File file = new File("." + File.separator + "append.txt");FileWriter fr = null;try { fr = new FileWriter(file, true); // 第二个参数就是是否是增加 fr.write(System.getProperty("line.separator") + "Append String using file writer");} catch (IOException e) { e.printStackTrace();} finally { try { fr.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }}
-
BufferedWriter
File file = new File("." + File.separator + "append.txt"); String data = System.getProperty("line.separator") + "Append using bufferwriter"; FileWriter fWriter = null;BufferedWriter bWriter = null; try { fWriter = new FileWriter(file, true); bWriter = new BufferedWriter(fWriter); bWriter.write(data); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();} finally { try { bWriter.close(); fWriter.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
-
FileOutputStream
File file = new File("." + File.separator + "append.txt");String data = System.getProperty("line.separator") + "Append using outputstream";FileOutputStream outputStream = null; try { outputStream = new FileOutputStream(file, true); // 第二个参数就是是否是增加 outputStream.write(data.getBytes(), 0, data.length());} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();} finally { try { outputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
-
PrintWriter
File file = new File("." + File.separator + "append.txt");FileWriter fr = new FileWriter(file, true);BufferedWriter br = new BufferedWriter(fr);PrintWriter pr = new PrintWriter(br);pr.println(System.getProperty("line.separator") + "Append using printwriter");pr.close();br.close();fr.close();
在文件的指定位置读写(RandomAccessFile)
RandomAccessFile 是随机访问文件(包括读/写)的类,我们可以从指定的位置读取/写入文件数据。
-
读取数据
RandomAccessFile file = null;try { file = new RandomAccessFile("source.txt", "r"); // 第一个参数是文件路径,第二个参数r表示只读 file.seek(4); //游标移动四个位置 byte[] bytes = new byte[2]; // 两个字符的缓存 file.read(bytes); // 读入两个字符到缓存中 System.out.println(new String(bytes)); // 打印读取出来的两个字符 } catch (IOException e) { e.printStackTrace();} finally { try { file.close(); } catch (IOException e) { e.printStackTrace(); }}
-
在某处写入数据
RandomAccessFile file = null;try { file = new RandomAccessFile("source.txt", "rw"); // 第一个参数是文件路径,第二个参数rw表示读写 file.seek(4); //游标移动四个位置 file.write("Insert data".getBytes()); // 在第五个字符位置插入数据 } catch (IOException e) { e.printStackTrace();} finally { try { file.close(); } catch (IOException e) { e.printStackTrace(); }}
-
在文件末尾写入数据
file.seek(file.length()); // 把游标移动到文件的末尾,其他操作和插入操作一样
网络下载文件
-
InputStream
BufferedInputStream bis = null;FileOutputStream fos = null; try { //url代表一个绝对地址,URL对象直接指向这个资源 URL url = new URL("http://pic6.nipic.com/20100417/1304280_085257009323_2.jpg"); // url.openStream()返回为InputStream bis = new BufferedInputStream(url.openStream()); // 存入本地文件 fos = new FileOutputStream("." + File.separator + "meinv.jpg"); byte[] bytes = new byte[1024]; int count = 0; while ((count = bis.read(bytes)) != -1) { fos.write(bytes, 0, count); } } catch (IOException e) { e.printStackTrace();} finally { try { fos.close(); bis.close(); } catch (IOException e) { e.printStackTrace(); }}
-
NIO Channel
ReadableByteChannel rbc = null;FileOutputStream fos = null;try { //url代表一个绝对地址,URL对象直接指向这个资源 URL url = new URL("http://pic6.nipic.com/20100417/1304280_085257009323_2.jpg"); rbc = Channels.newChannel(url.openStream()); fos = new FileOutputStream("." + File.separator + "meinv.jpg"); fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); } catch (IOException e) { e.printStackTrace();} finally { try { fos.close(); rbc.close(); } catch (IOException e) { e.printStackTrace(); }}
压缩和解压缩文件
-
压缩文件
FileInputStream fis = null;FileOutputStream fos = null;GZIPOutputStream gos = null;try { fis = new FileInputStream("./meinv.jpg"); // 输入流 fos = new FileOutputStream("./Meinv.gz"); // 输出流 gos = new GZIPOutputStream(fos); // 压缩输出流 byte[] buffer = new byte[1024]; int count = 0; while ((count = fis.read(buffer)) != -1) { gos.write(buffer, 0, count); } } catch (IOException e) { e.printStackTrace();} finally { try { gos.close(); fos.close(); fis.close(); } catch (IOException e) { e.printStackTrace(); }}
-
解压缩文件
FileInputStream fis = null;GZIPInputStream gis = null;FileOutputStream fos = null; try { fis = new FileInputStream("./Meinv.gz"); gis = new GZIPInputStream(fis); fos = new FileOutputStream("./new.jpg"); byte[] buffer = new byte[1024]; int len; while ((len = gis.read(buffer)) != -1) { fos.write(buffer, 0, len); }} catch (IOException e) { e.printStackTrace();} finally { try { fos.close(); gis.close(); fis.close(); } catch (IOException e) { e.printStackTrace(); }}
创建临时文件
createTempFile(String prefix, String suffix, File directory) 可以用来创建临时文件,创建出来的文件名称是prefix+random_long_no+suffix
,如果suffix给null,则为.tmp
, 如果directory不给,则为系统默认的临时文件夹。
File tmpFile = File.createTempFile("data", null);
链接:https://www.jianshu.com/p/8c19bb551d15