本文共 16651 字,大约阅读时间需要 55 分钟。
我已经在下面使用过一段时间了。 至少在我访问过的网站上,它似乎是分布最广的。
在Java中,是否有更好/不同的方式将文件读取为字符串?
private 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(); }}
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 ""; }
请注意,在使用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。
我还不能评论其他条目,所以我就把它留在这里。
最佳答案之一( ):
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(); }}
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();}
的方法类似于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);
由PiggyPiglet编辑
已弃用Files#toString
,并将于2019年8月将其删除。而应使用Files.asCharSource(new File(path), StandardCharsets.UTF_8).read();
奥斯卡·雷耶斯(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最新版本的源代码不匹配。 对于电流源,看到类 , , 和在包。
将文件读取为二进制文件并在末尾进行转换
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(); }}
如果您需要字符串处理(并行处理),则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
中提供了更多示例。
另一个班轮的例子
String out = String.join("\n", Files.readAllLines(Paths.get("file.txt")));
如果您无权访问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);}
如果您愿意使用外部库,请查看 (200KB JAR)。 它包含一个方法,该方法使您可以用一行代码将整个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);}
Java尝试在所有方面都变得极为通用和灵活。 结果,在脚本语言中相对简单的事情(您的代码将被python中的“ open(file).read()
”替换)要复杂得多。 除了使用外部库(例如提到的 )外,似乎没有什么更短的方法了。 您的选择:
您最好的选择可能是第二,因为它具有最少的依赖性。
Java 11添加了方法以将小的文件读取为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>
。 这种方法是“有损的”,因为从每行的末端剥去了行分隔符。
Listlines = Files.readAllLines(Paths.get(path), encoding);
Java 8添加了方法来生成Stream<String>
。 同样,此方法是有损的,因为剥去了行分隔符。 如果在读取文件时遇到IOException
,则它将包装在 ,因为Stream
不接受引发已检查异常的lambda。
try (Streamlines = Files.lines(path, encoding)) { lines.forEach(System.out::println);}
此Stream
确实需要调用; 这个在API上的文档很少,我怀疑很多人甚至没有注意到Stream
有close()
方法。 确保使用如图所示的ARM模块。
如果您使用的不是文件源,则可以使用BufferedReader
的方法。
保留换行符的第一种方法可能临时需要占用文件大小几倍的内存,因为在短时间内,原始文件内容(字节数组)和解码后的字符(即使已编码也为16位) (文件中的8位)一次存储在内存中。 将其应用于相对于可用内存较小的文件是最安全的。
第二种方法是读取行,通常可以提高内存效率,因为用于解码的输入字节缓冲区不需要包含整个文件。 但是,它仍然不适用于相对于可用内存而言非常大的文件。
为了读取大文件,您需要为程序提供不同的设计,即从流中读取文本块,对其进行处理,然后再移至下一个,重新使用相同的固定大小的内存块。 在此,“大”取决于计算机规格。 如今,此阈值可能是许多GB的RAM。 如果输入“记录”恰好是单独的行,则使用Stream<String>
的第三种方法是执行此操作的一种方法。 (使用BufferedReader
的readLine()
方法等效于此方法。)
原始帖子的示例中缺少的一件事是字符编码。 在某些特殊情况下,平台默认值是您想要的,但是很少见,您应该可以证明自己的选择合理。
类为所有Java运行时所需的编码定义了一些常量:
String content = readFile("test.txt", StandardCharsets.UTF_8);
该平台默认值可从本身获得:
String content = readFile("test.txt", Charset.defaultCharset());
注意:此答案在很大程度上替代了我的Java 6版本。 Java 7的实用程序安全地简化了代码,并且使用映射字节缓冲区的旧答案阻止了读取的文件被删除,直到对映射缓冲区进行垃圾回收为止。 您可以通过此答案上的“已编辑”链接查看旧版本。
如果您正在寻找不涉及第三方库的替代方案(例如 ),则可以使用类:
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(); }}
该代码将规范换行符,这可能是也可能不是您真正想要的。
这是一个不执行此操作的替代方法,它比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(); } }
在同一主题上有一个变体,它使用for循环而不是while循环来限制line变量的范围。 是否“更好”取决于个人喜好。
for(String line = reader.readLine(); line != null; line = reader.readLine()) { stringBuilder.append(line); stringBuilder.append(ls);}
在扫描仪之后按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 7,这是读取UTF-8文件的首选方法:
String content = new String(Files.readAllBytes(Paths.get(filename)), "UTF-8");
从Java 7开始,JDK具有新的java.nio.file
API,该API提供了许多快捷方式,因此对于简单的文件操作,并非始终需要第三方库。
import java.nio.file.Files;import java.nio.file.Paths;String content = new String(Files.readAllBytes(Paths.get("readMe.txt")), "UTF-8");
从Java 7开始,您可以使用这种方式。
使用 ,它是一行:
String data = IO.from(new File("data.txt")).toString();
您可以尝试使用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!");}
同样,如果您的文件恰好在罐子里,您也可以使用以下命令:
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");
在一行(Java 8)中,假设您具有阅读器:
String sMessage = String.join("\n", reader.lines().collect(Collectors.toList()));
根据@erickson的回答,您可以使用:
public String readAll(String fileName) throws IOException { Listlines = Files.readAllLines(new File(fileName).toPath()); return String.join("\n", lines.toArray(new String[lines.size()]));}
收集了从磁盘或网络以字符串形式读取文件的所有可能方法。
使用类 ,
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-使用类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 ); /*Listlines = FileUtils.readLines( fileName, encoding ); return lines.stream().collect( Collectors.joining("\\n") );*/ }
使用 Java 8
public static String streamURL_Buffer( URL url ) throws IOException { java.io.InputStream source = url.openStream(); BufferedReader reader = new BufferedReader( new InputStreamReader( source ) ); //Listlines = 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(); }}
@看到
没有使用外部库
您可以从文件内容创建一个新的String对象(使用java.nio.file
包中的类):
public String readStringFromFile(String filePath) throws IOException { String fileContent = new String(Files.readAllBytes(Paths.get(filePath))); return fileContent;}
从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
用户java.nio.Files
读取文件的所有行。
public String readFile() throws IOException { File fileToRead = new File("file path"); ListfileLines = Files.readAllLines(fileToRead.toPath()); return StringUtils.join(fileLines, StringUtils.EMPTY);}
基于非常精简的解决方案:
Scanner scanner = new Scanner( new File("poem.txt") );String text = scanner.useDelimiter("\\A").next();scanner.close(); // Put this call in a finally block
或者,如果要设置字符集:
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.close()
:
try (Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" )) { String text = scanner.useDelimiter("\\A").next();}
请记住, Scanner
构造函数可以抛出IOException
。 并且不要忘记导入java.io
和java.util
。
资料来源:
如果是文本文件,为什么不使用呢?
它具有以下方法
public static String readFileToString(File file) throws IOException
如果要将这些行作为列表使用
public static ListreadLines(File file) throws IOException
这个使用了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 } }}
结合使用Apache 和灵活解决方案:
Reader input = new FileReader();StringWriter output = new StringWriter();try { IOUtils.copy(input, output);} finally { input.close();}String fileContents = output.toString();
它适用于任何阅读器或输入流(不仅适用于文件),例如,从URL读取时。
转载地址:http://hbdnb.baihongyu.com/