Java读取文件的不同方法

Java读取文件的不同方法,java,file-io,Java,File Io,在Java中读取文本文件的方法似乎有很多很多(BufferedReader,DataInputStream等)。我个人最喜欢的是在构造函数中带有文件的扫描器(它更简单,与mathy数据处理更好地配合,并且具有熟悉的语法) 蜘蛛鲍里斯也提到了频道和随机访问文件 有人能解释一下每种方法的优缺点吗?具体来说,我想在什么时候使用它们 (编辑)我认为我应该具体一点,并补充说我非常喜欢扫描仪方法。所以真正的问题是,我什么时候不想使用它?注意:这种方法已经过时了。正如鲍里斯在评论中指出的那样。我将把它保留在这

在Java中读取文本文件的方法似乎有很多很多(
BufferedReader
DataInputStream
等)。我个人最喜欢的是在构造函数中带有
文件的
扫描器
(它更简单,与mathy数据处理更好地配合,并且具有熟悉的语法)

蜘蛛鲍里斯也提到了
频道
随机访问文件

有人能解释一下每种方法的优缺点吗?具体来说,我想在什么时候使用它们


(编辑)我认为我应该具体一点,并补充说我非常喜欢
扫描仪
方法。所以真正的问题是,我什么时候不想使用它?

注意:这种方法已经过时了。正如鲍里斯在评论中指出的那样。我将把它保留在这里作为历史记录,但您应该使用JDK中可用的方法

这取决于您正在执行的操作类型和正在读取的文件的大小

在大多数情况下,我建议对小文件使用

byte[] data = FileUtils.readFileToByteArray(new File("myfile"));
您可以将其读取为字符串或字符数组

现在,您正在处理大文件,或者直接在文件系统上更改文件的一部分,那么最好使用RandomAccessFile,甚至可能使用FileChannel来执行“nio”样式。

SCANNER:

可以使用正则表达式分析基元类型和字符串。 扫描器使用定界符模式将其输入拆分为标记,默认情况下,定界符模式匹配空白。然后可以将生成的令牌转换为不同类型的值。可以在

数据输入流:

允许应用程序以独立于机器的方式从底层输入流读取基本Java数据类型。应用程序使用数据输出流写入数据,这些数据稍后可由数据输入流读取。对于多线程访问,DataInputStream不一定是安全的。线程安全是可选的,由此类中方法的用户负责。更多信息请访问

BufferedReader:

从字符输入流读取文本,缓冲字符,以便有效读取字符、数组和行。可以指定缓冲区大小,也可以使用默认大小。默认值对于大多数用途来说都足够大。通常,读卡器发出的每个读取请求都会导致对底层字符或字节流发出相应的读取请求。因此,建议将BufferedReader包装在任何read()操作可能代价高昂的读取器(如FileReader和InputStreamReader)周围。比如说,

BufferedReader in   = new BufferedReader(new FileReader("foo.in"));

将缓冲来自指定文件的输入。如果没有缓冲,每次调用read()或readLine()都可能导致从文件中读取字节,转换为字符,然后返回,这可能会非常低效。使用DataInputStreams进行文本输入的程序可以通过使用适当的BufferedReader替换每个DataInputStream来本地化。更多详细信息请参见

让我们从开头开始。问题是你想做什么

理解文件实际上是什么很重要。文件是光盘上字节的集合,这些字节是您的数据。Java所提供的抽象有多个层次:

  • 文件(输入|输出)流
    -将这些字节作为
    字节流
    读取
  • 文件(读写器)
    -以
    字符流的形式从字节流中读取
  • Scanner
    -从
    char
    流中读取并标记它
  • RandomAccessFile
    -将这些字节作为可搜索的
    字节[]
    读取
  • FileChannel
    -以安全的多线程方式读取这些字节
  • 例如,您可以使用
    BufferedXXX
    添加缓冲。您可以使用
    PrintWriter
    将换行识别添加到
    FileWriter
    。您可以使用
    InputStreamReader
    InputStreamReader
    转换为
    Reader
    (目前为
    读取器指定字符编码的唯一方法)

    那么-我什么时候不想使用它[一个
    扫描仪
    ]

    如果愿意,您不会使用
    扫描仪
    (以下是一些示例):

  • 以字节形式读入数据
  • 读入序列化的Java对象
  • byte
    s从一个文件复制到另一个文件,可能需要一些过滤
  • 扫描器(文件文件)
    构造函数获取
    文件
    并使用平台默认编码打开一个
    文件输入流
    ,这也毫无价值-这几乎总是一个糟糕的想法。一般认为,应该明确指定编码,以避免令人讨厌的基于编码的错误。此外,流没有被缓冲

    所以你可能会和我一起过得更好

    try (final Scanner scanner = new Scanner(new BufferedInputStream(new FileInputStream())), "UTF-8") {
        //do stuff
    }
    
    丑陋,我知道

    值得注意的是,Java 7提供了进一步的抽象层,以消除对文件进行循环的需要-这些文件在类中:

    例如,要从
    路径
    获取大量单词,可以执行以下操作:

        final Stream<String> words = Files.lines(Paths.get("myFile.txt")).
                flatMap((in) -> Arrays.stream(in.split("\\b")));
    
    final Stream words=Files.line(path.get(“myFile.txt”))。
    flatMap((in)->array.stream(in.split(\\b”));
    
    别忘了
    频道
    随机访问文件
    以及它们的同类。。。所有这些方法都是不同的。有些读取二进制流。一些字符流。一些标记化输入。实际上没有可比性——它们有不同的使用场景。“它们有不同的使用场景。”是的。这就是我想问的原因。我的“选择武器”是
    LineNumberReader
    。非常适合逐行读取和解析人类可读的文本文件,如csv。我发现
    Scanner
    对于读取一维空格分隔的ascii数据文件非常有用。
    Scanner
    与其他文件不可相比。提到的其他技术
    Stream<String> Files.lines(Path path, Charset cs)
    Stream<Path> Files.list(Path dir)
    
        final Stream<String> words = Files.lines(Paths.get("myFile.txt")).
                flatMap((in) -> Arrays.stream(in.split("\\b")));