java io read中申请读的长度与实际长度不同|RocketMQ源码
今天,在读RockeMQ源码时,读到
MIXALL中的file2string方法,然后测试一个文件,返回null, 特别奇怪,查看了下源码
public static final String file2String(final File file) { if (file.exists()) { char[] data = new char[(int) file.length()]; boolean result = false; FileReader fileReader = null; try { fileReader = new FileReader(file); int datalen = data.length; int len = fileReader.read(data, 0, datalen); result = (len == data.length); } catch (IOException e) { // e.printStackTrace(); } finally { if (fileReader != null) { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } if (result) { String value = new String(data); return value; } } return null; }
原来是
int datalen = data.length;
int len = fileReader.read(data, 0, datalen);
result = (len == datalen);
因为len与datalen是不相等的原因。
也就是file.length与read获取长度不同,
两者有什么区别呢?
查看源码:
public long length() { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkRead(path); } if (isInvalid()) { return 0L; } return fs.getLength(this); }
@Override public native long getLength(File f);
可以看到是调用了WinNTFileSystem的本地的方法
而filereader.read源码则是
sun.nio.cs.StreamDecoder extends java.io.Reader里的代码,同样不可见。。。
两者什么时候相等呢?
原来的文件是这样的:
package bhz.test; import java.util.Date; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; import bhz.entity.Pay; import bhz.service.PayService; /** * <br>类 名: BaseTest * <br>描 述: 描述类完成的主要功能 * <br>作 者: bhz * <br>创 建: 2013年5月8日 * <br>版 本:v1.0.0 * <br> * <br>历 史: (版本) 作者 时间 注释 */ @ContextConfiguration(locations = {"classpath:applicationContext.xml" }) @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false) @RunWith(SpringJUnit4ClassRunner.class) @Transactional(rollbackFor = Exception.class) public class BaseTest { @Autowired private PayService payService; @Test public void testSave() throws Exception { Pay pay = new Pay(); pay.setUserid("z3"); pay.setUsername("张三"); pay.setAmount(5000d); pay.setDetail("0"); pay.setUpdateBy("z3"); pay.setUpdateTime(new Date()); this.payService.insert(pay); } @Test public void testUpdate() throws Exception { System.out.println(this.payService); Pay pay = this.payService.selectByPrimaryKey("z3"); pay.setAmount(pay.getAmount() - 1000d); pay.setUpdateTime(new Date()); this.payService.updateByPrimaryKey(pay); } }
我把file简单化,就写一行试试是可以的。
实践证明
加了以下是不可以的
/** * <br>类 名: BaseTest * <br>描 述: 描述类完成的主要功能 * <br>作 者: bhz * <br>创 建: 2013年5月8日 * <br>版 本:v1.0.0 * <br> * <br>历 史: (版本) 作者 时间 注释 */
"张三"
关键问题,居然是中文。。。。
一个中文相差两个大小。。
所以lentgh读的是字节,filereader读的是字符,在汉字上是两倍的问题,如果想让两个相等,则需要类型同样。比如用inputstream.reader
其实这个类的目的,就是文件内不能有中文,如果读读取出来,result写true则ok
相关参考
java io --- Reader类
https://blog.csdn.net/zhao123h/article/details/52831524
RocketMQ使用Filter问题!