我正在学习 Android 开发(我是一般编程的初学者)并学习 HTTP 网络,并在类(class)中看到了这段代码:
private String readFromStream(InputStream inputStream) throws IOException {
StringBuilder output = new StringBuilder();
if (inputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line != null) {
output.append(line);
line = reader.readLine();
}
}
return output.toString();
}
我不明白 InputStream、InputStreamReader 和 BufferedReader 到底是做什么的。它们都有一个 read() 方法,在 BufferedReader 的情况下还有 readLine()。为什么我不能只使用 InputStream 或只添加 InputStreamReader?为什么我需要添加 BufferedReader?我知道这与效率有关,但我不明白这是怎么回事。
我一直在研究 documentation for the BufferedReader试图解释这一点,但我仍然不明白谁在做什么:
In general, each read request made of a Reader causes a corresponding read request to be made of the underlying character or byte stream. It is therefore advisable to wrap a BufferedReader around any Reader whose read() operations may be costly, such as FileReaders and InputStreamReaders. For example,
BufferedReader in = new BufferedReader(new FileReader("foo.in"));will buffer the input from the specified file. Without buffering, each invocation of read() or readLine() could cause bytes to be read from the file, converted into characters, and then returned, which can be very inefficient.
所以,我知道 InputStream 只能读取一个字节,InputStreamReader 只能读取一个字符,而 BufferedReader 只能读取整行,而且它还可以提高效率,这是我不明白的。我想更好地了解谁在做什么,以便理解为什么我需要这三者以及没有其中之一会有什么不同。
我在这里和网络上的其他地方进行了很多研究,似乎没有找到任何我能理解的解释,几乎所有教程都只是重复文档信息。这里有一些相关的问题可能会开始解释这个但不要更深入地解决我的困惑:Q1 , Q2 , Q3 , Q4 .我想这可能与最后一个问题对系统调用和返回的解释有关。但我想了解这一切的含义。
会不会是 BufferedReader 的 readLine() 调用了 InputStreamReader 的 read() 方法,而 InputStreamReader 的 read() 方法又调用了 InputStream 的 read() 方法?并且 InputStream 返回转换为 int 的字节,一次返回一个字节,InputStreamReader 读取足够多的字节来生成单个字符并将其转换为 int 并一次返回一个字符,BufferedReader 读取足够多的这些字符表示为整数来组成整行?并将整行作为字符串返回,只返回一次而不是多次?我不知道,我只是想知道事情是如何运作的。
非常感谢!
最佳答案
这Streams in Java concepts and usage链接,给出一个很好的解释。
Streams、Readers、Writers、BufferedReader、BufferedWriter – 这些是您将在 Java 中处理的术语。 Java 中提供了一些类来处理输入和输出。真正值得了解它们之间的关系以及它们的使用方式。这篇文章将详细探讨 Java 中的 Streams 和其他相关类。那么让我们开始吧:
让我们在高层次上定义每一个,然后深入挖掘。
流
用于处理字节级数据
读者/作家
用来处理人物等级。它还支持各种字符编码。
BufferedReader/BufferedWriter
以提高性能。要读取的数据将缓存到内存中,以便快速访问。
虽然这些用于获取输入,但也只有相应的类用于输出。例如,如果有一个用于读取字节流的 InputStream,而 OutputStream 将有助于写入字节流。
输入流
java提供了多种类型的InputStreams。每个都连接到不同的数据源,例如字节数组、文件等。
例如,FileInputStream 连接到文件数据源,可用于从文件中读取字节。而 ByteArrayInputStream 可用于将字节数组视为输入流。
输出流
这有助于将字节写入数据源。几乎每个 InputStream 都有对应的 OutputStream,只要它有意义。
更新
什么是缓冲流?
这里我引用自Buffered Streams , Java 文档(附技术说明):
Buffered Streams
Most of the examples we've seen so far use unbuffered I/O. This means each read or write request is handled directly by the underlying OS. This can make a program much less efficient, since each such request often triggers disk access, network activity, or some other operation that is relatively expensive.
To reduce this kind of overhead, the Java platform implements buffered I/O streams. Buffered input streams read data from a memory area known as a buffer; the native input API is called only when the buffer is empty. Similarly, buffered output streams write data to a buffer, and the native output API is called only when the buffer is full.
有时候,我在阅读技术文档时会头皮发麻。所以,这里引用https://yfain.github.io/Java4Kids/的比较人性化的解释 :
In general, disk access is much slower than the processing performed in memory; that’s why it’s not a good idea to access the disk a thousand times to read a file of 1,000 bytes. To minimize the number of times the disk is accessed, Java provides buffers, which serve as reservoirs of data.
In reading File with FileInputStream then BufferedInputStream, the class BufferedInputStream works as a middleman between FileInputStream and the file itself. It reads a big chunk of bytes from a file into memory (a buffer) in one shot, and the FileInputStream object then reads single bytes from there, which are fast memory-to-memory operations. BufferedOutputStream works similarly with the class FileOutputStream.
The main idea here is to minimize disk access. Buffered streams are not changing the type of the original streams — they just make reading more efficient. A program performs stream chaining (or stream piping) to connect streams, just as pipes are connected in plumbing.
关于java - InputStream、InputStreamReader 和 BufferedReader 如何在 Java 中协同工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43147069/
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121