读取本文部分数据变为byte数组,如何防止字符被拆开?

Jobernowl 2011-11-17 03:45:55
如题。具体情形是:我要读取一个大文本,于是每次读取一小部分(假设每次读取58kb),读取出来的形式是byte数组,然后再把byte数组转化为String。现在遇上的问题是一些特殊编码如unicode最开始读取到的58kb数据不是乱码,但是往后都是乱码了。经过查找资料得知,原因是unicode一个字符要占几个字节吧,由于我分块读取所以把分界点的字符拆开了,比如只读取了半个字符。应该这就是问题所在了吧。现在我考虑的办法是分析每块读取的byte数组最后长度为10的一部分如果没有半个字符就读完,如果有半个字符就归到下一块。只是我不知该如何区分,求助。或者你们觉得我的想法有错或者有更好的想法也可以提出来。编码类型现在考虑到的有UNICODE、UTF-16BE、UTF-16LE。值得注意的是现在我已经能判断这几种编码类型了,所以问题仅仅有以上所说的
...全文
709 49 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
49 条回复
切换为时间正序
请发表友善的回复…
发表回复
绿领巾童鞋 2011-12-05
  • 打赏
  • 举报
回复
...统一一下字符类型,省事
杜尚奎 2011-12-05
  • 打赏
  • 举报
回复
String(char[],offset,size)
jacklondon 2011-12-05
  • 打赏
  • 举报
回复
FileInputStream stream = new FileInputStream("filepath");
String charsetName = "utf-8";
InputStreamReader reader = InputStreamReader(stream , String charsetName);
BufferedReader in = new BufferedReader(reader);
while((String line = in.readLine())!=null){
...
}
in.close();
stream.close();
富兰克陈 2011-12-05
  • 打赏
  • 举报
回复
用字符流,str.toCharArray().length<str.getBytes().length,说明存在占两个字节的中文或其它字符,那你就需要一个个排查,再分开它们了了
lfp001 2011-11-23
  • 打赏
  • 举报
回复
11楼的代码不能实现你的需求吗?

建议你停下来去看看JDK源码,你会发现读取不同字符集的文件是怎么实现的。

你似乎很执着,非得读到byte[]检测“半个字符”之类。先前我在7L说了,按你的思路,要自己编写代码从底层实现,例如你读入58K到byte[],得从byte[]起始处检测,其实JDK现成的方法也是这么干的,你这么绕来绕去的,何不直接用它给你提供的现成的方法呢?

涉及这些比较底层的东西,停下来去看看JDK相应的源码比较好。如果你不能确保写出比它更好的实现代码,还是用它给你提供的现成的方法比较好一点。
Jobernowl 2011-11-23
  • 打赏
  • 举报
回复
详情请看 这个是我做的 那个东西留着很多bug没解决 现在只剩下这个大bug没解决了 不解决都不好意思更新了http://www.anzhi.com/soft_84133.html
Jobernowl 2011-11-23
  • 打赏
  • 举报
回复
[Quote=引用 39 楼 lfp001 的回复:]
11楼的代码不能实现你的需求吗?

建议你停下来去看看JDK源码,你会发现读取不同字符集的文件是怎么实现的。

你似乎很执着,非得读到byte[]检测“半个字符”之类。先前我在7L说了,按你的思路,要自己编写代码从底层实现,例如你读入58K到byte[],得从byte[]起始处检测,其实JDK现成的方法也是这么干的,你这么绕来绕去的,何不直接用它给你提供的现成的方法呢?

涉及这些比较……
[/Quote]

首先 我可能必须要读取为byte了 因为我提供了一个功能 允许用户随时更改编码格式 我不是把string。getbyte的 而是使用当前缓存的byte数组来允许用户任意构造任意编码的text 这样能确保准确与快速 其次我用到了MappedByteBuffer来很方便很快速地任意读取某一块内容的 输入流要求有getChannel()这个方法才能获得MappedByteBuffer的实例。
junerkele 2011-11-23
  • 打赏
  • 举报
回复
大哥竟然对编码如此了解,佩服之至啊
[Quote=引用 36 楼 sasuke38 的回复:]

引用 32 楼 magong 的回复:
第二页乱码问题,不知道你有没有确保data的起始是正确的,包括首字符不残缺,也包括FEFF前缀。


feff前缀是啥意思 还有就是我写错了 没想得到会遇上没匹配到换行符的情况 应该加个判断什么的

引用 35 楼 CherryMs 的回复:
楼主这语气让人有点……


--signature--------------------
http://www.lunwenwa.com/


哎 当时我太着急了 因为我几乎每次都遇上别人问我干啥的 为……
[/Quote]
冰红茶盖 2011-11-22
  • 打赏
  • 举报
回复
坐看楼主和大大交流。虽然很多一下子看不懂...
jingluo 2011-11-22
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 magong 的回复:]

如果只是你顶楼提到的那几种编码,它们有个特点就是总是偶数字节编码的(不论中英文),
所以只要你的切块是偶数字节大小,不可能有字符断在切块之间。
[/Quote]

UNICODE、UTF-16BE、UTF-16LE 都是2byte一个字符
magong 2011-11-22
  • 打赏
  • 举报
回复
第二页乱码问题,不知道你有没有确保data的起始是正确的,包括首字符不残缺,也包括FEFF前缀。
magong 2011-11-22
  • 打赏
  • 举报
回复
你程序我看了,有一个问题就是
如果没匹配上最后应该返回0而不是全部长度。
Jobernowl 2011-11-22
  • 打赏
  • 举报
回复
[Quote=引用 37 楼 magong 的回复:]
引用 36 楼 sasuke38 的回复:

feff前缀是啥意思


UTF-16编码的前缀啊。你程序中不是体现到你知道这一点的嘛。
[/Quote]
没有 关于这方面的我一无所知
magong 2011-11-22
  • 打赏
  • 举报
回复
[Quote=引用 36 楼 sasuke38 的回复:]

feff前缀是啥意思

[/Quote]
UTF-16编码的前缀啊。你程序中不是体现到你知道这一点的嘛。
Jobernowl 2011-11-22
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 magong 的回复:]
第二页乱码问题,不知道你有没有确保data的起始是正确的,包括首字符不残缺,也包括FEFF前缀。
[/Quote]

feff前缀是啥意思 还有就是我写错了 没想得到会遇上没匹配到换行符的情况 应该加个判断什么的

[Quote=引用 35 楼 CherryMs 的回复:]
楼主这语气让人有点……
[/Quote]

哎 当时我太着急了 因为我几乎每次都遇上别人问我干啥的 为什么要那样做,我就急了 。况且世界上那么多人怎么能都问呢 而且无奇不有是不是?很多情况是我们想不到的 因为不是当事人啊
CherryMs 2011-11-22
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 sasuke38 的回复:]
我就是用nio 内存映射 我读取的是1Gb的文本 请大家不要管其他事了 这样子做都是别人的特殊要求你们自己当然不能理解了 因为你们不是本人 请帮一下忙
[/Quote]
楼主这语气让人有点……
Jobernowl 2011-11-21
  • 打赏
  • 举报
回复
因为我发现如果\n前面没有内容的话会跟有内容的情形不一样 所以我就自己加了内容进去 然后再把\n的字节截取出来
Jobernowl 2011-11-21
  • 打赏
  • 举报
回复
我测试的文件内容是中英混合的,不是单纯的英文或者中文
Jobernowl 2011-11-21
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 magong 的回复:]
引用 24 楼 magong 的回复:

不错啊。记得测试下每种charset下不同的换行符字节序列啊,免得破坏换行符。
还有考虑不同OS上的换行符不同的问题。

不好意思,仔细想了下,发现认换行符还是不行的,如以下UTF-16编码序列:
0x53, 0, 0x0A, (byte)0xA0
是两个合法Unicode字符“匀ઠ”
但是其中0, 0x0A子串就是换行符。
尽管这种字符……
[/Quote]

呵呵 你多虑了。首先换行符是唯一的,即使亿分之一的概率出现和换行符字节相同的字符那也是没关系的。因为换行符不是必须的。1.首先残缺字符肯定是在结尾;2.残缺字符的字节数组中不可能包含换行符。
所以我的方案是完美的。
按照约定先奉上我的代码

public int newLength(byte[] data,String charset){
String lastStr=" \n";
String nullStr=" ";
byte[] array=null;
byte[] nullByte=null;
try {
array=lastStr.getBytes(charset);
nullByte=nullStr.getBytes(charset);

} catch (UnsupportedEncodingException e) {
}
if(null!=array){
boolean flag=true;
int len1=data.length;
int len2=array.length;
byte[] temp=new byte[len2-nullByte.length];
System.arraycopy(array, nullByte.length, temp, 0, temp.length);
System.out.println("Array"+Arrays.toString(temp));
len2=temp.length;
int j=len2-1;
for(int i=len1-1;i>-1;i--){
flag=true;
if(j>-1&&data[i]==temp[j]){
j--;
}
else{
flag=false;
j=len2-1;
}
if(j==-1&&flag){
array=null;
nullByte=null;
return i+len2;
}
}
}
array=null;
nullByte=null;
return data.length;
}

写得很罗嗦。我试了一下,结果第二页中英文不会出现乱码了(比之前好多了),但是中文出现乱码,翻回第一页正常。想不明白为什么,求各位大大赐教。难道说我的方案哪里还有漏洞么?还是代码写错了?
magong 2011-11-21
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 sasuke38 的回复:]
首先换行符是唯一的,即使亿分之一的概率出现和换行符字节相同的字符那也是没关系的。因为换行符不是必须的。

1.首先残缺字符肯定是在结尾;2.残缺字符的字节数组中不可能包含换行符。

我试了一下,结果第二页中英文不会出现乱码了(比之前好多了),但是中文出现乱码,翻回第一页正常。
[/Quote]
换行符可以不是必须的,但是错误识别出来的“换行符”前后被破坏的其他字符是否是必须的呢。
如果你是任意切块,随机进入任意一块的话,残缺字符可能也出现在块的头部。
OK,26楼所举例子确实是极端情况,不太会出现。怕的就是某日它真的出现了。就不和你讨论这个了,反正你也知道了。

至于你的程序,
你的nullStr和lastStr为什么都要包含一个空格呢?
加载更多回复(25)

62,630

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧