java读取UTF-8的txt文件发现开头的一个字符问题
今天遇到一个奇葩问题,在读取一个TXT文件时,出现开头多了一个问号(?)。如下图:

莫名奇妙的多了一个。最后通过网上资料,知道在Java中,class文件采用utf8的编码方式,JVM运行时采用utf16。Java的字符串是永远都是unicode的,采用的是UTF-16的编码方式。
想测试一下,java对UTF-8文件的读写的能力,结果发现了一个很郁闷的问题,如果通过java写的UTF-8文件,使用Java可以正确的读,但是如果用记事本将相同的内容使用UTF-8格式保存,则在使用程序读取是会从文件中多读出一个不可见字符。
测试代码如下:
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStreamReader;
- public class UTF8Test {
- public static void main(String[] args) throws IOException {
- File f = new File("./utf.txt");
- FileInputStream in = new FileInputStream(f);
- // 指定读取文件时以UTF-8的格式读取
- BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
- String line = br.readLine();
- while(line != null)
- {
- System.out.println(line);
- line = br.readLine();
- }
- }
- }

utf.txt通过记事本创建,另存时使用指定utf-8编码,其内容为:
This is second line.
正常的测试结果应该是直接输出utf.txt的文本内容。可是实际上却输出了下面的内容:
This is second line.
第一行多出了一个问号。
通过上面的几篇文章应该可以想到是Java读取BOM(Byte Order Mark)的问题,在使用UTF-8时,可以在文件的开始使用3个字节的"EF BB BF"来标识文件使用了UTF-8的编码,当然也可以不用这个3个字节。
上面的问题应该就是因为对开头3个字节的读取导致的。开始不太相信这个是JDK的Bug,后来在多次试验后,问题依然存在,就又狗狗了一下,果然找到一个如下的Bug:
不过在我关掉的一些页面中记得有篇文件说这个bug只在jdk1.5及之前的版本才有,说是1.6已经解决了,从目前来看1.6只是解决了读取带有BOM文件失败的问题,还是不能区别处理有BOM和无BOM的UTF-8编码的文件,从Bug ID:4508058里的描述可以看出,这个问题将作为一个不会修改的问题关闭,对于BOM编码的识别将由应用程序自己来处理,原因可从另处一个bug处查看到,因为Unicode对于BOM的编码的规定可能发生变化。也就是说对于一个UTF-8的文件,应用程序需要知道这个文件有没有写BOM,然后自己决定处理BOM的方式。
解决办法:
1.保存时,选择
2.引用正确的读取类,比如我用的就是:org.apache.commons.io.FileUtils.readFileToString(new File(file), encoding);
ps:贴一下读取的工具类源码:
/**
* 读入文件到字串中
*
* @param file 需要读取的文件路径
* @return 读取的文件内容,若读入失败,则返回空字串
*/
public static String readFileToString(String file, String encoding)
{
try
{
if (StringHelper.isEmpty(encoding))
{
encoding = "GBK";
}
String content = org.apache.commons.io.FileUtils.readFileToString(new File(file), encoding);
return content;
}
catch (IOException ex)
{
logger.error("读取文件出错", ex);
}
return "";
}
注意两点都要过一下,希望有用。
java读取UTF-8的txt文件发现开头的一个字符问题的更多相关文章
- java将数据写入到txt文件中(txt有固定的格式)
java将数据写入到txt文件中,这个应该对于学过java I/O的人来说是很简单的事情了,但是如果要将数据以固定的格式写入到txt文件中,就需要一定的技巧了. 这里举个简单的例子,以供参考: 比如我 ...
- C# 读取大文件 (可以读取3GB大小的txt文件)
原文:C# 读取大文件 (可以读取3GB大小的txt文件) 在处理大数据时,有可能 会碰到 超过3GB大小的文件,如果通过 记事本 或 NotePad++去打开它,会报错,读不到任何文件. 如果你只是 ...
- 关于Java里面File类创建txt文件重复???
private JButton getOpenButton() { if (openButton == null) { openButton = new JButton(); openButton.s ...
- java读取resource/通过文件名获取文件类型
java读取resource java读取resource目录下文件的方法: 借助Guava库的Resource类 Resources.getResource("test.txt" ...
- 【转】Java读取matlab的.mat数据文件
参考:Java读取mat文件 下载链接:ujmp jmatio 下载完两个.jar文件之后,如何引用到java项目当中?项目名称->右键->Property->Java Build ...
- Java导出List集合到txt文件中——(四)
有时候,需要将数据以一定格式导出到txt文件中.利用Java的IO可以轻松的导出数据到txt中. package Action.txt; import java.io.BufferedWriter; ...
- 解决:java 读取 resources 下面的 json 文件
前言:java 读取 工程下的配置文件,文件类型为 json(*.json),记录一下始终读取不到 json 文件的坑.maven项目 直接上工具类代码 package com.yule.compon ...
- java存储数据到本地txt文件中
java存储数据,方便打印日志等 1.会覆盖以前的数据 try { File writeName = new File("D:\\data.txt"); // 相对路径,如果没有则 ...
- java读取jar包中的文件
随手写了一个java小工具,maven打包成功后,发现工具总是读不到打在jar包中的文件信息,要读取的文件位于 /src/main/resources 目录下,打包成功后,文件就在jar包中根目录下, ...
随机推荐
- x86汇编
● 实模式下32bit处理器,与8086兼容,例如loop 指令结束标志,只判断cx,而不是ecx ● IO端口 实际上是一些寄存器,在IO接口当中.向外设读写数据,要通过读写IO端口来实现. 有些计 ...
- Codeforces 1068 - A/B/C/D/E - (Done)
链接:http://codeforces.com/contest/1068 A - Birthday - [计算题] 题意:一共 $N$ 种硬币,我已经有其中 $K$ 种,我的 $M$ 个朋友每人送我 ...
- day4_局部变量和全局变量
一.介绍: 定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域. 局部变量意思就是在局部生效的,出了这个变量的作用域,这个变量就失效了 全局变量的意思就是在整个程序里面都生效的,在程 ...
- Django之中间件&信号&缓存&form上传
中间件 1.中间件是什么? 中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出.因为改变的是全局,所以需要谨慎实用, ...
- angular--获取时间方法services
写了一些公用方法获取自然周.传入开始和结束日期,获取中间全部日期等方法 .service('DateServices', [function () { // 获取某年自然周的方法 (如果是当年,只返回 ...
- 修改jupyter notebook的默认打开地址
1)在Anaconda Prompt终端中输入下面命令,查看你的notebook配置文件在哪里: jupyter notebook --generate-config 2)通过搜索关键词:c.Note ...
- Docker:使用自定义redis.conf运行redis容器(7)
演示环境:win7+docker toolbox 1.自定义配置文件 首先在Windows环境下准备好配置文件redis 然后打开Quickstart终端输入命令: cp -rf ~/Desktop/ ...
- 安装zabbix时PHP ldap Warning
一.如果是源码编译 [root@DaMoWang php-]# / opcache.a opcache.so # 出现告警是因为ldap模块不存在,须要编译生成此模块并重新加载 到源码包的解压目录下, ...
- 【Linux】Tomcat安装及一个服务器配置多个Tomcat
安装环境 :Linux(Ubuntu 版) 安装软件 : apache-tomcat-9.0.0.M1.tar.gz(下载地址http://tomcat.apache.org/) 步骤一 Tomcat ...
- SD卡与FAT32系统学习
2011-06-06 23:04 前2天,我了解了一下SD卡驱动的原理及FAT32文件系统的结构.接着准备主要已移植为主.通过LCD显示SD卡中的图片.但我需要分步进行. 0,使sd卡能读写数据.1, ...