首页 新闻 会员 周边

要把txt文件以默认gbk编码的内容,用utf-8编码写入另外一个文件时出现意外。但是用utf-16却正常。求大牛解

0
悬赏园豆:50 [已解决问题] 解决于 2015-01-20 11:56
  1 package com.test.file;
  2 
  3 import java.io.BufferedInputStream;
  4 import java.io.BufferedReader;
  5 import java.io.DataInputStream;
  6 import java.io.FileInputStream;
  7 import java.io.FileOutputStream;
  8 import java.io.IOException;
  9 import java.io.InputStreamReader;
 10 import java.io.OutputStreamWriter;
 11 import java.io.Writer;
 12 
 13 public class FileRW {
 14     public static void main(String[] args) {
 15         String file_utf = "D:/eclipse/workspace/javaFileTest/test-utf.txt";
 16         codeString(file_utf,true);
 17         getFileContent(file_utf,false);
 18 
 19         String file_gbk = "D:/eclipse/workspace/javaFileTest/test-gbk.txt";
 20         String file_gbk_utf_8 = "D:/eclipse/workspace/javaFileTest/test-gbk-utf-8-error.txt";
 21         String file_gbk_utf_16 = "D:/eclipse/workspace/javaFileTest/test-gbk-utf-16-ok.txt";
 22         
 23         transferFile(file_gbk,file_gbk_utf_8,"utf-8");
 24         transferFile(file_gbk,file_gbk_utf_16,"utf-16");
 25         
 26         codeString(file_gbk,true);
 27         getFileContent(file_gbk,false);
 28         
 29         codeString(file_gbk_utf_8,true);
 30         getFileContent(file_gbk_utf_8,false);
 31         
 32         codeString(file_gbk_utf_16,true);
 33         getFileContent(file_gbk_utf_16,false);
 34     }
 35 
 36     private static void getFileContent(String filePath,boolean forceCode)
 37     {
 38         try{
 39         String line_separator = System.getProperty("line.separator");
 40         FileInputStream fis = new FileInputStream(filePath);
 41         StringBuffer content = new StringBuffer();
 42         DataInputStream in = new DataInputStream(fis);
 43         String code = codeString(filePath,false);
 44         BufferedReader d = null;
 45         if (forceCode) {
 46             d = new BufferedReader(new InputStreamReader(in, "UTF-8"));
 47         } else {
 48             d = new BufferedReader(new InputStreamReader(in, code));
 49         }
 50         String line = null;
 51         while ((line = d.readLine()) != null)
 52             content.append(line + line_separator);
 53         d.close();
 54         in.close();
 55         fis.close();
 56       System.out.println(content);
 62         }catch(IOException e){
 63             System.out.println("获取文件内容异常");
 64         }
 65     }
 66     
 67     private static void transferFile(String srcFileName, String destFileName,String codeOuput) {
 68         try {
 69              String line_separator = System.getProperty("line.separator"); 
 70               FileInputStream fis = new FileInputStream(srcFileName);
 71               StringBuffer content = new StringBuffer();
 72               DataInputStream in = new DataInputStream(fis);
 73               String codeInput = codeString(srcFileName,false);
 74               BufferedReader d = new BufferedReader(new InputStreamReader(in, codeInput));// , "UTF-8"  
 75               String line = null;
 76               while ((line = d.readLine()) != null)
 77                content.append(line + line_separator);
 78               d.close();
 79               in.close();
 80               fis.close();
 81               Writer ow = new OutputStreamWriter(new FileOutputStream(destFileName), codeOuput);
 82               ow.write(content.toString());
 83               ow.close();
 84             System.out.println("写入完成!");
 85         } catch (Exception e) {
 86             System.out.println("文件编码转换异常");
 87         }
 88     }
 89 
 90     /**
 91      * 判断文件的编码格式
 92      * 
 93      * @param fileName
 94      *            :file
 95      * @return 文件编码格式
 96      * @throws Exception
 97      */
 98     public static String codeString(String fileName,boolean print) {
 99         String return_value = "";
100         try {
101             BufferedInputStream bin = new BufferedInputStream(
102                     new FileInputStream(fileName));
103             
104             int p = (bin.read() << 8) + bin.read();
105             
106             String code = null;
107 
108             switch (p) {
109             case 0xefbb:
110                 code = "UTF-8";
111                 break;
112             case 0xfffe:
113                 code = "Unicode";
114                 break;
115             case 0xfeff:
116                 code = "UTF-16BE";
117                 break;
118             case 0x5c75:
119                 code = "ANSI|ASCII";
120                 break;
121             default:
122                 code = "GBK";
123             }
124 
125             return_value = code;
126         } catch (Exception e) {
127             System.out.println("获取文件编码类型失败");
128         }
129         if (print)
130             System.out.println(fileName + " code:" + return_value);
131         return return_value;
132     }
133 
134 }
问题补充:

异常描述:

当用utf-16写入文件时,可以判断该文件的编码格式为utf-16,并且可以用utf-16的编码正确读出此文件。

当用utf-8写入文件时,判断该文件的编码格式却是gbk。但是如果用gbk编码去读文件内容,出现乱码。用utf-8编码读取时正常。

综上,我的疑问就是----------为什么用utf-8编码写入文件后,该文件的编码格式却是gbk。

求大牛。。。。。。。

yi-的主页 yi- | 初学一级 | 园豆:159
提问于:2015-01-20 01:27
< >
分享
最佳答案
0

有些utf-8的文件是没有BOM(Byte Order Mark,就是字节序标记)的,所以你判断的时候使用BOM来判断,自然就判断错了

收获园豆:10
诶碧司 | 小虾三级 |园豆:1912 | 2015-01-20 09:05

只需判断txt文件。

可以实测,txt文件另存为utf-8,再用此程序跑一下。你就会发现结果的。

yi- | 园豆:159 (初学一级) | 2015-01-20 09:59

@扛着西瓜刀的老鼠: 你用transferFile(file_gbk,file_gbk_utf_8,"utf-8");保存文件的时候,应该是不带BOM的,所以才判断不了

你说的实测,是指在系统自带的notepad打开,并另存为utf-8吗?如果是,那么当然可以判断,因为notepad另存为utf-8的时候会带BOM

诶碧司 | 园豆:1912 (小虾三级) | 2015-01-20 12:12

@诶碧司: 恩,是这样的。

现在的功能是需要将txt转为pdf文档。但是发现gbk编码的txt无法转换。

而utf-8编码的(带bom)才可以转换。

怎么写入utf-8时带上bom呢。

-------废话-----》结帖时过早了。发现加上bom头还是不对,文件后面还有一个特殊尾巴不好处理。

那么怎么写入时加上bom尾呢。求赐教

yi- | 园豆:159 (初学一级) | 2015-01-20 15:52

@诶碧司: 

加上bom的byte就可以了,之前加错编码了。

多谢你。

yi- | 园豆:159 (初学一级) | 2015-01-20 16:02
其他回答(2)
0

编码使用错了,读出的内容肯定会乱码

你在windows下可以使用UltraEdit获取其他工具查看文件的二进制内容

至于文件开头的FEFF这个标识是针对文本文件加的编码识别标识

UTF-8下汉字一般3个字节,GBK汉字2个字节,这些交错使用肯定就乱码了

收获园豆:40
2012 | 园豆:21230 (高人七级) | 2015-01-20 09:06

编码怎么错了。

转码的思路我是这样理解的:

 

gbk<------可逆过程------->unicode(java String)<------可逆过程------->utf-8。

哪有问题,求赐教。

支持(0) 反对(0) yi- | 园豆:159 (初学一级) | 2015-01-20 10:07
0

将文本内容以utf-8编码写入txt文本时,只是写入文本本身的utf-8编码内容。

通过导出txt文本的二进制数据,发现txt二进制数据前24表示此txt的编码方式。

那么将gbk编码的txt文档转换到utf-8编码的txt文档就有了方法。

--------->

二级制数据读写流:写入“111011111011101110111111”加上原文件内容的二进制流

yi- | 园豆:159 (初学一级) | 2015-01-20 11:55

你写入的“111011111011101110111111”,就是utf-8的BOM,三个字节的值”ef bb bf“

支持(0) 反对(0) 诶碧司 | 园豆:1912 (小虾三级) | 2015-01-20 12:15
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册