我正试图将一个简单的文本文件读入一个字符串。当然,有一种通常的方法可以获取输入流,并使用readline()进行迭代,然后将内容读取到字符串中。
在过去的数百次中,我只是想知道如何在最少的代码行中做到这一点?在Java中没有像EDOCX1,0…而是像这样简单的东西?
我知道有像ApacheCommonsIO这样的库提供了这样的简化,甚至我也可以编写一个简单的Util类来实现这一点。但我想知道的是,这是一个如此频繁的操作,每个人都需要,那么为什么Java不能提供这样简单的功能呢?是否真的有一个方法可以用某种默认或指定的编码将文件读取到字符串中?
是的,您可以在一行中做到这一点(不过对于健壮的IOException处理,您不想这样做)。
1 2
| String content = new Scanner (new File("filename")). useDelimiter("\\Z"). next();
System. out. println(content ); |
它使用一个java.util.Scanner,告诉它用\Z来限定输入,该输入是字符串锚的结尾。这最终使输入具有一个实际的标记,即整个文件,因此可以通过一次调用next()来读取它。
有一个构造函数接受一个File和一个String charSetName(以及许多其他重载)。这两个构造函数可以抛出FileNotFoundException,但像所有Scanner方法一样,不能将IOException抛出到这些构造函数之外。
如果发生或不发生IOException,可以通过ioException()方法查询Scanner本身。您还可能希望在阅读内容后显式地使用close()和Scanner,因此最好将Scanner引用存储在局部变量中。
也见
相关问题
- 使用java.util.scanner验证输入-有许多更典型的用法示例
第三方库选项
为了完整性,如果您有这些非常著名和非常有用的第三方库,那么这些是非常好的选择:
番石榴
com.google.common.io.Files包含许多有用的方法。相关的是:
- String toString(File, Charset)
- 使用给定的字符集,将文件中的所有字符读取到String中。
- List readLines(File, Charset)
阿帕奇公地/IO
org.apache.commons.io.IOUtils也提供类似的功能:
- String toString(InputStream, String encoding)
- 使用指定的字符编码,获取InputStream的内容作为String的内容。
- List readLines(InputStream, String encoding)
- …作为String的(原始)List,每行一个条目
相关问题
- 好吧!尽管可能不像您提到的那样健壮,但毫无疑问,这是在最少的代码行中实现的!
- 请参见下面的Java 7机制的解决方案,该机制本质上是一个默认的API,就像Java自这个问题以来略微移动的许多东西一样。
- 不幸的是,扫描程序解决方案失败,文件为空(nosuchelementexception)
- 除了在空文件上失败之外,它还省略了文件末尾的换行符(如果存在的话)。
- 我用这个已经有一段时间了,但事实证明它并不总是有效的!有时,\\Z会实际出现在文件中,并导致失败。
- 返回新的扫描程序(new url(url).openstream(),"utf-8").usedelimiter(\a").next();更好,因为它不会在空文件上失败。
- 我不知道为什么,但在Windows7上失败了,我遇到了NoSuchelementException。但是相同的代码在OSX上运行良好。读取相同的文件,这些文件不是空的。
- 如果使用的文本文件大于1024字节,请避免这种情况。扫描器将(至少在Android上)将结果字符串剪切到1024字节。
- 随着groovy的出现,您可以这样读取一个文件:string content=new file(filename).text()。
- 我不得不投反对票:它修剪了后面的换行符,这是不可接受的,我现在花了半个小时调试,非常感谢。
从Java 7(API描述)开始,您可以:
new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);
其中filepath是表示要加载的文件的字符串。
- 我相信只有当文件在平台的默认字符集中时,这才有效。
- @保罗,我认为这可以作为一个默认值。构造新字符串时,始终可以指定字符集
- 此解决方案的缺点是不使用类路径资源(通过Class.getResource()或类似方法获得),而Scanner解决方案在这种情况下确实有效。
- 此方法适用于类路径资源:string iamastring=new string(files.readallbytes(paths.get(((new classpathresource("iamafile")).getfile()).getabsolutepath())‌&8203;);
- 我最后一个注释的纯Java版本:String IAMString=new String(文件.Read Alpple)(新文件(Tr.CurrnTrthRead)).GETCaseCetryLoopLoad()、GETRESOUW和ZWNJ;以及RE(8203);RCE("IAMAFILE").Turn&ZWnJ;& Sy 8203;I.())(TopScript())
- @rondo并非所有的类路径资源都对应于File(例如,考虑一个jar中的资源),所以不,它一般不能用于这个目的。
- @迪卡尼,你把"不"放错了地方:我不是想把它变成一般。这个问题需要一个非一般性的答案,因为只有一般性的解决方案需要一次构建一点文件内容:例如:try url in=classloader.getSystemResource("文件名");system.out.println(in);inputstream is=classloader.getSystemResourceAsstream("文件名");int c;stringbuilder sb=new stringbuilder();while((c=is.read())!=-1)sb.append((char)c);string iamastring=sb.toString();catch(ioexception io)
- @jim inputstream未在api文件.readAllBytes()中关闭。
- @pruthvichitrala来自javadoc for readallbytes:从文件中读取所有字节。该方法确保在读取所有字节或引发I/O错误或其他运行时异常时关闭文件。inputstream不是files.readallbytes调用方关心的问题。Oracle、Oracle、COM/JavaSe/ 7/DOCS/API/Java/NiO/file/Helip;
- 从国际化的角度来看,使用不带charset参数的字符串构造函数不是最佳实践。我建议使用new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);,假设文件是UTF-8编码的,这在目前的大多数情况下是正确的。
您可以使用Apache Commons IO。
- Java程序员是什么样的,当Java构建了一个工作正常的设备时,总是试图使用第三方库。
- 当然,这些设施"工作得很好",只是有些设施完全过于复杂。不过,我同意使用另一个lib进行此操作有点过分。
- 这不是杀戮过度。这是一个机会。开始使用ApacheCommons库并提高生产效率的机会。或者你可以选择番石榴。
这应该对你有用:
1 2 3 4 5 6 7
| import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public static void main (String[] args ) throws IOException {
String content = new String(Files. readAllBytes(Paths. get("abc.java")));
} |
- 谢谢!与大多数解决方案不同,这也不会删除尾随换行符。一个改进:new String(…, StandardCharsets.UTF_8)。
使用Apache Commons IO。
1 2 3 4 5
| import org.apache.commons.io.FileUtils;
//...
String contents = FileUtils. readFileToString(new File("/path/to/the/file"), "UTF-8") |
有关方法的详细信息,请参阅de javadoc。
不要编写自己的Util类来实现这一点——我建议您使用充满各种优点的guava。在这种情况下,您需要Files类(如果您实际上只是在读取文件)或charstreams用于更通用的读取。它有方法将数据读取到字符串列表(readLines或全部(toString中)。
它对二进制数据也有类似的有用方法。还有图书馆的其他部分…
我同意在标准库中没有类似的东西是很烦人的。见鬼,只要能给FileReader提供一个CharSet,生活就会简单一点…
- 在Java 7上,你会推荐番石榴或EDOCX1?0?
- @马努:我绝对不会用那个——我至少要指定一个字符编码。但是,正如番石榴通常是有用的(即使使用Java 8),你也可以使用EDCOX1,1。
另一种替代方法是:
如何从文件的内容创建Java字符串?
其他选项是使用开放源码库提供的实用程序
http://commons.apache.org/io/api-1.4/index.html?org/apache/commons/io/ioutils.html文件
为什么Java不提供这样一个通用的UTIL API?< BR>a)保持API通用,以便程序员处理编码、缓冲等。
b)让程序员做一些工作并编写/共享OpenSource Util库:d;-)
遗憾的是,没有。
我同意这样频繁的操作应该比逐行循环复制输入更容易实现,但是您必须编写helper方法或使用外部库。
我发现接受的答案实际上并不总是有效,因为文件中可能会出现\\Z。另一个问题是,如果没有正确的字符集,可能会发生一大堆意外的事情,这可能会导致扫描仪只读取文件的一部分。
解决方案是使用一个定界符,您可以确定该定界符不会出现在文件中。然而,理论上这是不可能的。我们所能做的是使用一个分隔符,它在文件中有一个很小的机会可以忽略不计:这样的定界符是一个uuID,它在Java中是本地支持的。
1 2
| String content = new Scanner (file, "UTF-8")
. useDelimiter(UUID. randomUUID(). toString()). next(); |
- "文件中可能出现\z"是什么意思? z(unescaping之后)是java.util.regex.pattern的模式之一,而不是文字字符序列。文件中的字面值字符序列(后跟z的反斜杠)与模式z不匹配。
- @Kurokurosaka我不是指文字序列\Z,我的意思是文件实际上可能在文件中间的某个地方包含"字符串结尾"字符。这件事发生在我身上,正是我接受的答案对我不起作用的原因。
- 我懂了。您正在考虑这样一种情况:一个软件或操作系统决定使用CR或LF以外的控制字符(如果是Microsoft,则两者都使用)来执行EOL序列。例如,如果使用control-z作为eof字符,我会把它写成类似"'u001a'"。