【发布时间】:2012-09-12 12:01:36
【问题描述】:
在阅读旧的 InputStream 时,我使用了以下代码(我从来不习惯):
int read = 0;
InputStream is = ....;
while((i = is.read() != -1){
....
}
现在我正在尝试使用 NIO 从 InputStream 中读取 10MB:
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("In Controller.doPost(...)");
ByteBuffer chunk = ByteBuffer.allocateDirect(1000000);
/* Source channel */
int numRead = 0;
ReadableByteChannel rbc = Channels.newChannel(request.getInputStream());
/* Destination channel */
File destFile = new File(
"D:\\SegyDest.sgy");
FileOutputStream destFileFos = new FileOutputStream(destFile);
FileChannel destFileChannel = destFileFos.getChannel();
/* Read-Write code */
while (numRead >= 0) {
chunk.rewind();
numRead = rbc.read(chunk);
System.out.println("numRead = " + numRead);
chunk.rewind();
destFileChannel.write(chunk);
}
/* clean-up */
rbc.close();
destFileChannel.close();
destFileFos.close();
request.setAttribute("ops", "File Upload");
request.getRequestDispatcher("/jsp/Result.jsp").forward(request,
response);
}
我的问题是 /* 如何遍历源通道来读取所有字节? */
【问题讨论】:
-
谷歌上 ReadableByteChannel 的首页有一个看起来像一个工作示例exampledepot.com/egs/java.nio/ReadChannel.html 你需要重置()然后读取()然后重置()然后写入()。
-
嗨,Darryl,我编辑了我的原始帖子以包含您提供的链接中建议的实现。但它似乎没有“循环” - 无论我初始化“块”的大小如何,目标文件的大小都是相同的。输出是: numRead = 96 numRead = -1 我在这里遗漏了什么吗?
-
FWIW 为什么在看起来像 Servlet 的内部使用非阻塞 IO?你知道 Servlet API 被阻塞了吗?您正在尝试在阻塞 IO 句柄之上构建 NIO 方案。要进行 NIO,您必须使用 OS 非阻塞 IO 句柄作为构建的基础。您最好将新的 WebSocket Servlet API 之一用于非阻塞 IO 模型。
-
在 Servlet 中按原样使用 InputStream 非常好,因为 IO 模型是每个活动请求一个线程。考虑 NIO 的唯一原因是,如果您在同一线程中有一些有用的事情要做在读/写 IO 之间的时间相同。您的示例没有证明这种需要,它也没有检查成功写入的字节数,也没有处理积压的策略(输入 IO 比输出 IO 快,您被卡住了数据)。我认为您尝试使用 NIO这里可能会误导你有一些“不舒服”的感觉,收缩是最好的。
-
我不会在最终代码中编写 Servlet 中的 I/O 代码,在这里,我在 doPost(...) 中编写只是为了让我的方法清晰。实际上,我问的问题是在以下上下文中:stackoverflow.com/questions/12500185/… 请检查相同并指导我。