SG9. 字符编码检测
描述
输入描述
不同编码格式的文本输出描述
判断属于哪种编码,输出结果为示例1
输入:
004c2eb
输出:
GBK
Java 解法, 执行用时: 42ms, 内存消耗: 11380KB, 提交时间: 2020-10-31
import java.util.*; public class Main{ static boolean isAscii = true; //如果全是首位为0的字节,无法判断是UTF-8,还是GBK,还是UTF-16;,所以输出OTHER public static void main(String[] args){ Scanner in = new Scanner(System.in); String str = in.next(); str = str.substring(3); //str字符串前三位代表的是输入字符串长度,但总比实际长度大1, //不知道怎么回事,猜测是牛客转码把结尾的'\n'也算进去了,不管怎样决定不用前三位 short[] code = hexStringToShortArray(str); String ans = ""; if(isUTF8(code)) ans = "UTF-8"; else if(isAscii) ans = "OTHER"; else if(isGBK(code)) ans = "GBK"; else if(isUTF16(code)) ans = "UTF-16"; else ans = "OTHER"; System.out.println(ans); } /* UTF-16是以16位无符号整数为单位进行编码的,而这里一个short存8位,所以code数组的元素数必定要是2的倍数 当UTF-16在BMP内时占两个字节,这两个字节是任意的没有要求的。而当UTF-16在BMP外,就是四个字节。因为题目说采用小端存储, 所以低位在前,高位在后。所以UTF-16四个字节时低位两个字节的前6位是110111,高位两个字节的前6位是110110. 但是两个字节时也有可能是上述两个前缀,这个冲突问题,呃,我也不知道... 这道题目在这里并没怎么提到知识,应该考虑倍数问题即可 */ public static boolean isUTF16(short[] code){ if(code.length % 2 == 0) return true; return false; } /* 1、数值小于127的字节表示ASCII中原有字符,此时GBK占用一个字节 2、当数值大于127时,就需要读取下一个字节,此时GBK占用两个字节,高位的范围是81-fe,低位的范围是40-fe,但是不能是xx7f 3、当数值等于127时,题目没说,索性认为不是GBK */ public static boolean isGBK(short[] code){ for(int i = 0; i < code.length; i++){ if((int)code[i] > 127){ if(i + 1 >= code.length) return false; if((int)code[i] < 8 * 16 + 1 || (int)code[i] > 15 * 16 + 14) return false; i++; if((int)code[i] < 4* 16 + 0 || (int)code[i] > 15 * 16 + 14 || (int)code[i] == 7 * 16 + 15) return false; } else if((int)code[i] == 127) return false; } return true; } /* UTF-8正如题目所总结的规律去判断,这里顺便判断是否全是以0为开头的字节isAscii */ public static boolean isUTF8(short[] code){ for(int i = 0; i < code.length; i++){ String str = Integer.toBinaryString((int)code[i]); while(str.length() < 8) str = 0 + str; if(str.charAt(0) != '0'){ isAscii = false; int j = 0; while(j < 8 && str.charAt(j) != '0') j++; if(j >= 7 || j == 1) return false; j--; for(int k = i + 1; k <= code.length; k++){ if(k == code.length) return false; String temp = Integer.toBinaryString((int)code[k]); while(temp.length() < 8) temp = 0 + temp; if(temp.charAt(0) == '1' && temp.charAt(1) == '0') j--; else return false; if(j == 0){ i = k; break; } } } } if(isAscii) return false; else return true; } public static short[] hexStringToShortArray(String s) { short[] data = new short[s.length() / 2]; int i = 0; int k = 0; while (i < s.length()) { try { char c1 = s.charAt(i); char c2 = '\0'; if (i + 1 < s.length()) { c2 = s.charAt(i + 1); } String temp = c1 + ""; if (c2 != '\0') { temp = c1 + "" + c2; } data[k] = Short.parseShort(temp, 16); } catch (NumberFormatException e) { return null; } i = i + 2; k++; } return data; } }
Java 解法, 执行用时: 43ms, 内存消耗: 12616KB, 提交时间: 2020-07-30
import java.util.*; public class Main{ static boolean isAscii = true; //如果全是首位为0的字节,无法判断是UTF-8,还是GBK,还是UTF-16;,所以输出OTHER public static void main(String[] args){ Scanner in = new Scanner(System.in); String str = in.next(); str = str.substring(3); short[] code = hexStringToShortArray(str); String ans = ""; if(isUTF8(code)) ans = "UTF-8"; else if(isAscii) ans = "OTHER"; else if(isGBK(code)) ans = "GBK"; else if(isUTF16(code)) ans = "UTF-16"; else ans = "OTHER"; System.out.println(ans); } public static boolean isUTF16(short[] code){ if(code.length % 2 == 0) return true; return false; } public static boolean isGBK(short[] code){ for(int i = 0; i < code.length; i++){ if((int)code[i] > 127){ if(i + 1 >= code.length) return false; if((int)code[i] < 8 * 16 + 1 || (int)code[i] > 15 * 16 + 14) return false; i++; if((int)code[i] < 4* 16 + 0 || (int)code[i] > 15 * 16 + 14 || (int)code[i] == 7 * 16 + 15) return false; } else if((int)code[i] == 127) return false; } return true; } public static boolean isUTF8(short[] code){ for(int i = 0; i < code.length; i++){ String str = Integer.toBinaryString((int)code[i]); while(str.length() < 8) str = 0 + str; if(str.charAt(0) != '0'){ isAscii = false; int j = 0; while(j < 8 && str.charAt(j) != '0') j++; if(j >= 7 || j == 1) return false; j--; for(int k = i + 1; k <= code.length; k++){ if(k == code.length) return false; String temp = Integer.toBinaryString((int)code[k]); while(temp.length() < 8) temp = 0 + temp; if(temp.charAt(0) == '1' && temp.charAt(1) == '0') j--; else return false; if(j == 0){ i = k; break; } } } } if(isAscii) return false; else return true; } public static short[] hexStringToShortArray(String s) { short[] data = new short[s.length() / 2]; int i = 0; int k = 0; while (i < s.length()) { try { char c1 = s.charAt(i); char c2 = '\0'; if (i + 1 < s.length()) { c2 = s.charAt(i + 1); } String temp = c1 + ""; if (c2 != '\0') { temp = c1 + "" + c2; } data[k] = Short.parseShort(temp, 16); } catch (NumberFormatException e) { return null; } i = i + 2; k++; } return data; } }
Java 解法, 执行用时: 47ms, 内存消耗: 11740KB, 提交时间: 2020-09-13
import java.util.*; public class Main{ static boolean isAscii = true; //如果全是首位为0的字节,无法判断是UTF-8,还是GBK,还是UTF-16;,所以输出OTHER public static void main(String[] args){ Scanner in = new Scanner(System.in); String str = in.next(); str = str.substring(3); short[] code = hexStringToShortArray(str); String ans = ""; if(isUTF8(code)) ans = "UTF-8"; else if(isAscii) ans = "OTHER"; else if(isGBK(code)) ans = "GBK"; else if(isUTF16(code)) ans = "UTF-16"; else ans = "OTHER"; System.out.println(ans); } public static boolean isUTF16(short[] code){ if(code.length % 2 == 0) return true; return false; } public static boolean isGBK(short[] code){ for(int i = 0; i < code.length; i++){ if((int)code[i] > 127){ if(i + 1 >= code.length) return false; if((int)code[i] < 8 * 16 + 1 || (int)code[i] > 15 * 16 + 14) return false; i++; if((int)code[i] < 4* 16 + 0 || (int)code[i] > 15 * 16 + 14 || (int)code[i] == 7 * 16 + 15) return false; } else if((int)code[i] == 127) return false; } return true; } public static boolean isUTF8(short[] code){ for(int i = 0; i < code.length; i++){ String str = Integer.toBinaryString((int)code[i]); while(str.length() < 8) str = 0 + str; if(str.charAt(0) != '0'){ isAscii = false; int j = 0; while(j < 8 && str.charAt(j) != '0') j++; if(j >= 7 || j == 1) return false; j--; for(int k = i + 1; k <= code.length; k++){ if(k == code.length) return false; String temp = Integer.toBinaryString((int)code[k]); while(temp.length() < 8) temp = 0 + temp; if(temp.charAt(0) == '1' && temp.charAt(1) == '0') j--; else return false; if(j == 0){ i = k; break; } } } } if(isAscii) return false; else return true; } public static short[] hexStringToShortArray(String s) { short[] data = new short[s.length() / 2]; int i = 0; int k = 0; while (i < s.length()) { try { char c1 = s.charAt(i); char c2 = '\0'; if (i + 1 < s.length()) { c2 = s.charAt(i + 1); } String temp = c1 + ""; if (c2 != '\0') { temp = c1 + "" + c2; } data[k] = Short.parseShort(temp, 16); } catch (NumberFormatException e) { return null; } i = i + 2; k++; } return data; } }
Java 解法, 执行用时: 48ms, 内存消耗: 12508KB, 提交时间: 2020-10-31
import java.util.*; public class Main{ static boolean isAscii = true; //如果全是首位为0的字节,无法判断是UTF-8,还是GBK,还是UTF-16;,所以输出OTHER public static void main(String[] args){ Scanner in = new Scanner(System.in); String str = in.next(); str = str.substring(3); //str字符串前三位代表的是输入字符串长度,但总比实际长度大1, //不知道怎么回事,猜测是牛客转码把结尾的'\n'也算进去了,不管怎样决定不用前三位 short[] code = hexStringToShortArray(str); String ans = ""; if(isUTF8(code)) ans = "UTF-8"; else if(isAscii) ans = "OTHER"; else if(isGBK(code)) ans = "GBK"; else if(isUTF16(code)) ans = "UTF-16"; else ans = "OTHER"; System.out.println(ans); } /* UTF-16是以16位无符号整数为单位进行编码的,而这里一个short存8位,所以code数组的元素数必定要是2的倍数 当UTF-16在BMP内时占两个字节,这两个字节是任意的没有要求的。而当UTF-16在BMP外,就是四个字节。因为题目说采用小端存储, 所以低位在前,高位在后。所以UTF-16四个字节时低位两个字节的前6位是110111,高位两个字节的前6位是110110. 但是两个字节时也有可能是上述两个前缀,这个冲突问题,呃,我也不知道... 这道题目在这里并没怎么提到知识,应该考虑倍数问题即可 */ public static boolean isUTF16(short[] code){ if(code.length % 2 == 0) return true; return false; } /* 1、数值小于127的字节表示ASCII中原有字符,此时GBK占用一个字节 2、当数值大于127时,就需要读取下一个字节,此时GBK占用两个字节,高位的范围是81-fe,低位的范围是40-fe,但是不能是xx7f 3、当数值等于127时,题目没说,索性认为不是GBK */ public static boolean isGBK(short[] code){ for(int i = 0; i < code.length; i++){ if((int)code[i] > 127){ if(i + 1 >= code.length) return false; if((int)code[i] < 8 * 16 + 1 || (int)code[i] > 15 * 16 + 14) return false; i++; if((int)code[i] < 4* 16 + 0 || (int)code[i] > 15 * 16 + 14 || (int)code[i] == 7 * 16 + 15) return false; } else if((int)code[i] == 127) return false; } return true; } /* UTF-8正如题目所总结的规律去判断,这里顺便判断是否全是以0为开头的字节isAscii */ public static boolean isUTF8(short[] code){ for(int i = 0; i < code.length; i++){ String str = Integer.toBinaryString((int)code[i]); while(str.length() < 8) str = 0 + str; if(str.charAt(0) != '0'){ isAscii = false; int j = 0; while(j < 8 && str.charAt(j) != '0') j++; if(j >= 7 || j == 1) return false; j--; for(int k = i + 1; k <= code.length; k++){ if(k == code.length) return false; String temp = Integer.toBinaryString((int)code[k]); while(temp.length() < 8) temp = 0 + temp; if(temp.charAt(0) == '1' && temp.charAt(1) == '0') j--; else return false; if(j == 0){ i = k; break; } } } } if(isAscii) return false; else return true; } public static short[] hexStringToShortArray(String s) { short[] data = new short[s.length() / 2]; int i = 0; int k = 0; while (i < s.length()) { try { char c1 = s.charAt(i); char c2 = '\0'; if (i + 1 < s.length()) { c2 = s.charAt(i + 1); } String temp = c1 + ""; if (c2 != '\0') { temp = c1 + "" + c2; } data[k] = Short.parseShort(temp, 16); } catch (NumberFormatException e) { return null; } i = i + 2; k++; } return data; } }
Java 解法, 执行用时: 52ms, 内存消耗: 12648KB, 提交时间: 2020-11-01
import java.util.*; public class Main{ static boolean isAscii = true; //如果全是首位为0的字节,无法判断是UTF-8,还是GBK,还是UTF-16;,所以输出OTHER public static void main(String[] args){ Scanner in = new Scanner(System.in); String str = in.next(); str = str.substring(3); //str字符串前三位代表的是输入字符串长度,但总比实际长度大1, //不知道怎么回事,猜测是牛客转码把结尾的'\n'也算进去了,不管怎样决定不用前三位 short[] code = hexStringToShortArray(str); String ans = ""; if(isUTF8(code)) ans = "UTF-8"; else if(isAscii) ans = "OTHER"; else if(isGBK(code)) ans = "GBK"; else if(isUTF16(code)) ans = "UTF-16"; else ans = "OTHER"; System.out.println(ans); } /* UTF-16是以16位无符号整数为单位进行编码的,而这里一个short存8位,所以code数组的元素数必定要是2的倍数 当UTF-16在BMP内时占两个字节,这两个字节是任意的没有要求的。而当UTF-16在BMP外,就是四个字节。因为题目说采用小端存储, 所以低位在前,高位在后。所以UTF-16四个字节时低位两个字节的前6位是110111,高位两个字节的前6位是110110. 但是两个字节时也有可能是上述两个前缀,这个冲突问题,呃,我也不知道... 这道题目在这里并没怎么提到知识,应该考虑倍数问题即可 */ public static boolean isUTF16(short[] code){ if(code.length % 2 == 0) return true; return false; } /* 1、数值小于127的字节表示ASCII中原有字符,此时GBK占用一个字节 2、当数值大于127时,就需要读取下一个字节,此时GBK占用两个字节,高位的范围是81-fe,低位的范围是40-fe,但是不能是xx7f 3、当数值等于127时,题目没说,索性认为不是GBK */ public static boolean isGBK(short[] code){ for(int i = 0; i < code.length; i++){ if((int)code[i] > 127){ if(i + 1 >= code.length) return false; if((int)code[i] < 8 * 16 + 1 || (int)code[i] > 15 * 16 + 14) return false; i++; if((int)code[i] < 4* 16 + 0 || (int)code[i] > 15 * 16 + 14 || (int)code[i] == 7 * 16 + 15) return false; } else if((int)code[i] == 127) return false; } return true; } /* UTF-8正如题目所总结的规律去判断,这里顺便判断是否全是以0为开头的字节isAscii */ public static boolean isUTF8(short[] code){ for(int i = 0; i < code.length; i++){ String str = Integer.toBinaryString((int)code[i]); while(str.length() < 8) str = 0 + str; if(str.charAt(0) != '0'){ isAscii = false; int j = 0; while(j < 8 && str.charAt(j) != '0') j++; if(j >= 7 || j == 1) return false; j--; for(int k = i + 1; k <= code.length; k++){ if(k == code.length) return false; String temp = Integer.toBinaryString((int)code[k]); while(temp.length() < 8) temp = 0 + temp; if(temp.charAt(0) == '1' && temp.charAt(1) == '0') j--; else return false; if(j == 0){ i = k; break; } } } } if(isAscii) return false; else return true; } public static short[] hexStringToShortArray(String s) { short[] data = new short[s.length() / 2]; int i = 0; int k = 0; while (i < s.length()) { try { char c1 = s.charAt(i); char c2 = '\0'; if (i + 1 < s.length()) { c2 = s.charAt(i + 1); } String temp = c1 + ""; if (c2 != '\0') { temp = c1 + "" + c2; } data[k] = Short.parseShort(temp, 16); } catch (NumberFormatException e) { return null; } i = i + 2; k++; } return data; } }