项目运行的时候报了一个新的错误,记录一下。
贴上报错:
java.nio.BufferOverflowExceptionat java.nio.HeapByteBuffer.put(HeapByteBuffer.java:183)
at java.nio.ByteBuffer.put(ByteBuffer.java:832)
at com.util.FileIO.write2File(FileIO.java:79)
分析一下,报错是在流写入文件的时候。
public static void write2File(String items) throws IOException {
String path = "temp/test";
File file = new File(path);
if (!file.exists()) {
file.getParentFile().mkdirs();
}
file.createNewFile();
// 切记,此处的初始化必须在确定要修改文件才执行,否则由于写入流并没有指定允许追加,所以一旦打开写入流指针默认为0,则清空文件
FileOutputStream outputStream = null;
FileChannel out = null;
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(path, "rw");
FileChannel fc = raf.getChannel();
Charset charset = Charset.forName("UTF-8");
CharsetDecoder decoder = charset.newDecoder();
ByteBuffer buffer = ByteBuffer.allocate(1024);
CharBuffer cb = CharBuffer.allocate(1024);
StringBuffer line = new StringBuffer("");
int count = fc.read(buffer);
// NIO读取文件
while (count != -1) {
buffer.flip();
decoder.decode(buffer, cb, false);
cb.flip();
while (cb.hasRemaining()) {
line.append(cb.get());
}
buffer.clear();
cb.clear();
count = fc.read(buffer);
}
raf.close();
// 有数据则读取比对
List<String> itemsList = Arrays.asList(items.split(","));
List<String> lineList = Arrays.asList(line.toString().split(","));
// tmp用于临时存储itemsList, 数组转化的集合长度固定不能执行增删操作,所以新建两个集合
List<String> tmp = new ArrayList<String>();
List<String> l1 = new ArrayList<String>();
List<String> l2 = new ArrayList<String>();
tmp.addAll(itemsList);
l1.addAll(itemsList);
l2.addAll(lineList);
l1.removeAll(lineList);
l2.removeAll(tmp);
// 存在差异则写入新的数据
if (l1.size() != 0 || l2.size() != 0) {
outputStream = new FileOutputStream(path, false);
out = outputStream.getChannel();
buffer.clear();
byte[] bytes = items.getBytes();//将字符串转换为字符数组
buffer.put(bytes);
buffer.flip();
log.info("content change:" + items);
out.write(buffer);
HttpUtils http = new HttpUtils(items);
int uploadCount = 0;
while (uploadCount < 3) {
http.dataDeal();
String response = http.postRequest();
JSONObject resJSON = JSONObject.fromObject(response);
if (resJSON != null && resJSON.containsKey("code")) {
int code = resJSON.getInt("code");
if (code == 0) {
uploadCount = 3;
}else{
uploadCount++;
}
}
}
} else {
log.info("no change");
}
} finally {
if (outputStream != null) {
outputStream.close();
}
if (raf != null) {
raf.close();
}
log.info(
"=-------------------------------------------------------------------------------------------------=");
}
}
发现问题最关键的在于
ByteBuffer buffer = ByteBuffer.allocate(1024);
什么是ByteBuffer ?
一般是操作数据的字节(byte)形式,经常会用到ByteBuffer这样一个类。ByteBuffer提供了两种静态实例方式:
public static ByteBuffer allocate(int capacity)
public static ByteBuffer allocateDirect(int capacity)
(为什么要提供两种方式呢?这与Java的内存使用机制有关。第一种分配方式产生的内存开销是在JVM中的,而另外一种的分配方式产生的开销在JVM之外,以就是系统级的内存分配。不细说,咱也不会。)
写入的字节流超过了分配的1024,因此写入失败。只需要扩大分配容量即可。尴尬。