刚写了一个小应用,其中有个从文件读取数据转换后存入数据库的功能,代码见
https://github.com/itang/_demo/blob/master/pagingtree/src/main/scala/pagingtree/plugins/DataPlugin.scala, 在ubuntu下运行正常,windows下出现编码问题,编码为utf-8的文件读取不了。
定位到的出错语句是:
val regionData = fromLines(Source.fromInputStream(RegionDataImporter.getClass.getResourceAsStream("/data/region.txt")).getLines.toList
注意到Source.fromInputStream方法, 我这使用的应该是
def fromInputStream(is: InputStream)(implicit codec: Codec): BufferedSource
(fromInputStream另外一个定义是: def fromInputStream(is: InputStream, enc: String): BufferedSource)
显然第二个参数使用了隐式参数, 由此猜想这个隐式参数值跟平台有关。要弄清楚, 只有翻scala源码了。
按常理,先找到Source的源码, 猜想在某处导入了 implicit defaultCodec = Codec.xxx 之类。意外的是Source里未定义它,而且也未通过import XX._ 导入。
进一步判断是不是在scala.Predef 全局导入了。查找了Predef的源码,也未发现。有点诧异。难道scala有什么诡异的实现?
没办法,掉个方向,看看
scala.io.Codes源码里有什么玄机没。下面这几行代码引起了我的注意:
trait LowPriorityCodecImplicits {
self: Codec.type =>
/** The Codec of Last Resort. */
implicit def fallbackSystemCodec: Codec = defaultCharsetCodec
}
object Codec extends LowPriorityCodecImplicits {
...
def defaultCharsetCodec = apply(Charset.defaultCharset)
...
}
LowPriorityCodecImplicits 这个trait里声明了Codes的隐式参数值fallbackSystemCodec,而Codes对象继承了LowPriorityCodecImplicits。
但是感觉有点不对劲,Source源码里应该导入它啊,就如:
import Codes._
猜想:
难道类的半生对象里定义了其类型的隐式参数值, 不需要显式导入就可以被隐式引用吗?
带着这个疑问, 写了如下一些代码来验证之:
test.scala
-------------------
class A { override def toString = "A"}
trait T {
implicit def a = new A
}
object A extends T { } // T.a 混入 object A
def a(implicit pa: A) = pa
println(a) // 打印出 "A"
其效果跟如下代码是一样的:
class A { override def toString = "A"}
implicit def a = new A
def a(implicit pa: A) = pa
println(a) // 打印出 "A"
算是知道这么回事了(还是觉得scala如此处理有点诡异),那编码问题的密码完全归结到java.nio.charset.Charset.defaultCharset方法了,看其源码:
public static Charset defaultCharset() {
if (defaultCharset == null) {
synchronized (Charset.class) {
//从系统属性里读出file.encoding配置的值
//即System.getProperty("file.encoding");
String csn = AccessController.doPrivileged(
new GetPropertyAction("file.encoding"));
Charset cs = lookup(csn);
if (cs != null)
defaultCharset = cs;
else
defaultCharset = forName("UTF-8");
}
}
return defaultCharset;
}
答案浮出水面了,
ubuntu下 文件编码默认为UTF-8, windows xp下是GBK。这就是fromInputStream(is: InputStream)(implicit codec: Codec)第二个参数使用隐式值之后造成的后果。
前前后后的分析、猜想论证,总结出以下几条:
- scala.io.Source.fromInputStream(包括fromFile等)等方法第二个参数最好显显式的指定编码, 这样才不会受系统环境差异的影响
如Source.fromURL(new URL("http://www.baidu.com"), "GBK")
- 如果类的半生对象里定义了其类型的隐式参数值, 那么此隐式参数值不需要显式导入就可以被引用到
分享到:
相关推荐
资源分类:Python库 所属语言:Python 资源全名:flake8-no-implicit-concat-0.2.1.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
1. 半隐式数值方案(Semi-implicit Numerical Scheme):这是一种数值计算方法,用于模拟反应流中的动态燃烧过程。半隐式方法在时间积分过程中对某些项使用显式计算,而对其他项使用隐式计算。这种方法可以平衡计算...
实测可用
实测可用
实测可用
实测可用
实测可用
在Scala编程语言中,隐式转换(Implicit Conversion)是一种强大的特性,它允许我们不显式地将一个类型的值转换为另一个类型。隐式转换在某些特定情况下非常有用,例如当两个不兼容的类型需要一起工作时,或者为了...
2.2.3 Source code order.............................................................................................17 2.2.4 Coding guidelines for importing packages into $unit ..........................
PART I: VXBUS FUNDAMENTALS 1 Getting Started with Device Driver Development .................................... 3 1.1 About Device Drivers ...............................................................
《Level Set Methods And Dynamic Implicit Surfaces》是一本由流体动力学领域的权威专家Ronald Fedkiw撰写的著作,深入探讨了level set方法在处理动态隐式表面问题上的应用。这本书是研究流体力学、计算几何以及...
本文的标题《Combining Explicit and Implicit Feature Interactions for Recommender Systems.pdf》和描述表明,文章主题聚焦于推荐系统领域,并且探讨了如何结合显式和隐式的特征交互。这方面的研究对于理解和改善...
Contents Preface . . . . . . . . ....1 Introduction ....2 Sets ....3 Matrices: addition and multiplication ....4 The transpose of a matrix ....5 Square matrices ....6 Linear forms and quadratic forms ....
Contents Preface . . . . . . . . ....1Introduction ....2Sets ....3Matrices: addition and multiplication ....4The transpose of a matrix ....5Square matrices ....6Linear forms and quadratic forms ....7The rank of a matrix ....
当一个类或结构定义了一个`implicit operator`时,C#编译器会自动在满足条件的情况下执行这种转换。这种方式通常用于转换可能导致数据丢失风险较小的操作,因为编译器不会发出警告。 例如,我们可以定义一个`...
`public static implicit operator float(currency value)` 在 C# 中定义了一个隐式类型转换操作符,它允许从自定义类型`currency`隐式转换为`float`类型。这种转换方式可以使代码更加简洁,但在使用时也需要注意...
在MySQL 5.6版本中,当你安装或升级数据库系统时,可能会遇到一个警告提示:“TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see ...
Source Code for Hello World with Pygame ................................................................................ 7 Setting Up a Pygame Program ....................................................
在Python的推荐系统领域,`Implicit`库是一个非常重要的工具,尤其对于处理隐式反馈数据集,如用户浏览记录、点击行为等。隐式反馈数据集的特点是它们并不直接表示用户的喜好,而是通过用户的行为间接推断。例如,...