我已经使用下面的习语一段时间了。至少在我访问过的网站上,它似乎是使用最广泛的。

是否有更好/不同的方法可以将文件读入Java字符串中?

private String readFile(String file) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader (file));
    String         line = null;
    StringBuilder  stringBuilder = new StringBuilder();
    String         ls = System.getProperty("line.separator");

    try {
        while((line = reader.readLine()) != null) {
            stringBuilder.append(line);
            stringBuilder.append(ls);
        }

        return stringBuilder.toString();
    } finally {
        reader.close();
    }
}


评论

谁能以一种非常简单的方式向我解释NIO是什么?每次我读到它,我都会迷失在频道的第n个提及中:(

请记住,不能保证文件中的行分隔符不必与系统的行分隔符相同。

您能否最后插入一个合适的尝试关闭读者?有人可能会实际使用此示例,并在其代码中引入一个错误。

上面的代码有一个在最后一行添加额外的新行char的错误。它应该类似于以下if(line = reader.readLine())!= null){stringBuilder.append(line); } while(line = reader.readLine()!! = null){stringBuilder.append(ls); stringBuilder.append(line); }

Java 7引入了byte [] Files.readAllBytes(file);对于那些建议“单线”扫描仪解决方案的用户:不需要关闭它吗?

#1 楼

读取文件中的所有文本
Java 11添加了readString()方法以将小文件读取为String,并保留行终止符:
String content = Files.readString(path, StandardCharsets.US_ASCII);

对于Java 7和11之间的版本,这是一个紧凑的协议,实用的方法,包装在实用程序方法中:
static String readFile(String path, Charset encoding)
  throws IOException
{
  byte[] encoded = Files.readAllBytes(Paths.get(path));
  return new String(encoded, encoding);
}

从文件中读取文本行
Java 7添加了一种便捷方法,将文件读取为文本行,表示为List<String> 。这种方法是“有损的”,因为从每行的末尾剥离了行分隔符。
List<String> lines = Files.readAllLines(Paths.get(path), encoding);

Java 8添加了Files.lines()方法来生成Stream<String>。同样,该方法是有损耗的,因为剥去了行分隔符。如果在读取文件时遇到IOException,则会将其包装在UncheckedIOException中,因为Stream不接受引发已检查异常的lambda。
try (Stream<String> lines = Files.lines(path, encoding)) {
  lines.forEach(System.out::println);
}

Stream确实需要进行close()调用;这个在API上的记录很少,我怀疑很多人甚至没有注意到Stream有一个close()方法。请确保使用如图所示的ARM模块。
如果您使用的不是文件源,则可以在lines()中使用BufferedReader方法。
内存利用率
第一种方法,用于保留换行符,可能会临时需要几倍于文件大小的内存,因为在短时间内,原始文件内容(字节数组)和已解码字符(即使编码为8位,每个字符均为16位)在文件中)立即驻留在内存中。将安全文件应用于相对于可用内存较小的文件是最安全的。
第二种方法,读取行通常会提高内存效率,因为用于解码的输入字节缓冲区不需要包含整个文件。但是,它仍然不适用于相对于可用内存而言非常大的文件。
为了读取大文件,您需要为程序提供不同的设计,即从流中读取文本块,对其进行处理,然后再移至下一个,重新使用相同的固定大小的内存块。在此,“大”取决于计算机规格。如今,此阈值可能是许多GB的RAM。如果输入的“记录”恰好是单独的行,则使用Stream<String>的第三种方法是执行此操作的一种方法。 (使用readLine()BufferedReader方法等效于此方法。)
字符编码
原始文章中的示例缺少的一件事是字符编码。在某些特殊情况下,平台默认值是您所需要的,但是很少见,因此您应该能够证明自己的选择。
StandardCharsets类为所有Java运行时所需的编码定义了一些常量:
String content = readFile("test.txt", StandardCharsets.UTF_8);

Charset类本身提供了平台默认值:
String content = readFile("test.txt", Charset.defaultCharset());


注意:此答案在很大程度上取代了我的Java 6版本。 Java 7的实用程序安全地简化了代码,并且使用映射字节缓冲区的旧答案阻止了读取的文件被删除,直到对映射缓冲区进行垃圾回收为止。您可以通过此答案上的“已编辑”链接查看旧版本。

评论


从技术上讲,它在时间和空间上为O(n)。定性地讲,由于Strings的不可变性要求,因此很难记忆;暂时在内存中有两个char数据副本,外加用于编码字节的空间。假设某些单字节编码,(临时)文件中的每个字符将需要5个字节的内存。由于该问题专门要求一个String,这就是我所显示的,但是如果您可以使用由“ decode”返回的CharBuffer,则对内存的需求将大大减少。从时间上看,我认为您不会在核心Java库中更快地找到任何东西。

– erickson
09年6月17日在20:16

可能有错字? NIO有一个名为java.nio.charset.Charset的Charset(不是CharSet)类。这是CharSet应该是的吗?

–乔纳森·赖特(Jonathan Wright)
09年12月20日在22:43

注意:在执行了一些代码之后,我发现使用此方法读取文件后不能立即可靠地删除文件,在某些情况下这可能不是问题,但不是我的。可能与此问题有关:bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154吗?我终于接受了Jon Skeet的建议,该建议不受此bug的影响。无论如何,我只是想将信息提供给其他人,以防万一...

–SébastienNussbaumer
2010年8月19日15:47



@SébastienNussbaumer:我也碰到了这个问题。令人惊讶的是,该错误已被标记为“将无法修复”。本质上,这意味着FileChannel#map通常是不可用的。

–乔纳斯·普拉卡(Joonas Pulakka)
2010年11月9日,7:45


#2 楼

如果您愿意使用外部库,请查看Apache Commons IO(200KB JAR)。它包含一个org.apache.commons.io.FileUtils.readFileToString()方法,允许您使用一行代码将整个File读入String

示例:

 import java.io.*;
import java.nio.charset.*;
import org.apache.commons.io.*;

public String readFile() throws IOException {
    File file = new File("data.txt");
    return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
}
 


评论


在您提供的网址中找不到该方法。

– OscarRyz
08年11月28日在18:52

在org.apache.commons.io.FileUtils类中

–西里尔·卡(Cyrille Ka)
08年11月28日在19:04

我也使用FileUtils,但我想知道使用FileUtils还是公认的nio答案之间有什么更好的选择?

–纪尧姆
2010-2-9在16:31

@Guillaume:最大的问题是您是否对依赖第三方库感到满意。如果您的项目中确实有Commons IO或Guava,则使用它们(只是为了简化代码;否则可能不会有明显的区别)。

– Jonik
2013年12月29日13:04



#3 楼

一个基于Scanner的非常精简的解决方案:

Scanner scanner = new Scanner( new File("poem.txt") );
String text = scanner.useDelimiter("\A").next();
scanner.close(); // Put this call in a finally block


或者,如果要设置字符集,请执行以下操作: />或者,使用try-with-resources块,它将为您调用scanner.close()

Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" );
String text = scanner.useDelimiter("\A").next();
scanner.close(); // Put this call in a finally block


请记住,Scanner构造函数可以抛出IOException。而且不要忘记导入java.iojava.util

来源:Pat Niemeyer的博客

评论


\\ A之所以有效,是因为没有“文件的其他开头”,因此您实际上已读取了最后一个令牌……这也是第一个。从未尝试使用\\ Z。还要注意,您可以读取任何可读的内容,例如文件,InputStreams,通道...当我不确定是否要读取一个文件或另一个文件时,有时我会使用此代码从Eclipse的显示窗口中进行读取。是的,classpath使我感到困惑。

– Pablo Grisafi
2011年9月16日20:16在

作为张贴者,我可以说我真的不知道该文件是否以及何时正确关闭...我从未在生产代码中编写此文件,仅将其用于测试或调试。

– Pablo Grisafi
2012年6月4日17:26

我认为它不能超过1024个字符

–异想天开
2012年7月4日14:32

扫描器实现Closeable(它在源代码上调用close)-因此,尽管优雅,但它实际上并不是单线的。缓冲区的默认大小为1024,但是Scanner会根据需要增加大小(请参见Scanner#makeSpace())

–earcam
2012年11月23日在9:43

对于带有java.util.NoSuchElementException的空文件,此操作将失败。

–SpaceTrucker
13年8月2日在9:16

#4 楼

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

String content = new String(Files.readAllBytes(Paths.get("readMe.txt")), StandardCharsets.UTF_8);


从Java 7开始,您就可以用这种方式。

评论


这应该作为答案接受-单行,没有外部库。

–樱桃
18年5月4日在16:07

即使文件中不存在换行符,它也会在末尾添加一个换行符

– Stefan Haberl
2月12日14:38

#5 楼

如果您正在寻找不涉及第三方库的替代方案(例如Commons I / O),则可以使用Scanner类:

private String readFile(String pathname) throws IOException {

    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int)file.length());        

    try (Scanner scanner = new Scanner(file)) {
        while(scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine() + System.lineSeparator());
        }
        return fileContents.toString();
    }
}


评论


我认为这是最好的方法。查看java.sun.com/docs/books/tutorial/essential/io/scanning.html

–塔斯基
08年11月28日在19:19

接受String的Scanner构造函数不会将字符串视为要读取的文件名,而是将其视为要扫描的文本。我一直犯那个错误。 :-/

–艾伦·摩尔
08年11月29日在9:10

@Alan,很好。我对Don的答案进行了略微修改,以解决该问题(我希望如此)。

– Jonik
2010-4-17的10:12

fileContents.append(scanner.nextLine())。append(lineSeparator);

– ban-geoengineering
13年5月24日在10:53

将初始化语句更改为Scanner Scanner = new Scanner((Readable)new BufferedReader(new FileReader(file)));。否则,您只能捕获文件的一部分。

–杨伟
13-10-22在17:40

#6 楼


评论


这段代码已从long转换为int,这可能会弹出一些大文件的疯狂行为。有多余的空间吗?您在哪里关闭输入流?

– Mohamed Taher Alrefaie
13年4月22日在15:42

@ M-T-A:流已关闭,请注意在CharSource中使用Closer。答案中的代码不是实际的当前Guava来源。

– Jonik
13年12月29日在13:19

#7 楼

import java.nio.file.Files;


.......

 String readFile(String filename) {
            File f = new File(filename);
            try {
                byte[] bytes = Files.readAllBytes(f.toPath());
                return new String(bytes,"UTF-8");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "";
    }


评论


或更简单:new String(Files.readAllBytes(FileSystems.getDefault()。getPath(filename)));

–user321068
2012年8月6日在21:54

或新的String(Files.readAllBytes(Paths.get(filename))); :-)

– assafmo
13-4-6在12:09



发挥得很好,并且为了避免下一个谷歌搜索,Paths和FileSystems显然是1.7+。 (该死的!)

–松饼
13-4-9在19:51



可惜这个答案没有更多的票。我一直在寻找将文本文件转换为String的最快,最简单的方法。就是这样,如果我不上下滚动,我会错过的。 OP应考虑接受此答案以将其移至顶部。

–刺
13年4月16日在4:40

@Thorn这个答案有可怕的错误处理。不要在生产代码中使用此方法,或者更好:永远不要。

– xehpuk
2015年2月20日在23:35

#8 楼

如果需要字符串处理(并行处理),则Java 8具有出色的Stream API。

String result = Files.lines(Paths.get("file.txt"))
                    .parallel() // for parallel processing 
                    .map(String::trim) // to change line   
                    .filter(line -> line.length() > 2) // to filter some lines by a predicate                        
                    .collect(Collectors.joining()); // to join lines


JDK示例sample/lambda/BulkDataOperations中提供了更多示例,可以从Oracle Java下载这些示例。 SE 8下载页面

另一个衬管示例

String out = String.join("\n", Files.readAllLines(Paths.get("file.txt")));


评论


.parallel()是在您阅读这些行之后还是之前发生的?

–伊斯特万
2015年4月17日在20:17



由于调用了终端操作collect(...),因此开始了实际工作。流是一行一行地懒散地填充的。在处理(例如过滤和映射)之前无需读取存储器中的整个文件。

– Andrei N
2015年4月21日在15:17

在选择非空行之前进行修剪?

–索比昂·拉文·安德森(ThorbjørnRavn Andersen)
16年1月13日在19:16

#9 楼

该代码将使换行符规范化,这可能不是您真正想做的。

这是一个不执行此操作的替代方法,它比NIO更易于理解(IMO)代码(尽管仍然使用java.nio.charset.Charset):

public static String readFile(String file, String csName)
            throws IOException {
    Charset cs = Charset.forName(csName);
    return readFile(file, cs);
}

public static String readFile(String file, Charset cs)
            throws IOException {
    // No real need to close the BufferedReader/InputStreamReader
    // as they're only wrapping the stream
    FileInputStream stream = new FileInputStream(file);
    try {
        Reader reader = new BufferedReader(new InputStreamReader(stream, cs));
        StringBuilder builder = new StringBuilder();
        char[] buffer = new char[8192];
        int read;
        while ((read = reader.read(buffer, 0, buffer.length)) > 0) {
            builder.append(buffer, 0, read);
        }
        return builder.toString();
    } finally {
        // Potential issue here: if this throws an IOException,
        // it will mask any others. Normally I'd use a utility
        // method which would log exceptions and swallow them
        stream.close();
    }        
}


评论


请原谅我恢复了这么老的评论,但是您的意思是传递一个名为“ file”的String对象,还是应该改为一个File对象?

–布莱恩·拉森(Bryan Larson)
2013年6月5日19:17

好答案。 +1。但是这个答案已经12岁了。 Java现在具有try-with-resources。

– Harshal Parekh
11月10日20:32



#10 楼

收集了从磁盘或网络中以字符串形式读取文件的所有可能方法。



Guava:Google使用类ResourcesFiles

 static Charset charset = com.google.common.base.Charsets.UTF_8;
public static String guava_ServerFile( URL url ) throws IOException {
    return Resources.toString( url, charset );
}
public static String guava_DiskFile( File file ) throws IOException {
    return Files.toString( file, charset );
}
 








APACHE-使用类的命令IO IOUtils,FileUtils

 static Charset encoding = org.apache.commons.io.Charsets.UTF_8;
public static String commons_IOUtils( URL url ) throws IOException {
    java.io.InputStream in = url.openStream();
    try {
        return IOUtils.toString( in, encoding );
    } finally {
        IOUtils.closeQuietly(in);
    }
}
public static String commons_FileUtils( File file ) throws IOException {
    return FileUtils.readFileToString( file, encoding );
    /*List<String> lines = FileUtils.readLines( fileName, encoding );
    return lines.stream().collect( Collectors.joining("\n") );*/
}
 








使用Stream API的Java 8 BufferReader

 public static String streamURL_Buffer( URL url ) throws IOException {
    java.io.InputStream source = url.openStream();
    BufferedReader reader = new BufferedReader( new InputStreamReader( source ) );
    //List<String> lines = reader.lines().collect( Collectors.toList() );
    return reader.lines().collect( Collectors.joining( System.lineSeparator() ) );
}
public static String streamFile_Buffer( File file ) throws IOException {
    BufferedReader reader = new BufferedReader( new FileReader( file ) );
    return reader.lines().collect(Collectors.joining(System.lineSeparator()));
}
 







带有正则表达式\A的扫描仪类。

 static String charsetName = java.nio.charset.StandardCharsets.UTF_8.toString();
public static String streamURL_Scanner( URL url ) throws IOException {
    java.io.InputStream source = url.openStream();
    Scanner scanner = new Scanner(source, charsetName).useDelimiter("\A");
    return scanner.hasNext() ? scanner.next() : "";
}
public static String streamFile_Scanner( File file ) throws IOException {
    Scanner scanner = new Scanner(file, charsetName).useDelimiter("\A");
    return scanner.hasNext() ? scanner.next() : "";
}
 







Java 7(java.nio.file.Files.readAllBytes

 public static String getDiskFile_Java7( File file ) throws IOException {
    byte[] readAllBytes = java.nio.file.Files.readAllBytes(Paths.get( file.getAbsolutePath() ));
    return new String( readAllBytes );
}
 







BufferedReader使用InputStreamReader

 public static String getDiskFile_Lines( File file ) throws IOException {
    StringBuffer text = new StringBuffer();
    FileInputStream fileStream = new FileInputStream( file );
    BufferedReader br = new BufferedReader( new InputStreamReader( fileStream ) );
    for ( String line; (line = br.readLine()) != null; )
        text.append( line + System.lineSeparator() );
    return text.toString();
}
 





带有访问上述方法的main方法的示例。

 public static void main(String[] args) throws IOException {
    String fileName = "E:/parametarisation.csv";
    File file = new File( fileName );

    String fileStream = commons_FileUtils( file );
            // guava_DiskFile( file );
            // streamFile_Buffer( file );
            // getDiskFile_Java7( file );
            // getDiskFile_Lines( file );
    System.out.println( " File Over Disk : \n"+ fileStream );


    try {
        String src = "https://code.jquery.com/jquery-3.2.1.js";
        URL url = new URL( src );

        String urlStream = commons_IOUtils( url );
                // guava_ServerFile( url );
                // streamURL_Scanner( url );
                // streamURL_Buffer( url );
        System.out.println( " File Over Network : \n"+ urlStream );
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
}
 



@see


将InputStream转换为字符串的方式


#11 楼

如果是文本文件,为什么不使用apache commons-io?

它具有以下方法

public static String readFileToString(File file) throws IOException


如果要将行作为列表使用

public static List<String> readLines(File file) throws IOException


#12 楼

自JDK 11起:

String file = ...
Path path = Paths.get(file);
String content = Files.readString(path);
// Or readString(path, someCharset), if you need a Charset different from UTF-8


评论


为什么,为什么要引入依赖于2018年默认字符集的新方法?

– mryan
18-09-24在7:49

@mryan此方法不依赖默认系统字符集。默认为UTF-8,可以。

– Leventov
18-09-24在11:39

@leventov你是对的! File.readAllLines也是如此!这使得文件API与旧方法不太一致,但这是更好的方法:)

– mryan
18-09-25在13:34

#13 楼

将文件读取为二进制文件并在末尾进行转换

public static String readFileAsString(String filePath) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(filePath));
    try {
        long len = new File(filePath).length();
        if (len > Integer.MAX_VALUE) throw new IOException("File "+filePath+" too large, was "+len+" bytes.");
        byte[] bytes = new byte[(int) len];
        dis.readFully(bytes);
        return new String(bytes, "UTF-8");
    } finally {
        dis.close();
    }
}


#14 楼

Java尝试在所有方面都变得极为通用和灵活。结果,在脚本语言中相对简单的事情(您的代码将被python中的“ open(file).read()”代替)要复杂得多。除了使用外部库(例如提到的Willi aus Rohr)外,似乎没有什么更短的方法了。您的选择:


使用外部库。
将此代码复制到所有项目中。
创建自己的迷你库,其中包含经常使用的功能。

您的最佳选择可能是第二名,因为它的依赖性最小。

评论


是的它使“高级”语言具有不同的含义。 Java与C相比具有较高的水平,但与Python或Ruby相比却具有较低的水平

– OscarRyz
08年11月28日在19:36

同意Java在高级抽象方面很长,但在便利方法上却很短

–Dónal
2011年5月11日在16:44

的确,Java处理文件的方法非常疯狂,其中许多似乎很复杂。但是,这与高级语言中的代码非常接近:byte [] bytes = Files.readAllBytes(someFile.toPath());

–刺
13年4月16日在20:45

#15 楼

对于Java 7,这是读取UTF-8文件的首选方法:

String content = new String(Files.readAllBytes(Paths.get(filename)), "UTF-8");


由于Java 7,JDK具有新的java.nio.file API,该API提供了许多快捷方式,因此简单的文件操作并不总是需要第三方库。

#16 楼

使用JDK 8或更高版本:

不使用外部库

您可以从文件内容创建新的String对象(使用java.nio.file包中的类):

public String readStringFromFile(String filePath) throws IOException {
    String fileContent = new String(Files.readAllBytes(Paths.get(filePath)));
    return fileContent;
}


评论


重复的莫里兹·彼得森(Moritz Petersen)的答案是谁写的:字符串内容=新字符串(Files.readAllBytes(Paths.get(filename)),“ UTF-8”);

–让·克里斯托弗·布兰查德(Jean-Christophe Blanchard)
18年11月29日在10:30



#17 楼

在同一主题上有一个变体,它使用for循环而不是while循环来限制line变量的范围。是否“更好”取决于个人喜好。

for(String line = reader.readLine(); line != null; line = reader.readLine()) {
    stringBuilder.append(line);
    stringBuilder.append(ls);
}


评论


这会将换行符更改为默认的换行符选择。这可能是理想的,也可能是意料之外的。

– Peter Lawrey
2010-4-18的7:23

将编辑回滚到此答案,因为要缩小行变量的范围。编辑两次声明它,这将是编译错误。

–丹·代尔
13年8月1日在20:16

#18 楼

如果您无权访问Files类,则可以使用本机解决方案。

static String readFile(File file, String charset)
        throws IOException
{
    FileInputStream fileInputStream = new FileInputStream(file);
    byte[] buffer = new byte[fileInputStream.available()];
    int length = fileInputStream.read(buffer);
    fileInputStream.close();
    return new String(buffer, 0, length, charset);
}


评论


示例字符集调用?

– Thufir
18/12/30在8:48

#19 楼

将Apache commons-io的IOUtils与StringWriter结合使用的灵活解决方案:

Reader input = new FileReader();
StringWriter output = new StringWriter();
try {
  IOUtils.copy(input, output);
} finally {
  input.close();
}
String fileContents = output.toString();


它适用于任何读取器或输入流(不仅仅是文件),例如当从URL阅读。

#20 楼

请注意,在使用fileInputStream.available()时,返回的整数不必表示实际的文件大小,而是系统应该能够在不阻塞IO的情况下从流读取的猜测字节数。一种安全,简单的方法可能像这样

public String readStringFromInputStream(FileInputStream fileInputStream) {
    StringBuffer stringBuffer = new StringBuffer();
    try {
        byte[] buffer;
        while (fileInputStream.available() > 0) {
            buffer = new byte[fileInputStream.available()];
            fileInputStream.read(buffer);
            stringBuffer.append(new String(buffer, "ISO-8859-1"));
        }
    } catch (FileNotFoundException e) {
    } catch (IOException e) { }
    return stringBuffer.toString();
}


应该考虑这种方法不适用于UTF-8之类的多字节字符编码。 >

评论


此代码可能会产生不可预测的结果。根据available()方法的文档,如果该方法返回0,则不能保证到达文件结尾。在这种情况下,您可能会得到不完整的文件。更糟糕的是,实际读取的字节数可能小于available()返回的值,在这种情况下,您的输出将损坏。

– wau
13年3月15日在13:32

#21 楼

这是一种使用RandomAccessFile.readFully的方法,似乎可以从JDK 1.0中获得!

public static String readFileContent(String filename, Charset charset) throws IOException {
    RandomAccessFile raf = null;
    try {
        raf = new RandomAccessFile(filename, "r");
        byte[] buffer = new byte[(int)raf.length()];
        raf.readFully(buffer);
        return new String(buffer, charset);
    } finally {
        closeStream(raf);
    }
} 


private static void closeStream(Closeable c) {
    if (c != null) {
        try {
            c.close();
        } catch (IOException ex) {
            // do nothing
        }
    }
}


#22 楼

您可以尝试使用Scanner和File类,几行解决方案

 try
{
  String content = new Scanner(new File("file.txt")).useDelimiter("\Z").next();
  System.out.println(content);
}
catch(FileNotFoundException e)
{
  System.out.println("not found!");
}


#23 楼

根据@erickson的回答,您可以使用:

public String readAll(String fileName) throws IOException {
    List<String> lines = Files.readAllLines(new File(fileName).toPath());
    return String.join("\n", lines.toArray(new String[lines.size()]));
}


#24 楼

用户java.nio.Files读取文件的所有行。

public String readFile() throws IOException {
        File fileToRead = new File("file path");
        List<String> fileLines = Files.readAllLines(fileToRead.toPath());
        return StringUtils.join(fileLines, StringUtils.EMPTY);
}


#25 楼

public static String slurp (final File file)
throws IOException {
    StringBuilder result = new StringBuilder();

    BufferedReader reader = new BufferedReader(new FileReader(file));

    try {
        char[] buf = new char[1024];

        int r = 0;

        while ((r = reader.read(buf)) != -1) {
            result.append(buf, 0, r);
        }
    }
    finally {
        reader.close();
    }

    return result.toString();
}


评论


我认为使用平台默认编码会带来不便。无论如何+1 :)

– OscarRyz
2010-2-9 15:53

在我看来,finally块不知道try块中定义的变量。 javac 1.6.0_21引发错误,找不到符号。

–天花板
2012年6月25日的16:11

您甚至尝试过自己的代码吗?您已经在try / catch块中定义了阅读器,因此在finally块中将无法访问它。

– mauron85
18-10-31在9:48

#26 楼

我还不能评论其他条目,所以我就把它留在这里。

最好的答案之一在这里(https://stackoverflow.com/a/326448/1521167):

private String readFile(String pathname) throws IOException {

File file = new File(pathname);
StringBuilder fileContents = new StringBuilder((int)file.length());
Scanner scanner = new Scanner(file);
String lineSeparator = System.getProperty("line.separator");

try {
    while(scanner.hasNextLine()) {        
        fileContents.append(scanner.nextLine() + lineSeparator);
    }
    return fileContents.toString();
} finally {
    scanner.close();
}
}


仍然有一个缺陷。它总是将换行符放在字符串的末尾,这可能会导致一些奇怪的错误。我的建议是将其更改为:

    private String readFile(String pathname) throws IOException {
    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int) file.length());
    Scanner scanner = new Scanner(new BufferedReader(new FileReader(file)));
    String lineSeparator = System.getProperty("line.separator");

    try {
        if (scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine());
        }
        while (scanner.hasNextLine()) {
            fileContents.append(lineSeparator + scanner.nextLine());
        }
        return fileContents.toString();
    } finally {
        scanner.close();
    }
}


评论


在第一种情况下,您可能会在末尾添加额外的换行符。在第二种情况下,您可能会省略一个。因此,两者都是错误的。看这篇文章

–帕特里克·帕克(Patrick Parker)
18-3-28在13:46



#27 楼

在扫描仪之后按Ctrl + F后,我认为也应列出扫描仪解决方案。以最容易阅读的方式,它是这样的:

public String fileToString(File file, Charset charset) {
  Scanner fileReader = new Scanner(file, charset);
  fileReader.useDelimiter("\Z"); // \Z means EOF.
  String out = fileReader.next();
  fileReader.close();
  return out;
}


如果您使用Java 7或更高版本(并且您确实应该)考虑使用try-with-resources进行代码更易于阅读。不再有点滴杂物乱扔一切。但这主要是一种风格选择方法。

我主要出于完成主义的目的发布此方法,因为如果您需要做很多事情,那么java.nio.file.Files中应该有一些东西我的建议是使用Files#readAllBytes(Path)来获取所有字节,并将其提供给新的String(byte [] Charset)以从中获得一个字符串,这是更好的工作。你可以信任。字符集在您的一生中对您而言将是卑鄙的,因此请当心这些内容。

其他人提供了代码和内容,我不想窃取他们的荣耀。 ;)

#28 楼

使用此库,只需一行:

String data = IO.from(new File("data.txt")).toString();


评论


如果不计算库​​中的行。

–阿里
17年8月1日在2:13

#29 楼

另外,如果文件恰好位于jar中,则也可以使用以下命令:

public String fromFileInJar(String path) {
    try ( Scanner scanner 
            = new Scanner(getClass().getResourceAsStream(path))) {
        return scanner.useDelimiter("\A").next();
    }
}


例如,如果jar是
,则路径应以/开头。
my.jar/com/some/thing/a.txt


然后您要像这样调用它:

String myTxt = fromFileInJar("/com/com/thing/a.txt");


#30 楼

在一行(Java 8)中,假设您拥有阅读器:

String sMessage = String.join("\n", reader.lines().collect(Collectors.toList()));