仅在匹配阈值字节时才在地图中填充字符串值

我有一个tasks列表对象,我正在迭代并将每个任务对象附加到StringBuilder后跟新行,如下所示。 现在,我将继续在同一个字符串构建器中追加任务对象,直到达到60000字节的大小限制。 一旦达到限制,我将把这个字符串填充为map中的值,key将是带有增量索引的文件名。 然后我将重置字符串构建器和其他东西并再次重复此过程。

因此,如果我有一个大tasks对象,那么我将拆分成多个字符串对象,其大小应始终小于60000字节。

我得到了下面的代码,但我总是看到地图中的值大小超过60000字节。 我做错了什么? 此外,我在两个不同的位置填充HashMap – 一个达到限制,另一个是如果未达到限制。

  public void populate(final List tasks) { Map holder = new HashMap(); int size = 0; int index = 0; StringBuilder sb = new StringBuilder(); for (Task task : tasks) { sb.append(task).append(System.getProperty("line.separator")); size = sb.toString().getBytes(StandardCharsets.UTF_8).length; if (size > 60000) { String fileName = "tasks_info_" + index + ".txt"; holder.put(fileName, sb.toString()); index++; sb = new StringBuilder(); size = 0; } } // for cases where we don't reach the limit if(sb.toString().length > 0) { String fileName = "tasks_info_" + index + ".txt"; holder.put(fileName, sb.toString()); } System.out.println(holder); } 

注意:如果每个Task对象超过60000 bytes ,那么我将立即删除该对象并移至下一个条目。 但实际上,它不会发生。

更新:

 public void populate(final List tasks, final long timestamp) { Map holder = new HashMap(); int size = 0; int index = 0; int nl = System.getProperty("line.separator").getBytes(StandardCharsets.UTF_8).length; StringBuilder sb = new StringBuilder(); // new change sb.append(timestamp).append(System.getProperty("line.separator")); for (Task task : tasks) { int ts = String.valueOf(task).getBytes(StandardCharsets.UTF_8).length; if (size + ts + nl > 60000) { String fileName = "tasks_info_" + index + ".txt"; holder.put(fileName, sb.toString()); index++; sb = new StringBuilder(); // new change sb.append(timestamp).append(System.getProperty("line.separator")); size = 0; } sb.append(task).append(System.getProperty("line.separator")); size += ts + nl; } // for cases where we don't reach the limit if (size > 0) { // size can only be 0 if you have 0 tasks String fileName = "tasks_info_" + index + ".txt"; holder.put(fileName, sb.toString()); } System.out.println(holder); } 

其他答案已经提到了它不起作用的原因(在它已经超出限制之后添加)。 但我认为到目前为止没有一个实现是正确的,不仅仅是因为新行的大小被省略了。

 public Map populate(final List tasks) { Map holder = new HashMap<>(); if (tasks.size() == 0) return holder; int index = 0; int nl = System.getProperty("line.separator").getBytes(StandardCharsets.UTF_8).length; StringBuilder sb = new StringBuilder(); sb.append(System.currentTimeMillis()).append(System.getProperty("line.separator")); int size = sb.toString().getBytes(StandardCharsets.UTF_8).length; for (Task task : tasks) { int ts = String.valueOf(task).getBytes(StandardCharsets.UTF_8).length; if (size + ts + nl > 60000) { String fileName = "tasks_info_" + index + ".txt"; holder.put(fileName, sb.toString()); index++; sb = new StringBuilder(); sb.append(System.currentTimeMillis()).append(System.getProperty("line.separator")); size = sb.toString().getBytes(StandardCharsets.UTF_8).length; } sb.append(task).append(System.getProperty("line.separator")); size += ts + nl; } String fileName = "tasks_info_" + index + ".txt"; holder.put(fileName, sb.toString()); return holder; } 

我试用了你的代码以确保解决方案。 在将新任务的值实际添加到SB之前,您需要尝试检查下一个大小。 我修改了代码以反映这个解决方案。 你可以尝试一下,告诉我们它是否适合你?

 public void populate(final List tasks) { Map holder = new HashMap<>(); int size = 0; int index = 0; int lengthTask = 0; int lengthSb = 0; StringBuilder sb = new StringBuilder(); for (Task task : tasks) { lengthTask = task.toString().getBytes(StandardCharsets.UTF_8).length; lengthSb = sb.toString().getBytes(StandardCharsets.UTF_8).length; if (size + lengthTask + lengthSb > 60000) { System.out.println("last added size "+size); String fileName = "tasks_info_" + index + ".txt"; holder.put(fileName, sb.toString()); index++; sb = new StringBuilder(); size = 0; } sb.append(task).append(System.getProperty("line.separator")); size += sb.toString().getBytes(StandardCharsets.UTF_8).length; System.out.println("size "+size); } // for cases where we don't reach the limit String fileName = "tasks_info_" + index + ".txt"; holder.put(fileName, sb.toString()); System.out.println(holder); } 

如果我正确理解代码,我想它应该是

  size = sb.toString().getBytes(StandardCharsets.UTF_8).length; 

并且当前它在字符串大小超过60000字节后插入映射,因此映射中的值超过60000字节

 if (size > 60000) { ... holder.put(fileName, sb.toString()); ... }