精华内容
下载资源
问答
  • 全自动识别文件编码转换成无bom头的UTF8文件 全自动识别文件编码转换成无bom头的UTF8文件
  • 最近在项目开发过程中遇到一个编码上的问题,原流程是用户上传csv数据并对数据入库。...我们日常用到的编码格式大体就那么几种,最常见的有UTF-8(带BOM)、UTF-8无BOM、GBK。其中UTF-8(带BOM)的最好区分,从文件头拿三

    最近在项目开发过程中遇到一个编码上的问题,原流程是用户上传csv数据并对数据入库。我们不知道用户会使用哪种编码的格式进行文件上传,而直接规定用户必须使用固定编码进行上传又感觉不够友好。所以需要我们程序要能识别出来文件的编码格式,并进行相应的处理。

    我们日常用到的编码格式大体就那么几种,最常见的有UTF-8(带BOM)、UTF-8无BOM、GBK。其中UTF-8(带BOM)的最好区分,从文件头拿三个字符就能判断出来,这里不做过多说明。重点是UTF-8无BOM和GBK格式的区分。怎么区分从网上可以查到一些资料,我使用的是通过UTF-8的编码规则进行判断。读取字节,如果不符UTF-8规则,立马返回,判断出结果。如果相符,则继续判断,有可能会一直持续到文件最后才能出结果。如果全是单字节的话,就无所谓是UTF-8还是GBK,都可以解析出来。

    下面我来分享我封装的工具类,有问题的话,欢迎留言。

    package com.xxxx.common.utils;
    
    import lombok.Cleanup;
    import lombok.NonNull;
    import lombok.extern.slf4j.Slf4j;
    
    import java.io.*;
    import java.util.BitSet;
    
    /**
     * 编码工具类,主要用于识别UTF8、UTF8 BOM、GBK
     * Created by dongp on 2018/1/9.
     */
    @Slf4j
    public class EncodeUtils {
        private static int BYTE_SIZE = 8;
        public static String CODE_UTF8 = "UTF-8";
        public static String CODE_UTF8_BOM = "UTF-8_BOM";
        public static String CODE_GBK = "GBK";
    
        /**
         * 通过文件全名称获取编码集名称
         *
         * @param fullFileName
         * @param ignoreBom
         * @return
         * @throws Exception
         */
        public static String getEncode(String fullFileName, boolean ignoreBom) throws Exception {
            log.debug("fullFileName ; {}", fullFileName);
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fullFileName));
            return getEncode(bis, ignoreBom);
        }
    
        /**
         * 通过文件缓存流获取编码集名称,文件流必须为未曾
         *
         * @param bis
         * @return
         * @throws Exception
         */
        public static String getEncode(@NonNull BufferedInputStream bis, boolean ignoreBom) throws Exception {
            bis.mark(0);
    
            String encodeType = "";
            byte[] head = new byte[3];
            bis.read(head);
            if (head[0] == -1 && head[1] == -2) {
                encodeType = "UTF-16";
            } else if (head[0] == -2 && head[1] == -1) {
                encodeType = "Unicode";
            } else if (head[0] == -17 && head[1] == -69 && head[2] == -65) { //带BOM
                if (ignoreBom) {
                    encodeType = CODE_UTF8;
                } else {
                    encodeType = CODE_UTF8_BOM;
                }
            } else if ("Unicode".equals(encodeType)) {
                encodeType = "UTF-16";
            } else if (isUTF8(bis)) {
                encodeType = CODE_UTF8;
            } else {
                encodeType = CODE_GBK;
            }
            log.info("result encode type : " + encodeType);
            return encodeType;
        }
    
        /**
         * 是否是无BOM的UTF8格式,不判断常规场景,只区分无BOM UTF8和GBK
         *
         * @param bis
         * @return
         */
        private static boolean isUTF8(@NonNull BufferedInputStream bis) throws Exception {
            bis.reset();
    
            //读取第一个字节
            int code = bis.read();
            do {
                BitSet bitSet = convert2BitSet(code);
                //判断是否为单字节
                if (bitSet.get(0)) {//多字节时,再读取N个字节
                    if (!checkMultiByte(bis, bitSet)) {//未检测通过,直接返回
                        return false;
                    }
                } else {
                    //单字节时什么都不用做,再次读取字节
                }
                code = bis.read();
            } while (code != -1);
            return true;
        }
    
        /**
         * 检测多字节,判断是否为utf8,已经读取了一个字节
         *
         * @param bis
         * @param bitSet
         * @return
         */
        private static boolean checkMultiByte(@NonNull BufferedInputStream bis, @NonNull BitSet bitSet) throws Exception {
            int count = getCountOfSequential(bitSet);
            byte[] bytes = new byte[count - 1];//已经读取了一个字节,不能再读取
            bis.read(bytes);
            for (byte b : bytes) {
                if (!checkUtf8Byte(b)) {
                    return false;
                }
            }
            return true;
        }
    
        /**
         * 检测单字节,判断是否为utf8
         *
         * @param b
         * @return
         */
        private static boolean checkUtf8Byte(byte b) throws Exception {
            BitSet bitSet = convert2BitSet(b);
            return bitSet.get(0) && !bitSet.get(1);
        }
    
        /**
         * 检测bitSet中从开始有多少个连续的1
         *
         * @param bitSet
         * @return
         */
        private static int getCountOfSequential(@NonNull BitSet bitSet) {
            int count = 0;
            for (int i = 0; i < BYTE_SIZE; i++) {
                if (bitSet.get(i)) {
                    count++;
                } else {
                    break;
                }
            }
            return count;
        }
    
    
        /**
         * 将整形转为BitSet
         *
         * @param code
         * @return
         */
        private static BitSet convert2BitSet(int code) {
            BitSet bitSet = new BitSet(BYTE_SIZE);
    
            for (int i = 0; i < BYTE_SIZE; i++) {
                int tmp3 = code >> (BYTE_SIZE - i - 1);
                int tmp2 = 0x1 & tmp3;
                if (tmp2 == 1) {
                    bitSet.set(i);
                }
            }
            return bitSet;
        }
    
        /**
         * 将一指定编码的文件转换为另一编码的文件
         *
         * @param oldFullFileName
         * @param oldCharsetName
         * @param newFullFileName
         * @param newCharsetName
         */
        public static void convert(String oldFullFileName, String oldCharsetName, String newFullFileName, String newCharsetName) throws Exception {
            log.info("the old file name is : {}, The oldCharsetName is : {}", oldFullFileName, oldCharsetName);
            log.info("the new file name is : {}, The newCharsetName is : {}", newFullFileName, newCharsetName);
    
            StringBuffer content = new StringBuffer();
    
            @Cleanup
            BufferedReader bin = new BufferedReader(new InputStreamReader(new FileInputStream(oldFullFileName), oldCharsetName));
            String line;
            while ((line = bin.readLine()) != null) {
                content.append(line);
                content.append(System.getProperty("line.separator"));
            }
            newFullFileName = newFullFileName.replace("\\", "/");
            File dir = new File(newFullFileName.substring(0, newFullFileName.lastIndexOf("/")));
            if (!dir.exists()) {
                dir.mkdirs();
            }
            @Cleanup
            Writer out = new OutputStreamWriter(new FileOutputStream(newFullFileName), newCharsetName);
            out.write(content.toString());
        }
    
    }
    
    //检测文件格式,如果不是UTF-8,将其转为UTF-8格式
    String encodeType = EncodeUtils.getEncode(fileUploadSavePath + savedFileName, true);
    if (!encodeType.equals(EncodeUtils.CODE_UTF8)) {
        String newSavedFileName = System.currentTimeMillis() + "_UTF8_" + fileName;
        EncodeUtils.convert(fileUploadSavePath + savedFileName,
                encodeType,
                fileUploadSavePath + newSavedFileName,
                EncodeUtils.CODE_UTF8);
        savedFileName = newSavedFileName;
    }
    这里是工具类的调用处理,项目中使用了lombok包,大家注意,也推荐大家使用。

    展开全文
  • UTF-8与UTF-8无BOM的区别

    2021-03-26 10:17:39
    UTF-8与UTF-8无BOM的区别 1.UTF+BOMUTFBOM多了三个字节前缀:0xEF0xBB0xBF,有这三个字节前缀的文本或字符串,程序可以自动判断它为utf-8格式,并按照utf-8格式来解析文本或字符串,否则,一个文本或者字符串在...

    UTF-8与UTF-8无BOM的区别

    1.UTF+BOM比UTF无BOM多了三个字节前缀:0xEF0xBB0xBF,有这三个字节前缀的文本或字符串,程序可以自动判断它为utf-8格式,并按照utf-8格式来解析文本或字符串,否则,一个文本或者字符串在未知编码的情况下,需要按照字符编码规范去一个个验证
    2.BOM: Byte Order Mark,就是字节序标记
    UTF-8 BOM又叫UTF-8 签名,其实UTF-8 的BOM对UFT-8没有作用,是为了支持UTF-16,UTF-32才加上的
    BOM,BOM签名的意思就是告诉编辑器当前文件采用何种编码,方便编辑器识别,但是BOM虽然在编辑器
    中不显示,但是会产生输出,就像多了一个空行。

    展开全文
  • 首先,UTF-8和Unicode是有转换关系的,我们假设UTF-8字符串没有BOM。 wstring UTF8toUnicode(const string &input) { int state = 0; unsigned char temp; wchar_t wc; wstring wstr; for (unsigned...

    UTF-8转Unicode

    首先,UTF-8和Unicode是有转换关系的,我们假设UTF-8字符串没有BOM。

    	wstring UTF8toUnicode(const string &input)
    	{
    		int state = 0;
    		unsigned char temp;
    		wchar_t wc;
    		wstring wstr;
    		for (unsigned char c : input)
    		{
    			switch (state)
    			{
    			case 0:
    				if (c >> 4 == 14)// 1110
    				{
    					temp = c << 4;
    					state = 1;
    					break;
    				}
    				if (c >> 5 == 6)// 110
    				{
    					temp = c >> 3 & 7;// 7dec=111b
    					wc = temp << 8;
    
    					temp = c << 6;
    					state = 3;
    					break;
    				}
    				if (c >> 7 == 0) // 0
    				{
    					wstr += c;
    					state = 0;
    					break;
    				}
    				throw string("Decode UTF-8 error.");
    				break;
    			case 1: // 1110 xxxx
    				if (c >> 6 == 2) //10
    				{
    					temp |= c >> 2 & 0xf;
    					wc = temp << 8;
    
    					temp = c << 6;
    					state = 2;
    				}
    				else
    					throw string("Decode UTF-8 error.");
    				break;
    			case 2: // 1110 xxxx 10xx xxxx
    				if (c >> 6 == 2) //10
    				{
    					temp |= c & 0x3F;
    					wc |= temp;
    					wstr += wc;
    
    					state = 0;
    				}
    				else
    					throw string("Decode UTF-8 error.");
    				break;
    			case 3: // 110x xxxx
    				if (c >> 6 == 2) //10
    				{
    					temp |= (c & 0x3F);
    					wc |= temp;
    					wstr += wc;
    
    					state = 0;
    				}
    				else
    					throw string("Decode UTF-8 error.");
    				break;
    			}
    		}
    		return wstr;
    	}
    

    函数返回wstring格式的Unicode字符串。如果编码不正确会抛出异常。

    Unicode转GB2312

    有些人提供的方法还要自己准备编码表,实在麻烦。Windows本就已经提供了API的。

    	string Unicode2GBK(const wstring &input)
    	{
    		int nLen = (int)input.length();
    
    		DWORD num = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)input.c_str(), -1, NULL, 0, NULL, 0);
    		string str(num, ' ');
    		int nResult = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)input.c_str(), nLen, (LPSTR)str.c_str(), num, NULL, NULL);
    
    		return str;
    	}
    

    关于UTF-8的BOM

    UTF-8字符串有时会在前面附上BOM,但有时既没有提供编码方式也没有BOM,这时可以采用试解码的方式解决。直接调用UTF8toUnicode函数,若抛出异常则说明不是UTF-8编码,若没有异常则说明解码正确。
    笔者采用此方法在解码eml文件时效果良好。

    展开全文
  • UTF8-NoBom UTF8-Bom Http 响应 Content-Type 用于指定数据类型(MIME) Content-Type:text/plain; 浏览器自动根据该类型选择显示方式。text/plain 显示时浏览会根据中编码自动时限,当你text/plain的编码是UTF8...

    UTF8-NoBom UTF8-Bom

    Http 响应 Content-Type 用于指定数据类型(MIME)

    Content-Type:text/plain; 浏览器自动根据该类型选择显示方式。text/plain 显示时浏览会根据中编码自动时限,当你text/plain的编码是UTF8-NOBom时浏览器无法判断时编码UTF,可以作为GB232显示。 除非 Content-Type: text/plain; charset=utf-8。

    UTF8-NoBom UTF8-Bom 的区别时什么
    UTF8-Bom 在文本的二进制中插入utf-8 标识,文本内容以UTF-8编码
    image

    UTF8-NoBom 标识,文本内容以UTF-8编码

    image

    引起当UTF8-Bom 浏览器可以识别的它时UTF-8

    下列时.net 如何保存为UTF8-Bom的 byte 二进制值

    var data = Encoding.UTF8.GetBytes("some data");
        var result = Encoding.UTF8.GetPreamble().Concat(data).ToArray();
        return File(result, "application/csv", "foo.csv");

    参考 stackoverflow https://stackoverflow.com/questions/4414088/how-to-getbytes-in-c-sharp-with-utf8-encoding-with-bom

    转载于:https://my.oschina.net/fsilence/blog/1586367

    展开全文
  • 转自: https://www.cnblogs.com/ferraborghini/p/4951102.html https://www.cnblogs.com/Detector/p/8744992.html 转载于:https://www.cnblogs.com/swordsman180309/p/11297462.html
  • 无BOM utf8编码判断

    2009-06-19 13:34:31
    BOM(Byte Order Mark)是一个字符,它表明UNICODE文本的UTF-16,UTF-32的编码字节顺序(高字节低字节顺序)和编码方式(UTF-8,UTF-16,UTF-32, 其中UTF-8编码是字节顺序无关的)。 如下所示:Encoding ...
  • java判断文件编码是UTF-8还是UTF-8(BOM)还是其他编码 final String filePath = "C:\\Users\\小太阳\\Desktop\\java\\20210302~\\mybatis\\mybatis.txt"; BufferedInputStream bis = new BufferedInputStream(new...
  • VBA 格式化输出XML(UTF-8无BOM编码)

    千次阅读 2016-08-28 02:37:23
    细心点的话会发现用上面的方法实际上输出的文件格式是带BOMUTF-8,它跟UTF-8无BOM的区别在哪呢?用UltraEdit工具来看十六进制码,会发现前者在开头多了三个字节:0xEF,0xBB,0xBF,想保存成UTF-8无BOM,把这三个...
  • python 检测文件编码是否是utf-8无bom

    千次阅读 2018-06-04 10:41:51
    代码如下:#!/usr/bin/env python ...#2018/05/31 检测文件是否是utf-8无bom格式的 import sys, codecs def detectUTF8(file_name): state = 0 line_num = 0 file_obj = open(file_name) all...
  • java自动识别文件编码格式UTF-8,UTF-8无BOM,GBK

    万次阅读 热门讨论 2018-07-13 16:53:58
    背景:在解读properties配置文件时windows操作系统编辑过的内容上传后总是无法通过键获取文件中内容,讲过分析是文件的编码格式为UTF-8BOM的,因此通过该程序获取文件编码格式/** * */ import java.io....
  • 从txt文件中读取一串字符串和数据库中另一串字符串比较的时候发现两串字符串一样,但是判断是否equal的时候发现返回的是false,也就是不相等。这就奇怪了,于是打印log,发现了端倪: 左边的字符串是数据库的,...
  • JAVA 无BOM utf8文件编码判断

    千次阅读 2016-02-26 17:27:02
    /** * @Comments :获取文件编码格式 * @param fileName * @return */ private static String getCharset(File fileName) { BufferedInputStream... int bom = 0; String str = " "; String str2 = "";
  • 在一个Qt项目整合的过程中,出现了如下报错: ...经过检查,发现所有文件编码都没有任何问题,都是utf-8编码。但可能是因为组里有人用的是独立的Qt,有人用的VS版Qt,二者编码有细微的差别。 经过调查,我们发现VS...
  • BOM(Byte Order Mark)在分析unicode之前,先把bom(byte order mark)说一下。...来举个很简单的例子,在windows下新建一个文本文件,并另存为utf8的文件格式: 该文件里面没有任何内容,我们再用Hex
  • remove utf8 bom

    2013-11-02 09:02:34
    utf8格式的 php 代码里...这个工具就是专门用来删除utf8文件里的bom的。 把文件或者目录拖到工具的主窗口上,他就能自动遍历所有文件,找出带bom的文件。 然后手动判断排除不需要修改的文件,就可以一键 修复BOM 了。
  • //读文件 QFile file("C:\\Users\\08497\\Desktop\\热词1utf8bom.txt"); if(file.open(QIODevice::ReadOnly)) { qDebug(); } else { qDebug(); } QByteArray array = file.readAll(); file.close(); //判断读取文本...
  • /// 判断是否是不带 BOMUTF8 格式 /// &lt;/summary&gt; /// &lt;param name="data"&gt;&lt;/param&gt; /// &lt;returns&gt;&lt;/returns&gt; pub
  • UTF-8BOM和不带BOM

    千次阅读 2018-03-29 16:29:09
    UTF-8 不需要 BOM,尽管 Unicode 标准允许在 UTF-8 中使用 BOM。所以不含 BOMUTF-8 才是标准形式,在 UTF-8 文件中放置 BOM 主要是微软的习惯(顺便提一下:把带有 BOM 的小端序 UTF-16 称作「Unicode」而又不...
  • Go语言:读取带有BOM头的UTF8文件

    千次阅读 2020-05-13 14:26:04
    BOM头是UTF8文件开头的三个固定取值的字节,读文件的时候如果遇到BOM头需要忽略。在Golang里,比较有效率的方法是用ioutil.ReadFile,返回[]byte之后截取从第四个字节到末尾的切片。因为由切片截取生成的新切片和原...
  • Encoding GetBytesEncoding(byte[] bs) { int len = bs.Length; if (len >= 3 && bs[0] == 0xEF && bs[1] == 0xBB && bs[2] == 0xBF) { return Encoding.UTF8; } int[] cs = { 7, 5, 4,
  • 用VBS判断无BOM头的文件是否UTF-8编码

    千次阅读 2014-11-15 22:39:22
    标题: 用VBS判断无BOM头的文件是否UTF-8编码 作者: Demon 链接: http://demon.tw/programming/vbs-validate-utf8.html 版权: 本博客的所有文章,都遵守“署名-非商业性使用-相同方式共享 2.5 中国大陆”协议...
  • } else if (IsUTF8Bytes(ss)) { return Encoding.UTF8.GetString(bs, 0, len ); } if (len >= 2 &&ss[0] == 0xFE && ss[1] == 0xFF ) { return Encoding.BigEndianUnicode.GetString(bs, 2, len - 2); } else if ...
  • 版权声明:本文为博主原创...BOM——Byte Order Mark,就是字节序标记   在UCS 编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在...
  • 判断并删除utf8文本文件中的前三个字节BOM
  • Java解决UTF-8BOM问题

    千次阅读 2016-03-18 14:18:24
    近日在项目中遇到一件诡异的事情,有一个txt文件,用记事本保存和notepad++ 保存,再用Java读取的时候,读出来的结果不一致。...后面在网上查询了一下,txt文件编码格式有UTF-8和UTF-8无(BOM) 2中格式,下面来看
  • 前端项目运行后浏览器能识别html,但是... 查看target后中文显示正常,应该就不是tomcat 的原因 单独用notepad++转为utf8 BOM编码浏览器就能正常显示 但是这样效率太低了 有没有能让浏览器判断utf8 无BOM的编码呢?
  • C++判断字符串编码格式(ANSI\UTF16_LE\UTF16_BE\UTF8\UTF8_BOM) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,420
精华内容 3,768
关键字:

判断utf8无bom