我一直在使用下面的成语一段时间了。它似乎是最广泛的,至少在我访问的网站上。
有没有更好/不同的方法将文件读入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();
}
}
答案 0 :(得分:1389)
这是Java 7的一个紧凑,强大的习惯用法,包含在一个实用方法中:
static String readFile(String path, Charset encoding)
throws IOException
{
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
Java 7添加了convenience method to read a file as lines of text,,表示为List<String>
。这种方法是“有损”的,因为行分隔符是从每一行的末尾剥离的。
List<String> lines = Files.readAllLines(Paths.get(path), encoding);
Java 8添加了Files.lines()
方法来生成Stream<String>
。同样,这种方法是有损的,因为剥离了行分隔符。如果在读取文件时遇到IOException
,则会将其包装在UncheckedIOException
中,因为Stream
不接受抛出已检查异常的lambdas。
try (Stream<String> lines = Files.lines(path, encoding)) {
lines.forEach(System.out::println);
}
此Stream
确实需要close()
来电;这在API上记录很少,我怀疑很多人甚至没有注意到Stream
有close()
方法。请务必使用如图所示的ARM块。
如果您使用的是文件以外的来源,则可以使用BufferedReader
中的lines()
方法代替。
第一种保留换行符的方法,可以暂时需要几倍于文件大小的内存,因为短时间内原始文件内容(一个字节数组)和解码后的字符(每个都是16位)即使在文件中编码为8位)也会立即驻留在内存中。最安全的是应用于您知道相对于可用内存较小的文件。
读取行的第二种方法通常更有效,因为用于解码的输入字节缓冲区不需要包含整个文件。但是,它仍然不适合相对于可用内存非常大的文件。
对于读取大文件,您需要为程序设计一个不同的设计,一个从流中读取一块文本,处理它,然后继续下一个,重复使用相同的固定大小的内存块。这里,“大”取决于计算机规格。如今,这个阈值可能是几千兆字节的RAM。第三种方法,使用Stream<String>
是一种方法,如果您的输入“记录”恰好是单独的行。 (使用readLine()
BufferedReader
方法是与此方法等效的过程。)
原始帖子中的示例中缺少的一件事是字符编码。在某些特殊情况下,平台默认值是您想要的,但它们很少见,您应该能够证明您的选择。
StandardCharsets
类定义了所有Java运行时所需编码的一些常量:
String content = readFile("test.txt", StandardCharsets.UTF_8);
平台默认设置可从the Charset
class本身获得:
String content = readFile("test.txt", Charset.defaultCharset());
注意:这个答案很大程度上取代了我的Java 6版本。 Java 7的实用程序安全地简化了代码,使用映射字节缓冲区的旧答案阻止了读取的文件被删除,直到映射的缓冲区被垃圾收集。您可以通过此答案中的“已编辑”链接查看旧版本。
答案 1 :(得分:316)
如果您愿意使用外部库,请查看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);
}
答案 2 :(得分:172)
基于Scanner
的非常精益的解决方案:
Scanner scanner = new Scanner( new File("poem.txt") );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block
或者,如果你想设置charset:
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
或者,使用try-with-resources块,会为您调用scanner.close()
:
try (Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" )) {
String text = scanner.useDelimiter("\\A").next();
}
请记住,Scanner
构造函数可以抛出IOException
。不要忘记导入java.io
和java.util
。
答案 3 :(得分:93)
import java.nio.file.Files;
import java.nio.file.Paths;
String content = new String(Files.readAllBytes(Paths.get("readMe.txt")), "UTF-8");
因为java 7你可以这样做。
答案 4 :(得分:75)
如果您正在寻找不涉及第三方库的替代方案(例如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();
}
}
答案 5 :(得分:67)
Guava的方法与Willi aus Rohr提到的Commons IOUtils类似:
import com.google.common.base.Charsets;
import com.google.common.io.Files;
// ...
String text = Files.toString(new File(path), Charsets.UTF_8);
由Oscar Reyes编辑
这是引用库中的(简化)底层代码:
InputStream in = new FileInputStream(file);
byte[] b = new byte[file.length()];
int len = b.length;
int total = 0;
while (total < len) {
int result = in.read(b, total, len - total);
if (result == -1) {
break;
}
total += result;
}
return new String( b , Charsets.UTF_8 );
编辑(作者Jonik):以上内容与最近的Guava版本的源代码不符。对于当前来源,请参阅Files包中的课程CharStreams,ByteSource,CharSource和com.google.common.io。
答案 6 :(得分:51)
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 "";
}
答案 7 :(得分:49)
该代码将规范化换行符,这可能是你真正想做的也可能不是。
这是一个不能做到这一点的替代方案,而且(IMO)比NIO代码更容易理解(虽然它仍然使用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();
}
}
答案 8 :(得分:47)
如果需要字符串处理(并行处理),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 download page
另一个班轮示例
String out = String.join("\n", Files.readAllLines(Paths.get("file.txt")));
答案 9 :(得分:25)
收集了从磁盘或网络读取文件为字符串的所有可能方法。
Guava: Google使用班级Resources
,Files
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 - COMMONS 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") );*/
}
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
答案 10 :(得分:24)
如果是文本文件,为什么不使用apache commons-io?
它有以下方法
public static String readFileToString(File file) throws IOException
如果您想将这些行用作列表
public static List<String> readLines(File file) throws IOException
答案 11 :(得分:22)
自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
答案 12 :(得分:16)
将文件读取为二进制文件并在结尾处进行转换
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();
}
}
答案 13 :(得分:16)
使用Java 7,这是我读取UTF-8文件的首选选项:
String content = new String(Files.readAllBytes(Paths.get(filename)), "UTF-8");
从Java 7开始,JDK具有新的java.nio.file
API,它提供了许多快捷方式,因此简单文件操作并不总是需要第三方库。
答案 14 :(得分:15)
Java尝试极其通用且灵活。因此,在脚本语言中相对简单的东西(您的代码将在python中替换为“open(file).read()
”)要复杂得多。除了使用外部库(如提到的Willi aus Rohr)之外,似乎没有任何更短的方法。你的选择:
你最好的选择可能是第二个,因为它的依赖性最小。
答案 15 :(得分:11)
未使用外部库
您可以从文件内容中创建一个新的String对象(使用java.nio.file
包中的类):
public String readStringFromFile(String filePath) throws IOException {
String fileContent = new String(Files.readAllBytes(Paths.get(filePath)));
return fileContent;
}
答案 16 :(得分:8)
同一主题中有一个变体,它使用for循环而不是while循环来限制行变量的范围。是否“更好”是个人品味的问题。
for(String line = reader.readLine(); line != null; line = reader.readLine()) {
stringBuilder.append(line);
stringBuilder.append(ls);
}
答案 17 :(得分:7)
如果您无权访问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);
}
答案 18 :(得分:4)
使用来自Apache IOUtils的commons-io与StringWriter结合使用的灵活解决方案:
Reader input = new FileReader();
StringWriter output = new StringWriter();
try {
IOUtils.copy(input, output);
} finally {
input.close();
}
String fileContents = output.toString();
它适用于任何读者或输入流(不仅仅是文件),例如从URL读取时。
答案 19 :(得分:3)
请注意,在使用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等多字节字符编码。
答案 20 :(得分:3)
您可以尝试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!");
}
答案 21 :(得分:3)
这个方法使用方法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 :(得分:3)
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();
}
答案 23 :(得分:3)
用户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);
}
答案 24 :(得分:2)
在Scanner之后按Ctrl + F,我认为也应该列出Scanner解决方案。以最容易阅读的方式,它是这样的:
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)以获取您可以信任的字符串。 Charsets在你的一生中对你意味着,所以现在要小心这些东西。
其他人已经给出了代码和东西,我不想偷走他们的荣耀。 ;)
答案 25 :(得分:2)
使用this library,它是一行:
String data = IO.from(new File("data.txt")).toString();
答案 26 :(得分:2)
此外,如果您的文件恰好位于jar中,您也可以使用:
public String fromFileInJar(String path) {
try ( Scanner scanner
= new Scanner(getClass().getResourceAsStream(path))) {
return scanner.useDelimiter("\\A").next();
}
}
例如,如果你的jar是
,路径应该以{{1}}开头/
然后你想像这样调用它:
my.jar/com/some/thing/a.txt
答案 27 :(得分:2)
在一行(Java 8)中,假设您有一个Reader:
String sMessage = String.join("\n", reader.lines().collect(Collectors.toList()));
答案 28 :(得分:2)
根据@ 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()]));
}
答案 29 :(得分:1)
我还不能评论其他参赛作品,所以我会把它留在这里。
这里最好的答案之一(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();
}
}
还有一个漏洞。它总是将新行char放在字符串的末尾,这可能会导致一些奇怪的错误。我的建议是将其更改为:
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();
}
}
答案 30 :(得分:0)
使用代码:
File file = new File("input.txt");
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(
file));
byte[] buffer = new byte[(int) file.length()];
bin.read(buffer);
String fileStr = new String(buffer);
fileStr包含String中的输出。
答案 31 :(得分:0)
您可以使用多种方式读取文件内容。下面是几种读取文件内容的方法
使用 BufferedReader
try {
File file = new File("C://temp/sample.txt");
FileInputStream fileInputStream = new FileInputStream(file);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
// Converting input stream to buffer reader
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String temp = "";
StringBuffer textFileContent = new StringBuffer();
while ((temp = bufferedReader.readLine()) != null) {
textFileContent.append(temp);
}
System.out.println(textFileContent);
// In below line we are closing the bufferReader
bufferedReader.close();
} catch (Exception e) {
e.printStackTrace();
}
使用扫描仪
try {
File file = new File("C:\\temp\\sample.txt");
Scanner scanner = new Scanner(file);
StringBuffer textFileContent = new StringBuffer();
while (scanner.hasNextLine()) {
textFileContent.append(scanner.nextLine());
}
System.out.println(textFileContent);
scanner.close();
} catch (Exception e) {
e.printStackTrace();
}
}
使用 File.ReadBytes
try {
byte[] encoded = Files.readAllBytes(Paths.get("D:\\workspace\\sample.txt"));
String s = new String(encoded, StandardCharsets.US_ASCII);
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
更多请参考以下网址
https://beginnersbug.com/how-to-read-a-file-from-java-with-example/
答案 32 :(得分:-1)
在java 8中,有一个新的类
java.util.stream.Stream
流表示一系列元素,并支持不同类型的操作以对这些元素执行计算
阅读更多相关信息:
这里有一个例子:
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
public Class ReadFile{
public static String readFile(String filePath) {
StringBuilder stringBuilder = new StringBuilder();
String ls = System.getProperty("line.separator");
try {
try (Stream<String> lines = Files.lines(Paths.get(filePath), StandardCharsets.UTF_8)) {
for (String line : (Iterable<String>) lines::iterator) {
stringBuilder.append(line);
stringBuilder.append(ls);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return stringBuilder.toString();
}
}
答案 33 :(得分:-1)
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Collectors;
/**
* A simple example program that reads a text file into a String using Files.lines and stream.
*/
public class ReadTextFileExample {
public static void main(String[] args) throws IOException {
String contents = Files.lines(Paths.get("c:\\temp\\testfile.txt")).collect(Collectors.joining("\n"));
System.out.println(contents);
}
}