• Java读取文件的N种方法


    1.概述
    在这篇文章里, 我们将探索不同的方式从文件中读取数据

    首先, 学习通过标准的的Java类,从classpath、URL或者Jar中加载文件。

    然后,学习通用BufferedReader, Scanner, StreamTokenizer, DataInputStream, SequenceInputStream, FileChannel读取文件内容。也会讨论如何读取UTF-8编码的文件。

    最后,学习Java7和Java8中新的加载和读取文件的技术。

    2.准备
    2.1 输入文件

    这篇文章的很多示例,从名为fileTest.txt的文件读取文本内容,文件包含

    Hello,World!
    有少量示例, 我们会读取不同的文件, 示例中会有说明。

    2.2 辅助方法

    很多示例都会用到共用的方法readFromInputStream, 该方法将InputStream转化String

       

    1. private String readFromInputStream(InputStream inputStream)
    2.             throws IOException {
    3.         StringBuilder resultStringBuilder = new StringBuilder();
    4.         try (BufferedReader br
    5.                      = new BufferedReader(new InputStreamReader(inputStream))) {
    6.             String line;
    7.             while ((line = br.readLine()) != null) {
    8.               resultStringBuilder.append(line).append("\n");
    9.             }
    10.         }
    11.         return resultStringBuilder.toString();
    12.     } 


    3.从Classpath读取文件
    3.1 使用标准Java

    从src/main/resources读取文件fileTest.txt

       

    1. @Test
    2.     public void test() throws IOException {
    3.         String expectedData = "Hello,World!";
    4.         Class clazz = ReadFileTest.class;
    5.         InputStream inputStream = clazz.getResourceAsStream("/fileTest.txt");
    6.         String data = readFromInputStream(inputStream);
    7.  
    8.         Assert.assertThat(data, containsString(expectedData));
    9.     }


    在上面的代码中,我们通过当前类的getResourceAsStream方法加载文件,入参是绝对路径。

    ClassLoader中相同的方法也可以使用。

    ClassLoader classLoader = getClass().getClassLoader();
    InputStream inputStream = classLoader.getResourceAsStream("fileTest.txt");
    String data = readFromInputStream(inputStream);
    这两种方法的主要区别是, 当前类的ClassLoader的getResourceAsStream方法,入参路径是从classpath开始。

    而类实例的入参是相对于包路径,但路径开始使用'/'符号, 也是绝对路径。

    特别要注意的是, 文件打开读取完数据后, 始终需要关闭

    inputStream.close();
    3.2 使用commons-io库

    另一个比较常用的方法是使用commons-io包里的FileUtils.readFileToString方法。

           

    1.             commons-io
    2.             commons-io
    3.             1.4
    4.        
    5.     @Test
    6.     public void useCommonIO() throws IOException {
    7.         String expectedData = "Hello,World!";
    8.  
    9.         ClassLoader classLoader = getClass().getClassLoader();
    10.         File file = new File(classLoader.getResource("fileTest.txt").getFile());
    11.         String data = FileUtils.readFileToString(file, "UTF-8");
    12.  
    13.         assertEquals(expectedData, data.trim());
    14.     }


    该方法入参是File对象。这个工具类的优点是不用编码InputStream实例的相关代码。
    这个库还提供了IOUtils类。

       

    1. @Test
    2.     public void useCommonIO2() throws IOException {
    3.         String expectedData = "Hello,World!";
    4.  
    5.         FileInputStream fis = new FileInputStream("src/test/resources/fileTest.txt");
    6.         String data = IOUtils.toString(fis, "UTF-8");
    7.  
    8.         assertEquals(expectedData, data.trim());
    9.     }
    10. 4.BufferedReader
    11. @Test
    12. public void bufferedReader() throws IOException {
    13.     String expected_value = "Hello,World!";
    14.     String file ="src/test/resources/fileTest.txt";
    15.  
    16.     BufferedReader reader = new BufferedReader(new FileReader(file));
    17.     String currentLine = reader.readLine();
    18.     reader.close();
    19.  
    20.     assertEquals(expected_value, currentLine);
    21. }


    当读取结束的时候, reader.readLine()会返回null

    5.Java NIO
    NIO是在JDK7中添加。

    5.1读取小文件

    首先看一下关于Files.readAllLines的示例

       

    1. @Test
    2.     public void readSmallFile()  throws IOException {
    3.         String expected_value = "Hello,World!";
    4.  
    5.         Path path = Paths.get("src/test/resources/fileTest.txt");
    6.  
    7.         String read = Files.readAllLines(path).get(0);
    8.         assertEquals(expected_value, read);
    9.     }


    入参Path对象,Path可以认为是java.io.File的升级版本,提供一些额外的功能。

    如果读取的是二进制文件,可以使用Files.readAllBytes()方法

    5.2读取大文件

    如果想要读取大文件, 我们可以使用Files类和BufferedReader类。

       

    1. @Test
    2.     public void readLargeFile() throws IOException {
    3.         String expected_value = "Hello,World!";
    4.  
    5.         Path path = Paths.get("src/test/resources/fileTest.txt");
    6.  
    7.         BufferedReader reader = Files.newBufferedReader(path);
    8.         String line = reader.readLine();
    9.         assertEquals(expected_value, line);
    10.     }


    5.3Files.lines

    在JDK8中,Files类增加了lines方法,这个方法将返回Stream。跟文件操作一样,Stream需要显式调用的close()。Files API提供了很多简单读取文件的方法。

    6.Scanner
    下面我们将使用Scanner读取文件,使用逗号(,)作为定界符(delimiter)。

    1. @Test
    2. public void whenReadWithScanner_thenCorrect()
    3.         throws IOException {
    4.     String file = "src/test/resources/fileTest.txt";
    5.     Scanner scanner = new Scanner(new File(file));
    6.     scanner.useDelimiter(",");
    7.  
    8.     assertTrue(scanner.hasNext());
    9.     assertEquals("Hello", scanner.next());
    10.     assertEquals("World!", scanner.next());
    11.  
    12.     scanner.close();
    13. }


    Scanner默认的定界符是空格。它适用于从控制台读取输入或者内容有固定定界符的内容时。

    7.StreamTokenizer
    tokenizer会指出下一个token的类型,String或Number。

    tokenizer.nval - 如果类型为Number时,读取该字段

    tokenizer.sval - 如果类型为String时,读取该字段

    1. @Test
    2. public void readWithTokenize()
    3.         throws IOException {
    4.     String file = "src/test/resources/fileTestTokenizer.txt";
    5.     FileReader reader = new FileReader(file);
    6.     StreamTokenizer tokenizer = new StreamTokenizer(reader);
    7.  
    8.     //  1
    9.     tokenizer.nextToken();
    10.     assertEquals(StreamTokenizer.TT_WORD, tokenizer.ttype);
    11.     assertEquals("Hello", tokenizer.sval);
    12.  
    13.     //  2
    14.     tokenizer.nextToken();
    15.     assertEquals(StreamTokenizer.TT_NUMBER, tokenizer.ttype);
    16.     assertEquals(1, tokenizer.nval, 0.0000001);
    17.  
    18.     //  3
    19.     tokenizer.nextToken();
    20.     assertEquals(StreamTokenizer.TT_EOF, tokenizer.ttype);
    21.     reader.close();
    22. }

    8.DataInputStream
    如果要读取二进制文件或者原生数据,可以使用DataInputStream

    1. @Test
    2. public void whenReadWithDataInputStream() throws IOException {
    3.     String expectedValue = "Hello,World!";
    4.     String file ="src/test/resources/fileTest.txt";
    5.     String result = null;
    6.  
    7.     DataInputStream reader = new DataInputStream(new FileInputStream(file));
    8.     int nBytesToRead = reader.available();
    9.     if(nBytesToRead > 0) {
    10.         byte[] bytes = new byte[nBytesToRead];
    11.         reader.read(bytes);
    12.         result = new String(bytes);
    13.     }
    14.  
    15.     assertEquals(expectedValue, result);
    16. }
    17. package com.pl;
    18. import java.io.DataInputStream;
    19. import java.io.FileInputStream;
    20. import java.io.IOException;
    21. public class ccs_2 {
    22. public static void main(String[] args) throws IOException {
    23. String expectedValue = "";
    24. String file = "C:\\Users\\Administrator\\Desktop\\1.txt";
    25. //result = null;
    26. DataInputStream reader = new DataInputStream(new FileInputStream(file));
    27. int nBytesToRead = reader.available();
    28. if (nBytesToRead > 0) {
    29. byte[] bytes = new byte[nBytesToRead];
    30. reader.read(bytes);
    31. expectedValue = new String(bytes);
    32. }
    33. System.out.printf("\n====" + expectedValue);
    34. }
    35. }

    9.FileChannel
    如果读取的是一个大文件,FileChannel速度会超过standard IO。

    1. @Test
    2. public void whenReadWithFileChannel()
    3.         throws IOException {
    4.     String expected_value = "Hello,World!";
    5.     String file = "src/test/resources/fileTest.txt";
    6.     RandomAccessFile reader = new RandomAccessFile(file, "r");
    7.     FileChannel channel = reader.getChannel();
    8.  
    9.     int bufferSize = 1024;
    10.     if (bufferSize > channel.size()) {
    11.         bufferSize = (int) channel.size();
    12.     }
    13.     ByteBuffer buff = ByteBuffer.allocate(bufferSize);
    14.     channel.read(buff);
    15.     buff.flip();
    16.  
    17.     assertEquals(expected_value, new String(buff.array()));
    18.     channel.close();
    19.     reader.close();
    20. }
    21. package com.pl;
    22. import java.io.IOException;
    23. import java.io.RandomAccessFile;
    24. import java.nio.ByteBuffer;
    25. import java.nio.channels.FileChannel;
    26. public class ccs_2 {
    27. public static void main(String[] args) throws IOException {
    28. //throws IOException {
    29. String expected_value = "";
    30. String file = "C:\\Users\\Administrator\\Desktop\\1.txt";
    31. RandomAccessFile reader = new RandomAccessFile(file, "r");
    32. FileChannel channel = reader.getChannel();
    33. int bufferSize = 1024;
    34. if (bufferSize > channel.size()) {
    35. bufferSize = (int) channel.size();
    36. }
    37. //}
    38. ByteBuffer buff = ByteBuffer.allocate(bufferSize);
    39. channel.read(buff);
    40. buff.flip();
    41. expected_value = new String(buff.array());
    42. //assertEquals(expected_value, new String(buff.array()));
    43. channel.close();
    44. reader.close();
    45. System.out.printf("\n====" + expected_value);
    46. }
    47. }

    10.读取utf-8编码的文件
     

    1. @Test
    2. public void whenReadUTFEncodedFile()
    3.         throws IOException {
    4.     String expected_value = "你好,世界!";
    5.     String file = "src/test/resources/fileTestUtf8.txt";
    6.     BufferedReader reader = new BufferedReader
    7.             (new InputStreamReader(new FileInputStream(file), "UTF-8"));
    8.     String currentLine = reader.readLine();
    9.     reader.close();
    10.  
    11.     assertEquals(expected_value, currentLine);
    12. }
    13. package com.pl;
    14. import java.io.BufferedReader;
    15. import java.io.FileInputStream;
    16. import java.io.IOException;
    17. import java.io.InputStreamReader;
    18. public class ccs_2 {
    19. public static void main(String[] args) throws IOException {
    20. // File file = new File("C:\\Program Files");
    21. //
    22. // //System.out.println(file.list());
    23. // String[] A = file.list();
    24. // for (int i = 0; i < A.length; i++) {
    25. // System.out.printf("\n=====" + A[i]);
    26. // }
    27. String expected_value = "你好,世界!";
    28. String file = "C:\\Users\\Administrator\\Desktop\\1.txt";
    29. BufferedReader reader = new BufferedReader
    30. (new InputStreamReader(new FileInputStream(file), "UTF-8"));
    31. String currentLine = reader.readLine();
    32. reader.close();
    33. System.out.printf("\n====" + currentLine);
    34. }
    35. }


    11.从URL读取数据

    1. @Test
    2. public void readFromURL() throws IOException {
    3.     URL urlObject = new URL("https://www.baidu.com");
    4.     URLConnection urlConnection = urlObject.openConnection();
    5.     InputStream inputStream = urlConnection.getInputStream();
    6.     String data = readFromInputStream(inputStream);
    7. }


    12.从jar包中读取文件
    我们的目标是读取junit-4.12.jar包中的LICENSE-junit.txt文件。clazz只需要这个Jar中的类就行。

    1. @Test
    2. public void readFromJar() throws IOException {
    3.     String expectedData = "Eclipse Public License";
    4.  
    5.     Class clazz = Test.class;
    6.     InputStream inputStream = clazz.getResourceAsStream("/LICENSE-junit.txt");
    7.     String data = readFromInputStream(inputStream);
    8.  
    9.     Assert.assertThat(data, containsString(expectedData));
    10. }

  • 相关阅读:
    RabbitMQ-高级篇-黑马程序员
    五)Stable Diffussion使用教程:文生图之高清修复
    测试岗面试,一份好的简历总可以让人眼前一亮
    Java复习六:内部类+异常处理
    【开源打印组件】vue-plugin-hiprint初体验
    net-java-php-python-阿克苏水果销售管理计算机毕业设计程序
    企业如何实现财务无纸化?票档一体化建设势在必行
    人工智能指数报告2023
    debian系和redhat系如何列出deb包和rpm包中包含的文件列表
    Go 代码包与引入:如何有效组织您的项目
  • 原文地址:https://blog.csdn.net/webxscan/article/details/133958556