首页 > 解决方案 > 为什么在 java 中有不同的处理文件 I/O 的方法?

问题描述

到目前为止,我一直在使用Scanners 从文本文件中读取数据。例子:

        File file = new File("path\\to\\file") ;

        Scanner scan = new Scanner(file) ;  

        System.out.println(scan.nextLine()) ;

并使用FileWriters 将数据写入文本文件。像这样:

        try
        {
            FileWriter writer = new FileWriter("Foo.txt") ;
            writer.write("hello there!") ;                      
            writer.close() 
        }
        catch(IOException ex) 
        {
            ex.printStackTrace() ;
        }

几天前,我在和我的导师开会。当我检查他的代码时,我注意到他使用了一种BufferedReaderBufferedWriter- 一种读取和写入我以前没有使用过的文件的方法。BufferedReader然后我问他使用 a和 aScanner从文件中读取数据有什么区别。他无法向我解释。

所以我做了一些研究,发现执行这些操作的类是InputStreamOutputStream. 这些类有各自的子类FileInputStream,如FileOutputStream, 等。

在我的研究中,我遇到了用于从文件读取数据和将数据写入文件的Reader和类。Writer同样,像InputStreamand一样OutputStream,这些类是abstract super类并且有自己的子类来执行读写操作。

我对此并不感到困惑,但是……为什么?我的意思是,为什么有不同的方法来做同样的事情?有什么意义?哪种方法是处理文件输入和输出的最有效方法?

标签: javafile-io

解决方案


Readers 读chars;InputStreambytes。(相应地,Writers write chars;OutputStreams write bytes)。

Strings 是 s 的序列char,而不是bytes。

如果您想阅读bytes,请使用InputStream. 如果要从文件中读取它们,请使用FileInputStream; 但并非所有bytes 序列都来自文件,例如,ByteArrayInputStream允许您byte从 a 中读取 s序列byte[];但因为它是一个InputStream,所以它的使用方式与它来自文件的方式完全相同。

如果您想阅读chars,请使用Reader. 如果您想将 an 读取InputStreamchars,请使用 an InputStreamReader,为此您指定 a CharSet,这样可以将s 正确byte转换为chars。

ABufferedReaderReader缓冲其输入的 a - 它一次从源读取多个字节,而不是一次读取一个。假设您需要不止一个,那么一次阅读很多而不是只阅读一个通常更有效。它还提供了获取 aString而不是 a 的便捷方法char[]

对我来说,BufferedReader允许您在 a 之外做的典型示例Reader一次阅读整行

Scanner是一个高级类,它允许您从 a String(或者,通常是 a Readable,例如,由Readerand实现BufferedReader)读取数据,但将该数据作为其他类型获取String- 例如,您可以读取1 2.0 true为 a intdouble并且boolean分别,而不必自己进行解析。

这只是建立在其他事物的功能之上,基本上是通过从内部读取Reader. Scanner 基本上是一个标记器,尽管还有更老的StringTokenizer.


Scanner老实说,这是一个相当糟糕的课程:它在基本程序中经常使用(例如“输入你的名字,输入你最喜欢的颜色”);但它有锋利的边缘,吸引了许多初学者(例如,扫描仪在使用 next() 或 nextFoo() 后跳过了 nextLine()?);并且它不像您想的那样简单,例如验证用户输入数字而不是一般字符串。

我发现您很快就会从使用 开始Scanner,而只是使用s(Buffered)Reader来阅读所有内容String:它更强大。


推荐阅读