当前位置:  开发笔记 > 编程语言 > 正文

如何从文件内容创建Java字符串?

如何解决《如何从文件内容创建Java字符串?》经验,为你挑选了18个好方法。

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

是否有更好/不同的方式将文件读入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();
    }
}

erickson.. 1467

从文件中读取所有文本

这是Java 7的一个紧凑,健壮的习惯用法,包含在一个实用程序方法中:

String content = Files.readString(path, StandardCharsets.US_ASCII);

从文件中读取文本行

Java 7添加了一种方便的方法来将文件读取为文本行,表示为String.这种方法是"有损"的,因为行分隔符从每行的末尾剥离.

static String readFile(String path, Charset encoding) 
  throws IOException 
{
  byte[] encoded = Files.readAllBytes(Paths.get(path));
  return new String(encoded, encoding);
}

在Java 8中,List添加了一个新方法,Files.lines()以生成一个Stream.如果IOException在读取文件时遇到a,则将其包装在一个中UncheckedIOException,因为Stream不接受抛出已检查异常的lambdas.

List lines = Files.readAllLines(Paths.get(path), encoding);

还有一种Stream方法可以做一些非常相似的事情,close()直接返回.但我不喜欢它.在Stream需要close()调用; 这在API上记录很少,我怀疑很多人甚至没有注意到lines()有一种BufferedReader方法.所以你的代码看起来非常相似,如下所示:

try (Stream lines = Files.lines(path, encoding)) {
  lines.forEach(System.out::println);
}

区别在于你已经Stream分配了一个变量,我尝试避免这种做法,以便我不小心尝试两次调用流.

内存利用率

第一种保留换行符的方法可以暂时需要几倍于文件大小的内存,因为短时间内原始文件内容(一个字节数组)和解码后的字符(即使编码也是16位)因为文件中的8位)一次驻留在内存中.最安全的方法是应用于您知道相对于可用内存较小的文件.

读取行的第二种方法通常更有效,因为用于解码的输入字节缓冲区不需要包含整个文件.但是,它仍然不适合相对于可用内存非常大的文件.

对于读取大型文件,您需要为程序设计一个不同的设计,一个从流中读取一块文本,处理它,然后继续下一个,重用相同的固定大小的内存块.这里,"大"取决于计算机规格.如今,这个阈值可能是几千兆字节的RAM.readLine()如果您的输入"记录"恰好是单独的行,则使用a的第三种方法是这样做的一种方法.(使用BufferedReader方法StandardCharsets是程序等同于这种方法.)

字符编码

原始帖子中的示例中缺少的一件事是字符编码.在某些特殊情况下,平台默认值是您想要的,但它们很少见,您应该能够证明您的选择.

Charset类中定义的所有Java运行时所需要的编码的一些常量:

String content = readFile("test.txt", StandardCharsets.UTF_8);

该平台默认可从该String类本身:

String content = readFile("test.txt", Charset.defaultCharset());

注意:这个答案很大程度上取代了我的Java 6版本.Java 7的实用程序安全地简化了代码,使用映射字节缓冲区的旧答案阻止了读取的文件被删除,直到映射的缓冲区被垃圾收集.您可以通过此答案中的"已编辑"链接查看旧版本.



1> erickson..:

从文件中读取所有文本

这是Java 7的一个紧凑,健壮的习惯用法,包含在一个实用程序方法中:

String content = Files.readString(path, StandardCharsets.US_ASCII);

从文件中读取文本行

Java 7添加了一种方便的方法来将文件读取为文本行,表示为String.这种方法是"有损"的,因为行分隔符从每行的末尾剥离.

static String readFile(String path, Charset encoding) 
  throws IOException 
{
  byte[] encoded = Files.readAllBytes(Paths.get(path));
  return new String(encoded, encoding);
}

在Java 8中,List添加了一个新方法,Files.lines()以生成一个Stream.如果IOException在读取文件时遇到a,则将其包装在一个中UncheckedIOException,因为Stream不接受抛出已检查异常的lambdas.

List lines = Files.readAllLines(Paths.get(path), encoding);

还有一种Stream方法可以做一些非常相似的事情,close()直接返回.但我不喜欢它.在Stream需要close()调用; 这在API上记录很少,我怀疑很多人甚至没有注意到lines()有一种BufferedReader方法.所以你的代码看起来非常相似,如下所示:

try (Stream lines = Files.lines(path, encoding)) {
  lines.forEach(System.out::println);
}

区别在于你已经Stream分配了一个变量,我尝试避免这种做法,以便我不小心尝试两次调用流.

内存利用率

第一种保留换行符的方法可以暂时需要几倍于文件大小的内存,因为短时间内原始文件内容(一个字节数组)和解码后的字符(即使编码也是16位)因为文件中的8位)一次驻留在内存中.最安全的方法是应用于您知道相对于可用内存较小的文件.

读取行的第二种方法通常更有效,因为用于解码的输入字节缓冲区不需要包含整个文件.但是,它仍然不适合相对于可用内存非常大的文件.

对于读取大型文件,您需要为程序设计一个不同的设计,一个从流中读取一块文本,处理它,然后继续下一个,重用相同的固定大小的内存块.这里,"大"取决于计算机规格.如今,这个阈值可能是几千兆字节的RAM.readLine()如果您的输入"记录"恰好是单独的行,则使用a的第三种方法是这样做的一种方法.(使用BufferedReader方法StandardCharsets是程序等同于这种方法.)

字符编码

原始帖子中的示例中缺少的一件事是字符编码.在某些特殊情况下,平台默认值是您想要的,但它们很少见,您应该能够证明您的选择.

Charset类中定义的所有Java运行时所需要的编码的一些常量:

String content = readFile("test.txt", StandardCharsets.UTF_8);

该平台默认可从该String类本身:

String content = readFile("test.txt", Charset.defaultCharset());

注意:这个答案很大程度上取代了我的Java 6版本.Java 7的实用程序安全地简化了代码,使用映射字节缓冲区的旧答案阻止了读取的文件被删除,直到映射的缓冲区被垃圾收集.您可以通过此答案中的"已编辑"链接查看旧版本.


注意:在执行了一些代码之后,我发现在使用此方法读取文件后,您无法可靠地删除文件,在某些情况下这可能不是问题,但不是我的问题.可能与此问题有关:http://bugs.sun.com/bugdatabase/view_bug.do?video_id = 4715154?我终于选择了没有遭受这个bug的Jon Skeet的命题.无论如何,我只是想为其他人提供信息以防万一......
可能错字?NIO有一个名为java.nio.charset.Charset的Charset(而不是CharSet)类.这是CharSet本来应该的吗?
@SébastienNussbaumer:我也遇到了这个问题.令人惊讶的是,该bug已标记为"无法修复".这实际上意味着`FileChannel#map`通常是不可用的.
@SébastienNussbaumer:该漏洞已从Oracle/Sun Bug数据库中删除:"此错误无法使用." Google将该网站缓存在http://webcache.googleusercontent.com/search?q=cache:bugs.sun.com/bugdatabase/view_bug.do%3Fbug_id%3D4715154
从技术上讲,它在时间和空间上都是O(n).定性地说,由于字符串的不变性要求,它在内存上相当困难; 暂时在内存中有两个char数据副本,加上编码字节的空间.假设有一些单字节编码,它(暂时)需要为文件中的每个字符提供5个字节的内存.由于问题专门针对一个字符串,这就是我所展示的,但是如果你可以使用"解码"返回的CharBuffer,那么内存需求要少得多.时间方面,我不认为你会在核心Java库中找到更快的东西.

2> 小智..:

下议院org.apache.commons.io.FileUtils.readFileToString():

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);
}

使用VM的默认编码将文件内容读入String.该文件始终关闭.

参数:

File - 要读取的文件,不能为null

返回:文件内容,永远不为null

抛出: - String- 如果发生I/O错误

自:Commons IO 1.3.1

该类(间接)使用的代码是:

Apache License 2.0下的IOUtils.java.

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);
}

它与Ritche_W使用的非常相似.


@Guillaume:最大的问题是你是否愿意依赖第三方库.如果你的项目中有Commons IO或[Guava](http://stackoverflow.com/a/2224519/56285),那就使用它(只是为了简化代码;否则可能没有明显的区别).
它位于org.apache.commons.io.FileUtils类中
我也在使用FileUtils,但我想知道使用FileUtils或接受的nio答案有什么好处?

3> Pablo Grisaf..:

从这个页面非常精简的解决方案:

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

如果要设置charset


扫描仪实现了Closeable(它在源上调用close) - 所以虽然优雅但它不应该是一个单行.缓冲区的默认大小为1024,但扫描程序将根据需要增加大小(请参阅扫描程序#makeSpace())
对于带有`java.util.NoSuchElementException`的空文件,这个失败了.
\\ A有效,因为没有"文件的其他开头",所以你实际上是读了最后一个令牌......这也是第一个.没试过用\\ Z. 另请注意,您可以阅读任何可读的内容,例如Files,InputStreams,channels ...我有时会使用此代码从eclipse的显示窗口读取,当时我不确定我是在读一个文件还是其他文件. .yes,classpath让我困惑.
我认为它有1024个字符的限制

4> Jobin Joseph..:
import java.nio.file.Files;
import java.nio.file.Paths;

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

从java 7开始,你可以这样做.


应该提到所需的导入:import java.nio.file.Files; import java.nio.file.Paths;

5> Dónal..:

如果您正在寻找不涉及第三方库(例如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();
    }
}


接受String的Scanner构造函数不会将字符串视为要读取的文件的名称,而是将其视为要扫描的文本.我总是犯这个错误.: - /
.fileContents.append(scanner.nextLine())附加(lineSeparator);
我认为这是最好的方法.查看http://java.sun.com/docs/books/tutorial/essential/io/scanning.html

6> finnw..:

Guava有一种类似于Commons IOUtils的方法,Willi aus Rohr提到:

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版本的源代码不符.对于电流源,看到类文件,CharStreams,ByteSource和CharSource在com.google.common.io包.



7> user590444..:
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(Paths.get(filename)));`:-)
或者更简单:`new String(Files.readAllBytes(FileSystems.getDefault().getPath(filename)));`
可惜,这个答案没有更多的选票.我一直在寻找将文本文件转换为String的最快捷,最简单的方法.这就是它,如果我没有向下和向下滚动,我会错过它.OP应该考虑接受这个答案,将其移到顶部.

8> Jon Skeet..:

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

这是一个不能做到这一点的替代方案,而且(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();
    }        
}



9> Andrei N..:

如果您需要字符串处理(并行处理),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")));



10> Yash..:

收集了从磁盘或网络读取文件为字符串的所有可能方法.

番石榴:谷歌使用课程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 -使用类IOUtils,FileUtils的COMMONS IO

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 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 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();
    }
}

@看到

将InputStream转换为String的方法



11> 小智..:

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

它有以下方法

public static String readFileToString(File file) throws IOException

如果要将行作为列表使用

public static List readLines(File file) throws IOException



12> leventov..:

从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


@mryan此方法不依赖于默认系统字符集。它默认为UTF-8,这很好。

13> Peter Lawrey..:

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

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> Moritz Peter..:

使用Java 7,这是我读取UTF-8文件的首选选项:

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

从Java 7开始,JDK就拥有了新的java.nio.fileAPI,它提供了许多快捷方式,因此简单的文件操作并不总是需要第三方库.



15> Claudiu..:

Java试图在其所有方面都非常通用和灵活.因此,在脚本语言中相对简单的东西(您的代码将open(file).read()在python中替换为" ")要复杂得多.除了使用外部库(如Willi aus Rohr提到的)之外,似乎没有任何更短的方法.你的选择:

使用外部库.

将此代码复制到您的所有项目中.

创建自己的迷你库,其中包含您经常使用的功能.

你最好的选择可能是第二个,因为它的依赖性最小.


叶氏.它使"高级"语言具有不同的含义.与C相比,Java是高级别的,但与Python或Ruby相比较低
同意Java长期处于高级抽象,但缺乏便利方法
没错,Java有很多处理文件的方法,其中许多看起来很复杂.但这与我们在更高级语言中的相当接近:`byte [] bytes = Files.readAllBytes(someFile.toPath());`

16> Saikat Sengu..:
使用JDK 8或更高版本:

没有使用外部库

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

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



17> Dan Dyer..:

在同一主题上有一个变体,它使用for循环而不是while循环来限制行变量的范围.它是否"更好"是个人品味的问题.

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


这会将换行符更改为默认的换行符.这可能是期望的,或者是非预期的.

18> Ilya Gazman..:

如果您无权访问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);
}

推荐阅读
无名有名我无名_593
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有