sourcereader.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 165 行
SCALA
165 行
/* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author Martin Odersky */// $Id: SourceReader.scala 12390 2007-07-23 12:19:46Z michelou $package scala.tools.nsc.ioimport java.io.{File, FileInputStream, InputStream, IOException}import java.nio.{ByteBuffer, CharBuffer}import java.nio.channels.{FileChannel, ReadableByteChannel, Channels}import java.nio.charset.{CharsetDecoder, CoderResult}/** This class implements methods to read and decode source files. */class SourceReader(decoder: CharsetDecoder) { import SourceReader.{decode, flush} //######################################################################## // Private Fields /** The input byte buffer (small enough to fit in cache) */ private val bytes: ByteBuffer = ByteBuffer.allocate(0x4000) /** The output character buffer */ private var chars: CharBuffer = CharBuffer.allocate(0x4000) private def reportEncodingError(filename:String) = { Console println "IO error while decoding "+filename+" with "+decoder.charset(); Console println "Please try specifying another one using the -encoding option" } //######################################################################## // Public Methods /** Reads the file with the specified name. */ def read(filename: String): Array[Char]= read(new File(filename)) /** Reads the specified file. */ def read(file: File): Array[Char] = { val c = new FileInputStream(file).getChannel try { read(c) } catch { case e:Exception => reportEncodingError(file.toString()) new Array[Char](0) } finally { c.close() } } /** Reads the specified file. * * @param file ... * @return ... */ def read(file: AbstractFile): Array[Char] = { file match { case p:PlainFile => read(p.file) // bq: (!!!) case z:ZipArchive#FileEntry => val c = Channels.newChannel(z.getArchive.getInputStream(z.entry)) read(c) case _ => throw new IOException(file.toString()+" is neither plain file nor ZipArchive#FileEntry") } /* val decoder: CharsetDecoder = this.decoder.reset(); val bytes: ByteBuffer = ByteBuffer.wrap(file.read); val chars: CharBuffer = this.chars; chars.clear(); try { terminate(flush(decoder, decode(decoder, bytes, chars, true))); } catch { case e:Exception => reportEncodingError(file.toString()) new Array[Char](0) } */ } /** Reads the specified byte channel. */ protected def read(input: ReadableByteChannel): Array[Char] = { val decoder: CharsetDecoder = this.decoder.reset() val bytes: ByteBuffer = this.bytes; bytes.clear() var chars: CharBuffer = this.chars; chars.clear() var endOfInput: Boolean = false while (!endOfInput ) { endOfInput = input.read(bytes) < 0 bytes.flip() chars = decode(decoder, bytes, chars, endOfInput) } terminate(flush(decoder, chars)) } //######################################################################## // Private Methods /** * Sets the specified char buffer as the new output buffer and * reads and returns its content. */ private def terminate(chars: CharBuffer): Array[Char] = { val result = new Array[Char](chars.length()) chars.get(result) this.chars = chars result }}object SourceReader { /** * Decodes the content of the specified byte buffer with the * specified decoder into the specified char buffer, allocating * bigger ones if necessary, then compacts the byte buffer and * returns the last allocated char buffer. The "endOfInput" * argument indicates whether the byte buffer contains the last * chunk of the input file. */ def decode(decoder: CharsetDecoder, bytes: ByteBuffer, chars: CharBuffer, endOfInput: Boolean): CharBuffer = { val result: CoderResult = decoder.decode(bytes, chars, endOfInput) if (result.isUnderflow()) { bytes.compact() chars } else { if (result.isError()) throw new IOException(result.toString()) assert(result.isOverflow()) decode(decoder, bytes, increaseCapacity(chars), endOfInput) } } /** * Flushes the specified decoder into the specified char buffer, * allocating bigger ones if necessary and then flips and returns * the last allocated char buffer. */ def flush(decoder: CharsetDecoder, chars: CharBuffer): CharBuffer = { val result: CoderResult = decoder.flush(chars) if (result.isUnderflow()) { chars.flip() chars } else { if (result.isError()) throw new IOException(result.toString()) assert(result.isOverflow()) flush(decoder, increaseCapacity(chars)) } } /** * Flips the specified buffer and returns a new one with the same * content but with an increased capacity. */ private def increaseCapacity(buffer: CharBuffer): CharBuffer = { buffer.flip() val capacity = 2 * buffer.capacity() CharBuffer.allocate(capacity).put(buffer) }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?