赞 | 2 |
VIP | 143 |
好人卡 | 1 |
积分 | 1 |
经验 | 216792 |
最后登录 | 2019-10-10 |
在线时间 | 24 小时 |
Lv1.梦旅人
- 梦石
- 0
- 星屑
- 61
- 在线时间
- 24 小时
- 注册时间
- 2008-8-5
- 帖子
- 1924
|
才发现这贴,来晚了……
- 第一行空出一个字的问题是这样的:程序读取文本时需要事先知道它的编码方式,所以一般会在文件头写入一个表示了编码方式的记号,而我们的 UTF-8 字符集编码就是在文件开头写入这么个三字节的记号:0xEFBBBF。这个脚本在读取的时候把这个记号也读入了,并且和其它汉字一样占 3 个字节,所以最后看到的第一行空出了一个字实际上就是因为脚本还读取了这个记号,而记号在字符集中并不表示任何字符,因此整个字符串的描绘都向左移了~
解决方法就是在 file = File.open(filename, "r") 这一行下面、IO 对象初始化之后加一句:
file.seek(3),让输入流从第三个字节开始输入,跳过三字节的 UTF-8 编码记号 - 要弄清楚第二个问题就要先搞懂 UTF-8 相关的一些知识:
首先,在 UTF-8 编码规范中,汉字是被编码为三个字节的,ASCII 字符则仍然是一个字节~这个图书馆脚本本来用的是 75 这个数,一行刚好可以显示 25 个汉字,而你的 82 不是 3 的倍数,显然不对,除非你每一行都刚好有奇数数量个 ASCII 字符,这样就可以凑出 (3 的倍数的字节)+(奇数数量的字节) = 82
由于你一开始就把汉字的字节数记错了,所以自然对第二个问题百思不得其解——
三个半角字符加上其它汉字,最后还是 3 的倍数,所以不会出现在一个完整的三字节汉字之间断开的情况;
四个半角字符加上其它汉字,最后是 3 的倍数 + 1,这样一来就读取了本来应该是下一行第一个汉字的两个字节,这两个字节当然是不完整的,所以下一行的第一个汉字就没有描绘出来;
问题行删去一个半角字符,刚好是 3 的倍数,所以没有问题;
在被吞掉的字前面加一个半角空格,就相当于一行里面有了 5 个半角字符,最后就成了 3 的倍数 + 2,这样就会读取到下一行第一个汉字的一个字节,所以也是不完整的~如果加上两个半角空格,自然就有效了(当然这个脚本会把两个半角空格转换成一个全角的 =v=)
解决方法呢,简单点可以让这个脚本计算 UTF-8 字符集的字符个数,而不是实际的字节数——也就是说,要固定一行显示 25 个 UTF-8 字符,而不是 75 个字节。只要把
text = temp_story.slice!(0,75)
这一行改为:
text = temp_story.slice!(/.{25}?/)
即可~
这个方法有它的弊端,ASCII 字符宽度和汉字不一样,也不知道每个字符是不是固定宽度的,所以当英文啊数字啊很多的时候,一行就可能出现末尾空一大堆(因为 ASCII 字符宽度 < 汉字)
要弄到完美的话,只能像 Window_Message 那样一个一个计算字符的宽度,算出一行中能容纳的最长的字符串……
给一段例子代码好了(替换 update1 中的 for ... end),没有深入测试,参考大致的算法思路就行了:- (ref_bmp = @read_window.contents).font.size = 20
- for fileline in r
- chars = fileline.scan(/./)
- chars_copy = chars.clone
- len = width = 0
- for char in chars_copy
- width += ref_bmp.text_size(char).width
- if width > 508
- @real_text.push(chars.slice!(0, len).join)
- width = len = 0
- redo
- end
- len += 1
- end
- @real_text.push(chars.join)
- end
复制代码
|
|