当前位置: 首页 > 知识库问答 >
问题:

Java nio仅读取8192/433000字节

劳昊明
2023-03-14

为了更好地理解JavaNIO和网络编程,我正在进行一个项目。我正试图通过netcat将一个400000字节的文件发送到我的服务器,在那里可以找到并写入文件。

问题是:当文件小于10000字节时,或者当我放置一个线程时,程序可以完美地工作。选择()之前的睡眠(超时)。该文件发送但只读取8192字节,然后取消循环并返回select()以捕获其余数据。但是,该文件捕获了后面的内容。我需要完整的数据进一步扩大到该项目。

我尝试过的事情:我尝试将数据加载到另一个字节数组中,该数组显然有效,但跳过了8192个字节(因为再次调用了select()。读取391000字节的其余部分。比较文件时,缺少前8192个字节。我尝试过很多其他的事情,但我在NIO中还不足以理解我把事情搞砸了。

我的代码

这正是我感觉代码混乱的地方(调试后)

private void startServer() {
   File temp = new File("Filepath");
   Selector selector = Selector.open();
   ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
   serverSocketChannel.configureBlocking(false);
   serverSocketChannel.socket().bind(listenAddress);
   serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

   log.info("Server Socket Channel Started");

   while(!stopRequested){
     selector.select();
     Set<SelectionKey> keys = selector.selectedKeys();

     for(SelectionKey key : keys){
       if(key.isAcceptable()){
         try {
           serverSocketChannel = (ServerSocketChannel) key.channel();
           SocketChannel socket = serverSocketChannel.accept();
           socket.configureBlocking(false);
           socket.register(selector, SelectionKey.OP_READ);
         }catch (IOException e) {
           log.error("IOException caught: ", e);
         }
       }
       if(key.isReadable(){ read(key); }
       keys.remove(key);
     }
   } 
  } catch (IOException e) {
    log.error("Error: ", e);
  }
}

private void read(SelectionKey key) {
  int count = 0;
  File tmp = new File("Path");

  try {
    SocketChannel channel = (SocketChannel) key.channel();
    byteBuffer.clear();
    while((count = channel.read(byteBuffer)) > 0) {
         byteBuffer.flip();
         //in bytearrayoutputstream to append to data byte array
         byteArrayOutputStream.write(byteBuffer.array(), byteBuffer.arrayOffset(), count);
         byteBuffer.compact();
      }
    }
    data = byteArrayOutputStream.toByteArray();
    FileUtils.writeByteArrayToFile(tmp, data);
  }
}


上面的代码就是我正在使用的代码。我在这门课上有更多的东西,但我相信主要有两个函数有问题,就是这两个。我不太确定我应该采取什么措施。我必须测试我的程序的文件包含许多TCP,大约400000字节。select()收集最初的8192个字节,然后运行read(在捕获流中的所有数据之前不应该执行),然后返回并收集其余的字节。我已将byteBuffer分配为30720字节。

如果不清楚,我可以张贴代码的其余部分,让我知道你的建议是什么。

问题
为什么当分配的空间是30720时,这段代码只抓取8192字节?为什么它工作在调试模式或与Thread.sleep()?

以前的人建议我把行李放在行李架上。clear()在循环之外,即使这样做,问题仍然存在。

共有1个答案

巴照
2023-03-14

非阻塞API仅promise,如果存在超过0个字节,则会引发“可读”状态。它不能保证它会等到您感兴趣的所有字节都到达;甚至没有一种方式可以说“在至少有X个字节进入之前,不要将此频道标记为可读取”。没有办法直接解决这个问题;相反,您的代码必须能够处理半满的缓冲区。例如,通过读取这些数据,清除“isReadable”状态,直到更多字节到达。

使用原始的非阻塞API是火箭科学(例如,正确编写代码非常棘手,很容易让CPU内核旋转到100%,因为您对标志管理不当,并且很容易冻结所有线程由于意外调用阻塞方法,应用程序只能处理正常线程变体所能处理的一两个百分比。

我强烈建议您首先重新考虑是否需要非阻塞(它总是很慢,而且开发起来难度也很大。毕竟,你不能在任何处理程序代码的任何地方进行一次潜在的阻塞调用,否则你的应用程序在加载时都会非常慢,而且java在等待/产生东西方面也不是很好——唯一真正的好处是你可以更细粒度地控制缓冲区大小,这是不可改变的vant,除非您的RAM非常有限,并且可以为每个连接状态使用很小的缓冲区)。如果您认为这确实是唯一的方法,那么请使用使此API更易于使用的库,例如netty。

 类似资料:
  • 问题内容: 我正在使用for循环读取文件,但是我只想读取特定的行,例如26号和30号行。是否有任何内置功能可实现此目的? 问题答案: 如果要读取的文件很大,并且你不想一次读取内存中的整个文件: 注意,对于nth行。 在Python 2.6或更高版本中:

  • 问题内容: 我正在尝试实现基本的词法分析器。目前,我在文件解析方面陷入困境。 这是我的栏位,称为“ p ++。ppp” 解析文件时,我得到:但是p ++。ppp是文件名! 同样,当我调试时,它读取文件名,然后退出。我想念什么? 问题答案: 您误解了的API 。从文档的构造函数: 构造一个新的Scanner,该扫描器生成从指定字符串扫描的值。 参数: 源 -一个字符串,扫描 这不是文件名-只是一个字

  • 问题内容: 我想要类似C的选项。如何仅从命令行读取单个字符输入? 使用命令可以做到吗? 问题答案: 在ksh中,您基本上可以执行以下操作:

  • 一个更简单的方法,无需插件。生成安装文件更加的小。 引用 Setup.nsi 的内容: /*----------------------------------------------/ / 关于 NSIS 自定义控件写入超过 8192 字节的插件。/ / 理论上如果控件能够容纳,多大的文本都能放入 / /---------------------------------------

  • 我已经将选项设置为我的时区(并且我也尝试了),这样就节省了时间,但是,当从数据库读取时间时,Sequelize会将其转换为UTC。我也尝试了不同的时区,每一个都正确保存,但总是转换为UTC时,从数据库读取。 是我做错了什么,还是这是一个已知的问题,有什么解决方法吗?

  • eclipse编译的结果类文件和传统的“javac”命令是不同的。所以我想在eclipse中编译Java源代码来得到它的特殊输出。还有,这个输出只能由eclipse自己打开(至少我不知道其他打开方式)。然而,打开这么多文件并将内容复制到记事本上是一项艰苦的工作。 那么,有没有其他方法可以自动读取eclipse生成的类文件呢?我猜控制台中有一些命令可以使用eclipse并自动输出结果? 谢谢