File IO 0 File对象 File java.io.File
File 类可以用于表示文件和目录的信息,但是它不表示文件的内容。有大量相关的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 File(String pathname) File(URI uri) createNewFile() createTempFile(String prefix, String suffix) delete() deleteOnExit() exists() getAbsoluteFile() getAbsolutePath() getName() getPath() isFile() isDirectory() list() listFiles() mkdir() mkdirs() setReadOnly() setExecutable(boolean executable) setWritable(boolean writable) toPath() toURI()
RandomAccessFile java.io.RandomAccessFile
RandomAccessFile支持”随机访问”的方式,程序可以直接跳转到文件的任意地方来读写数据。
RandomAccessFile可以自由访问文件的任意位置。
RandomAccessFile允许自由定位文件记录指针。
RandomAccessFile只能读写文件而不是流。
1 2 3 4 5 6 7 RandomAccessFile(String name, String mode): RandomAccessFile(File file, String mode) read*() write*() long getFilePointer () :返回文件记录指针的当前位置。(native 方法)void seek (long pos) :将文件记录指针定位到pos位置。(调用本地方法seek0)
使用randomaccessfile插入内容。RandomAccessFile依然不能向文件的指定位置插入内容,如果直接将文件记录指针移动到中间某位置后开始输出,则新输出的内容会覆盖文件中原有的内容。如果需要向指定位置插入内容,程序需要先把插入点后面的内容读入缓冲区,等把需要插入的数据写入文件后,再将缓冲区的内容追加到文件后面。
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 public static void insert (String fileName, long pos, String insertContent) throws IOException { RandomAccessFile raf = null ; File tmp = File.createTempFile("tmp" , null ); FileOutputStream tmpOut = null ; FileInputStream tmpIn = null ; tmp.deleteOnExit(); try { raf = new RandomAccessFile (fileName, "rw" ); tmpOut = new FileOutputStream (tmp); tmpIn = new FileInputStream (tmp); raf.seek(pos); byte [] bbuf = new byte [64 ]; int hasRead = 0 ; while ((hasRead = raf.read(bbuf)) > 0 ) { tmpOut.write(bbuf, 0 , hasRead); } raf.seek(pos); raf.write(insertContent.getBytes()); while ((hasRead = tmpIn.read(bbuf)) > 0 ) { raf.write(bbuf, 0 , hasRead); } } finally { if (raf != null ) { raf.close(); } } }
NIO:Files
1 列出:list BIO 递归地列出一个目录下所有文件:
1 2 3 4 5 6 7 8 9 10 11 12 public static void listAllFiles (File dir) { if (dir == null || !dir.exists()) { return ; } if (dir.isFile()) { System.out.println(dir.getName()); return ; } for (File file : dir.listFiles()) { listAllFiles(file); } }
从 Java7 开始,可以使用 Paths 和 Files 代替 File。
2 复制:copy BIO 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 import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class CopyDemo { public static void main (String[] args) throws IOException { FileInputStream fis = new FileInputStream ("01.rmvb" ); FileOutputStream fos = new FileOutputStream ("01_cp.rmvb" ); int d; long start = System.currentTimeMillis(); while ((d = fis.read()) != -1 ) { fos.write(d); } long end = System.currentTimeMillis(); System.out.println("复制完毕!耗时:" + (end - start) + "ms" ); fis.close(); fos.close(); } } ```java public static void copyFile (String src, String dist) throws IOException { FileInputStream in = new FileInputStream (src); FileOutputStream out = new FileOutputStream (dist); byte [] buffer = new byte [20 * 1024 ]; int cnt; while ((cnt = in.read(buffer, 0 , buffer.length)) != -1 ) { out.write(buffer, 0 , cnt); } in.close(); out.close(); }
NIO 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 package com.howtodoinjava.examples.io; import java.io.File;import java.io.IOException;import java.nio.file.Files;import java.nio.file.StandardCopyOption; public class DirectoryCopyExample { public static void main (String[] args) throws IOException { File sourceFolder = new File ("c:\\temp" ); File destinationFolder = new File ("c:\\tempNew" ); copyFolder(sourceFolder, destinationFolder); } private static void copyFolder (File sourceFolder, File destinationFolder) throws IOException { if (sourceFolder.isDirectory()) { if (!destinationFolder.exists()) { destinationFolder.mkdir(); System.out.println("Directory created :: " + destinationFolder); } String files[] = sourceFolder.list(); for (String file : files) { File srcFile = new File (sourceFolder, file); File destFile = new File (destinationFolder, file); copyFolder(srcFile, destFile); } } else { Files.copy(sourceFolder.toPath(), destinationFolder.toPath(), StandardCopyOption.REPLACE_EXISTING); System.out.println("File copied :: " + destinationFolder); } } } Output: Directory created :: c:\tempNew File copied :: c:\tempNew\testcopied.txt File copied :: c:\tempNew\testoriginal.txt File copied :: c:\tempNew\testOut.txt
common-util 1 2 3 4 5 6 7 8 9 10 11 private static void fileCopyUsingApacheCommons () throws IOException { File fileToCopy = new File ("c:/temp/testoriginal.txt" ); File newFile = new File ("c:/temp/testcopied.txt" ); FileUtils.copyFile(fileToCopy, newFile); IOUtils.copy(new FileInputStream (fileToCopy), new FileOutputStream (newFile)); }
3 删除:delete NIO 1 2 3 4 5 6 7 8 9 10 11 12 public class DeleteDirectoryNIOWithStream { public static void main (String[] args) { Path dir = Paths.get("c:/temp/innerDir" ); Files.walk(dir) .sorted(Comparator.reverseOrder()) .map(Path::toFile) .forEach(File::delete); } }
apache commons-io 1 2 3 4 5 6 7 8 9 10 11 12 public class DeleteDirectoryNIOWithStream { public static void main(String[] args) { Path dir = Paths.get("c:/temp/innerDir"); Files.walk(dir) .sorted(Comparator.reverseOrder()) .map(Path::toFile) .forEach(File::delete); } }
4 创建create BIO:createNewFile File.createNewFile()方法创建新文件。 此方法返回布尔值–
如果文件创建成功,则返回true 。
如果文件已经存在或操作由于某种原因失败,则返回false 。
此方法不会像文件中写任何数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 File file = new File ("c://temp//testFile1.txt" ); if (file.createNewFile()){ System.out.println("File is created!" ); } else { System.out.println("File already exists." ); } FileWriter writer = new FileWriter (file);writer.write("Test data" ); writer.close();
BIO:FileOutputStream FileOutputStream.write()方法自动创建一个新文件并向其中写入内容 。
1 2 3 4 5 6 String data = "Test data" ; FileOutputStream out = new FileOutputStream ("c://temp//testFile2.txt" ); out.write(data.getBytes()); out.close();
NIO Files.write()是创建文件的最佳方法,如果您尚未使用它,则应该是将来的首选方法。
此方法将文本行写入文件 。 每行都是一个char序列,并按顺序写入文件,每行由平台的line separator终止。
1 2 3 4 5 6 7 8 9 10 11 12 String data = "Test data" ;Files.write(Paths.get("c://temp//testFile3.txt" ), data.getBytes()); List<String> lines = Arrays.asList("1st line" , "2nd line" ); Files.write(Paths.get("file6.txt" ), lines, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.APPEND);
5 写入:wrirte&append
append模式,使用BufferedWritter , PrintWriter , FileOutputStream和Files类将内容追加到java中的 Files 。 在所有示例中,在打开要写入的文件时,您都传递了第二个参数true ,表示该文件以append mode打开
BIO:BufferedWriter 通过BufferedWriter,进行更少的IO操作,提高了性能。
1 2 3 4 5 6 7 8 public static void usingBufferedWritter () throws IOException { String fileContent = "Hello Learner !! Welcome to howtodoinjava.com." ; BufferedWriter writer = new BufferedWriter (new FileWriter ("c:/temp/samplefile1.txt" )); writer.write(fileContent); writer.close(); }
BIO:PrintWriter 使用PrintWriter将格式化的文本写入文件。
1 2 3 4 5 6 7 8 9 10 public static void usingPrintWriter () throws IOException { String fileContent = "Hello Learner !! Welcome to howtodoinjava.com." ; FileWriter fileWriter = new FileWriter ("c:/temp/samplefile3.txt" ); PrintWriter printWriter = new PrintWriter (fileWriter); printWriter.print(fileContent); printWriter.printf("Blog name is %s" , "howtodoinjava.com" ); printWriter.close(); }
BIO:FileOutputStream 使用FileOutputStream 将二进制数据写入文件 。 FileOutputStream用于写入原始字节流,例如图像数据。 要编写字符流,请考虑使用FileWriter 。
1 2 3 4 5 6 7 8 9 10 public static void usingFileOutputStream () throws IOException { String fileContent = "Hello Learner !! Welcome to howtodoinjava.com." ; FileOutputStream outputStream = new FileOutputStream ("c:/temp/samplefile4.txt" ); byte [] strToBytes = fileContent.getBytes(); outputStream.write(strToBytes); outputStream.close(); }
BIO:DataOutputStream DataOutputStream允许应用程序以可移植的方式将原始Java数据类型写入输出流。 然后,应用程序可以使用数据输入流来读回数据。
1 2 3 4 5 6 7 8 9 10 public static void usingDataOutputStream () throws IOException { String fileContent = "Hello Learner !! Welcome to howtodoinjava.com." ; FileOutputStream outputStream = new FileOutputStream ("c:/temp/samplefile5.txt" ); DataOutputStream dataOutStream = new DataOutputStream (new BufferedOutputStream (outputStream)); dataOutStream.writeUTF(fileContent); dataOutStream.close(); }
NIO:FileChannel FileChannel可用于读取,写入,映射和操作文件。 如果要处理大文件,则FileChannel可能比标准IO快。
文件通道可以安全地供多个并发线程使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static void usingFileChannel () throws IOException { String fileContent = "Hello Learner !! Welcome to howtodoinjava.com." ; RandomAccessFile stream = new RandomAccessFile ("c:/temp/samplefile6.txt" , "rw" ); FileChannel channel = stream.getChannel(); byte [] strBytes = fileContent.getBytes(); ByteBuffer buffer = ByteBuffer.allocate(strBytes.length); buffer.put(strBytes); buffer.flip(); channel.write(buffer); stream.close(); channel.close(); }
NIO:Files静态方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static void usingPath () throws IOException { String fileContent = "Hello Learner !! Welcome to howtodoinjava.com." ; Path path = Paths.get("c:/temp/samplefile7.txt" ); Files.write(path, fileContent.getBytes()); } public static void usingPath () throws IOException { String textToAppend = "\r\n Happy Learning !!" ; Path path = Paths.get("c:/temp/samplefile.txt" ); Files.write(path, textToAppend.getBytes(), StandardOpenOption.APPEND); }
6 读取:read BIO:BufferedReader按行读 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private static String usingBufferedReader (String filePath) { StringBuilder contentBuilder = new StringBuilder (); try (BufferedReader br = new BufferedReader (new FileReader (filePath))) { String sCurrentLine; while ((sCurrentLine = br.readLine()) != null ) { contentBuilder.append(sCurrentLine).append("\n" ); } } catch (IOException e) { e.printStackTrace(); } return contentBuilder.toString();
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 import java.io.File;import java.io.FileInputStream; public class ContentToByteArrayExample { public static void main (String[] args) { File file = new File ("C:/temp/test.txt" ); readContentIntoByteArray(file); } private static byte [] readContentIntoByteArray(File file) { FileInputStream fileInputStream = null ; byte [] bFile = new byte [(int ) file.length()]; try { fileInputStream = new FileInputStream (file); fileInputStream.read(bFile); fileInputStream.close(); for (int i = 0 ; i < bFile.length; i++) { System.out.print((char ) bFile[i]); } } catch (Exception e) { e.printStackTrace(); } return bFile; } }
NIO:Files按行读 lines()方法从文件中读取所有行以进行流传输,并在stream被消耗时延迟填充。 使用指定的字符集将文件中的字节解码为字符。 readAllBytes()方法reads all the bytes from a file 。 该方法可确保在读取所有字节或引发I / O错误或其他运行时异常时关闭文件。
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 import java.io.IOException;import java.nio.charset.StandardCharsets;import java.nio.file.Files;import java.nio.file.Paths;import java.util.stream.Stream; public class ReadFileToString { public static void main (String[] args) { String filePath = "c:/temp/data.txt" ; System.out.println( readLineByLineJava8( filePath ) ); } private static String readLineByLineJava8 (String filePath) { StringBuilder contentBuilder = new StringBuilder (); try (Stream<String> stream = Files.lines( Paths.get(filePath), StandardCharsets.UTF_8)) { stream.forEach(s -> contentBuilder.append(s).append("\n" )); } catch (IOException e) { e.printStackTrace(); } return contentBuilder.toString(); } }
NIO:读取所有字节 读取所有字节后,我们将这些字节传递给String类构造函数以创建一个字符串
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 import java.io.IOException;import java.nio.file.Files;import java.nio.file.Paths; public class ReadFileToString { public static void main (String[] args) { String filePath = "c:/temp/data.txt" ; System.out.println( readAllBytesJava7( filePath ) ); } private static String readAllBytesJava7 (String filePath) { String content = "" ; try { content = new String ( Files.readAllBytes( Paths.get(filePath) ) ); } catch (IOException e) { e.printStackTrace(); } return content; } }
commons-io 1 2 3 4 5 byte [] org.apache.commons.io.FileUtils.readFileToByteArray(File file) byte [] org.apache.commons.io.IOUtils.toByteArray(InputStream input)
7 Properties 任何复杂的应用程序都需要某种配置。 有时我们需要将此配置为只读(通常在应用程序启动时读取),有时(或很少)我们需要写回或更新这些属性配置文件上的内容。
在这个简单易用的教程中,学习使用Properties.load()方法读取Java中的Properties.load() 文件 。 然后,我们将使用Properties.setProperty()方法将新属性写入file 。
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 import java.io.IOException;import java.io.InputStream;import java.util.Properties;import java.util.Set; public class PropertiesCache { private final Properties configProp = new Properties (); private PropertiesCache () { InputStream in = this .getClass().getClassLoader().getResourceAsStream("app.properties" ); System.out.println("Read all properties from file" ); try { configProp.load(in); } catch (IOException e) { e.printStackTrace(); } } private static class LazyHolder { private static final PropertiesCache INSTANCE = new PropertiesCache (); } public static PropertiesCache getInstance () { return LazyHolder.INSTANCE; } public String getProperty (String key) { return configProp.getProperty(key); } public Set<String> getAllPropertyNames () { return configProp.stringPropertyNames(); } public boolean containsKey (String key) { return configProp.containsKey(key); } }
补充:静态内部类与懒汉式单例模式 这种方式是当被调用getInstance()时才去加载静态内部类LazyHolder,LazyHolder在加载过程中会实例化一个静态的Singleton,因为利用了classloader的机制来保证初始化instance时只有一个线程,所以Singleton肯定只有一个,是线程安全的,这种比上面1、2都好一些,既实现了线程安全,又避免了同步带来的性能影响。
1 2 3 4 5 6 7 8 9 public class Singleton { private static class LazyHolder { private static final Singleton INSTANCE = new Singleton (); } private Singleton () {} public static final Singleton getInstance () { return LazyHolder.INSTANCE; } }
8 Resource File ClassLoader引用从应用程序的资源包中读取文件。加载上下文环境中的文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.howtodoinjava.demo; import java.io.File;import java.io.IOException;import java.nio.file.Files; public class ReadResourceFileDemo { public static void main (String[] args) throws IOException { String fileName = "config/sample.txt" ; ClassLoader classLoader = new ReadResourceFileDemo ().getClass().getClassLoader(); File file = new File (classLoader.getResource(fileName).getFile()); System.out.println("File Found : " + file.exists()); String content = new String (Files.readAllBytes(file.toPath())); System.out.println(content); } }
在spring中可以这样 1 2 3 4 5 6 7 8 9 File file = ResourceUtils.getFile("classpath:config/sample.txt" ) System.out.println("File Found : " + file.exists()); String content = new String (Files.readAllBytes(file.toPath()));System.out.println(content);
10 读写utf8数据 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 import java.io.BufferedWriter;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;import java.io.UnsupportedEncodingException;import java.io.Writer; public class WriteUTF8Data { public static void main (String[] args) { try { File fileDir = new File ("c:\\temp\\test.txt" ); Writer out = new BufferedWriter (new OutputStreamWriter (new FileOutputStream (fileDir), "UTF8" )); out.append("Howtodoinjava.com" ).append("\r\n" ); out.append("UTF-8 Demo" ).append("\r\n" ); out.append("क्षेत्रफल = लंबाई * चौड़ाई" ).append("\r\n" ); out.flush(); out.close(); } catch (UnsupportedEncodingException e) { System.out.println(e.getMessage()); } catch (IOException e) { System.out.println(e.getMessage()); } catch (Exception e) { System.out.println(e.getMessage()); } } }
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 import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException; public class ReadUTF8Data { public static void main (String[] args) { try { File fileDir = new File ("c:\\temp\\test.txt" ); BufferedReader in = new BufferedReader ( new InputStreamReader ( new FileInputStream (fileDir), "UTF8" )); String str; while ((str = in.readLine()) != null ) { System.out.println(str); } in.close(); } catch (UnsupportedEncodingException e) { System.out.println(e.getMessage()); } catch (IOException e) { System.out.println(e.getMessage()); } catch (Exception e) { System.out.println(e.getMessage()); } } }
11 从控制台读取输入 console对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private static void usingConsoleReader () { Console console = null ; String inputString = null ; try { console = System.console(); if (console != null ) { inputString = console.readLine("Name: " ); System.out.println("Name entered : " + inputString); } } catch (Exception ex) { ex.printStackTrace(); } }
System.in封装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 private static void usingBufferedReader () { System.out.println("Name: " ); try { BufferedReader bufferRead = new BufferedReader (new InputStreamReader (System.in)); String inputString = bufferRead.readLine(); System.out.println("Name entered : " + inputString); } catch (IOException ex) { ex.printStackTrace(); } }
更加复杂的Scanner 1 2 3 4 5 6 7 8 9 10 private static void usingScanner () { System.out.println("Name: " ); Scanner scanIn = new Scanner (System.in); String inputString = scanIn.nextLine(); scanIn.close(); System.out.println("Name entered : " + inputString); }
12 将String转换成输入流 1 2 3 4 5 6 7 8 9 10 11 12 13 import java.io.ByteArrayInputStream;import java.io.InputStream; public class ConvertStringToInputStreamExample { public static void main (String[] args) { String sampleString = "howtodoinjava.com" ; InputStream stream = new ByteArrayInputStream (sampleString.getBytes()); } }
apach.IOUtils 1 2 3 4 5 6 7 8 9 10 11 12 13 import java.io.InputStream;import org.apache.commons.io.IOUtils; public class ConvertStringToInputStreamExample { public static void main (String[] args) { String sampleString = "howtodoinjava.com" ; InputStream stream = IOUtils.toInputStream(sampleString); } }