引入字符集编码信息的一些实践--乱码探源(3)

摘要: 介绍了两种引入编码信息的实践, 变相引入及外部指定.

前面说到, 文本文件中没有编码信息, 导致了各种混乱, 那么, 最关键的就是要指定好所用的编码信息. 具体地讲, 有以下一些途径.

变相引入

什么是变相引入呢? 其实本质与前面提到的一些"文件头"信息是类似的.

xml

我们来看看 xml 文件的例子, 你通常能在最开始看到这样的一行:

<?xml version="1.0" encoding="UTF-8"?>

那么这里面, encoding 指明的就是所用编码的信息了. 可是, 等等!! 为了得到这一编码信息, 我得先读取这一文件;可要正确读取文件, 我又要先知道编码信息!

这成了一个鸡生蛋, 蛋生鸡, 又或者说是先有鸡还是先有蛋的问题了.

怎么破呢? 考虑这一行信息所有字符都是 ASCII 中的字符, 那么我们可以先使用最基础的 ASCII 去读取它开头的一些信息, 获取到这一编码信息后, 再次用这一编码去读取文件即可.

ASCII 可谓是这样一个始祖鸟或者始祖蛋一样的存在.

可以动动手做些实验, 先建立一个 xml 文件, 比如就叫 foo.xml

foo.xml

继续阅读

确定文本文件的字符集编码--乱码探源(2)

摘要: 介绍了如何去确定一个文本文件所使用的编码, 特别地以记事本保存"联通"为例进行了深入分析.

在上一篇中, 探讨了文件名编码以及非文本文件中的文本内容的编码, 在这里, 将介绍更为重要的文本文件的编码.

混乱的现状

设想一下, 如果在保存文本文件时, 也同时把所使用的编码的信息也保存在文件内容里, 那么, 在再次读取时, 确定所使用的编码就容易多了.

很多的非文本文件比如图片文件通常会在文件的头部加上所谓的 "magic number(魔法数字)" 来作为一种标识.

所谓的 "magic number", 其实它就是一个或几个固定的字节构成的固定值, 用于标识文件的种类(类似于签名).

比如 bmp 文件通常会以 "42 4D" 两字节开头.

又比如 Java 的 class 文件, 则是以四字节的 "ca fe ba be" 打头. (咖啡宝贝? )

java class magic number

即便没有文件后缀名, 根据这些信息也是确定一个文件类型的手段.

附: 关于用 Notepad++ 查看十六进制的问题, 这是一个插件, 如果没有装, 菜单--插件--plugin manager--available--HEX-Editor, 装上它.

装上后, 它通常在工具栏的最右边, 一个黑色的大写的斜体的"H"就是它. 单击它可以在正常文本与 16 进制间切换. 要进一步查看二进制, 在文本区, 右键--view in--to binary.

继续阅读

文件, 文本文件以及编码--乱码探源(1)

摘要: 介绍了文件名在操作系统中的编码, 以及一些非文本文件中的文本内容所用的编码.

在前面的字符集编码系列中, 已经探讨了几大主要的字符集编码. 在此基础之上, 这里将进一步探讨编码的应用及乱码的根源, 我们先从基本的文件说起.

文件

文件(内容)就是字节序列. 文本文件也是文件, 所以它也是字节序列.

文件名与文件内容

通常说到文件时, 指的是 文件内容, 但文件还有 文件名, 文件名与文件内容是分开存储的. 你可以在硬盘上新建一个文件, 它的大小为 0. 如下:

大小为0的新建文本文档

但它是有文件名的, 比如上述的"新建文本文档.txt", 保存这些名字自然也要占用空间, 只不过它与文件内容是分离的.

这些由操作系统的文件系统模块负责.

继续阅读

递归解决换零钱问题--回顾总结之递归的表达能力

摘要: 关于递归表达能力的一个总结.

前面为了保持叙述的流畅, 没有做太多的引申, 把总结推迟到了后面.

补上一些总结, 以防止出现 "下面呢? 下面没有了" 的尴尬.

方向性问题

虽然题目在一开始就暗示了这一点, 但首先, 我们还是要问, 它能用递归解决吗?

有点怀疑精神是好的, 既要低头走路, 更要抬头看路, 以防止发生方向性错误, 导致缘木求鱼的后果.

说这个问题能用递归解决, 这种信心或者判断的依据来自于哪呢?

有人可能知道了, 换零钱这个问题在<<计算机程序的构造和解释>>(SICP: Structure and Interpretation of Computer Programs)一书有这个例子, 而在书上是用递归来解决的.

继续阅读

关于 Java 的线程状态

摘要: 初步谈论了Java中的6种线程状态, 并探讨了它们与操作系统线程状态的异同.

Java 线程有 6 种状态. 在某个给定时间点上, 一个线程只能处于这 6 种状态中的一种.

线程状态的枚举: Thread.State

这 6 种状态被明确地定义在 Thread 类的一个内部枚举类 Thread.State 中:

java 线程状态内部枚举类 Thread.State

它们是:

  • NEW (新建) A thread that has not yet started is in this state.
  • RUNNABLE (可运行) A thread executing in the Java virtual machine is in this state.
  • BLOCKED (阻塞) A thread that is blocked waiting for a monitor lock is in this state.
  • WAITING (等待) A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
  • TIMED_WAITING (计时等待) A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
  • TERMINATED (终止) A thread that has exited is in this state.

注: 以上内容直接来自 State 类中的 Javadoc, 只对状态进行了翻译, 具体的描述后面再分析.

它上面还有个注解 @since 1.5, 暗示了在 JDK1.5 时引入了这些定义.

因此, 说有 6 种线程状态是对 1.5 及以后版本而言.

Thread 类中有一个方法 getState, 返回的就是这里定义的状态.

可用于监控工具分析线程状态, 不作同步工具使用.

继续阅读