java - 为什么在 java 中有不同的处理文件 I/O 的方法?
问题描述
到目前为止,我一直在使用Scanner
s 从文本文件中读取数据。例子:
File file = new File("path\\to\\file") ;
Scanner scan = new Scanner(file) ;
System.out.println(scan.nextLine()) ;
并使用FileWriter
s 将数据写入文本文件。像这样:
try
{
FileWriter writer = new FileWriter("Foo.txt") ;
writer.write("hello there!") ;
writer.close()
}
catch(IOException ex)
{
ex.printStackTrace() ;
}
几天前,我在和我的导师开会。当我检查他的代码时,我注意到他使用了一种BufferedReader
和BufferedWriter
- 一种读取和写入我以前没有使用过的文件的方法。BufferedReader
然后我问他使用 a和 aScanner
从文件中读取数据有什么区别。他无法向我解释。
所以我做了一些研究,发现执行这些操作的类是InputStream
和OutputStream
. 这些类有各自的子类FileInputStream
,如FileOutputStream
, 等。
在我的研究中,我遇到了用于从文件读取数据和将数据写入文件的Reader
和类。Writer
同样,像InputStream
and一样OutputStream
,这些类是abstract
super
类并且有自己的子类来执行读写操作。
我对此并不感到困惑,但是……为什么?我的意思是,为什么有不同的方法来做同样的事情?有什么意义?哪种方法是处理文件输入和输出的最有效方法?
解决方案
Reader
s 读char
s;InputStream
读byte
s。(相应地,Writer
s write char
s;OutputStream
s write byte
s)。
String
s 是 s 的序列char
,而不是byte
s。
如果您想阅读byte
s,请使用InputStream
. 如果要从文件中读取它们,请使用FileInputStream
; 但并非所有byte
s 序列都来自文件,例如,ByteArrayInputStream
允许您byte
从 a 中读取 s序列byte[]
;但因为它是一个InputStream
,所以它的使用方式与它来自文件的方式完全相同。
如果您想阅读char
s,请使用Reader
. 如果您想将 an 读取InputStream
为char
s,请使用 an InputStreamReader
,为此您指定 a CharSet
,这样可以将s 正确byte
转换为char
s。
ABufferedReader
是Reader
缓冲其输入的 a - 它一次从源读取多个字节,而不是一次读取一个。假设您需要不止一个,那么一次阅读很多而不是只阅读一个通常更有效。它还提供了获取 aString
而不是 a 的便捷方法char[]
。
对我来说,BufferedReader
允许您在 a 之外做的典型示例Reader
是一次阅读整行。
Scanner
是一个高级类,它允许您从 a String
(或者,通常是 a Readable
,例如,由Reader
and实现BufferedReader
)读取数据,但将该数据作为其他类型获取String
- 例如,您可以读取1 2.0 true
为 a int
,double
并且boolean
分别,而不必自己进行解析。
这只是建立在其他事物的功能之上,基本上是通过从内部读取Reader
. Scanner 基本上是一个标记器,尽管还有更老的StringTokenizer
.
Scanner
老实说,这是一个相当糟糕的课程:它在基本程序中经常使用(例如“输入你的名字,输入你最喜欢的颜色”);但它有锋利的边缘,吸引了许多初学者(例如,扫描仪在使用 next() 或 nextFoo() 后跳过了 nextLine()?);并且它不像您想的那样简单,例如验证用户输入数字而不是一般字符串。
我发现您很快就会从使用 开始Scanner
,而只是使用s(Buffered)Reader
来阅读所有内容String
:它更强大。
推荐阅读
- ios - 如何检查文本字段在 Swift 中是否有多个字母?
- reactjs - getInitialProps 在我的实时站点上导致 ERR_TOO_MANY_REDIRECTS 错误,但在我的本地版本上没有
- generative-adversarial-network - 判别器的真假损失是一样的,不变的
- asp.net-core - 避免在 ASP.NET Core 属性路由中使用魔法字符串
- android - 使用cordova-plugin-firebasex时如何连接到firebase本地模拟器
- c++ - 如何在 c++17 或 20 中使用 std::invoke_result_t 而不是 c++14 中的 std::result_of_t?
- c++ - std::lock_guard 是否在使用 std::adopt_lock 选项构造后释放互斥锁?
- java - 如何在 Spring Boot 中从命令行解析链接?
- react-native - IntelliJ Expo 控制台日志以红色显示 ANSI 转义字符
- django - Django:我想显示当月的数据,但我还没有找到有效的查询。请协助