【问题标题】:Java windows write bytes to file, some are incorrect [duplicate]Java windows将字节写入文件,有些不正确[重复]
【发布时间】:2017-04-02 17:48:52
【问题描述】:

我的目标是将字节流从套接字读取到文件中,然后稍后将其作为我的应用程序的测试工具进行回放。在将字节写入磁盘的某个地方,一个字节会被错误地写入,似乎是随机的。

我的作者是这样的:

blobWriter = new BufferedOutputStream(new FileOutputStream(blobFileName));  
blobChannel = Channels.newChannel(blobWriter);

我正在使用blobChannel,这样我就可以直接从ByteBuffer 写信。在每次读取套接字时,我只需将缓冲区传递给写入器:

if (key.isReadable()) {
    final int bytesRead= socketChannel.read(readBuffer);

    if(bytesRead == -1)
    {
        logger.warn("no bytes to read");
        break;
    }

    readBuffer.flip();
    blobChannel.write(readBuffer);
    ... 
    <continue to process data>
}

当提要处于活动状态时,程序会处理对记录的读取,并且它们不会损坏。假设每条消息,它输出一个包含 7 个字段的元组。例如,其中之一是这样的:

(tupleid=0,msgType=110,feedId=225,venueId=30,orderId=160,symbol="CHF.NOK.SPOT",venueTime=44417979)

当我没有与市场建立实时连接,而是将应用程序连接到从磁盘播放相同数据的读取器时,处理后的输出会变得混乱:

(tupleid=0,msgType=110,feedId=225,venueId=30,orderId=160,symbol="CHF.-�ûnX",venueTime=44417979)

注意损坏的符号

最奇怪的是它会处理数千条具有相同符号和其他字段的消息,但随后莫名其妙地一条消息被破坏了。并不总是符号字段不正确,有时 orderId 错误等等......

我怀疑blobWriter 有时会写错。我的操作系统(Windows 7)可以做一些时髦的事情吗?我检查了notepad++ 中保存到磁盘的字节流,确实它显示了不正确的字节,所以错误必须在文件编写器中,而不是在我的播放机制中。此外,如果主应用程序本身有问题,它应该会误读实时提要上的字节;它没有。

有谁知道可能出了什么问题?

【问题讨论】:

  • 输出显示在哪里?
  • 具体是哪个输出?
  • 你提到的'处理后的输出'。
  • 我展示的两个元组记录是处理输出的一个例子。第一个,具有正确的字段,是在实时市场上完成处理时。第二个,有一个坏字节,是一个处理从保存到磁盘的数据的例子。我在想 writeBufferChannel 可能是问题所在,因为服务器处于非阻塞模式并且 javadoc 提到这可能是一个问题
  • EJP,这真的是重复的吗,因为我在发布之前阅读了那个问题?如果是这样,我会改变我的作家以确保正确的行为?顺便说一句,我的频道似乎正在写入更多字节,而我的读者实际上是从缓冲区读取的。

标签: java sockets io buffer nio


【解决方案1】:

看起来WritableByteChannel javaDoc 试图警告我:

除非另有说明,否则写入操作将仅在 写入所有 r 个请求的字节。某些类型的渠道, 根据它们的状态,可能只写一些字节或 可能根本没有。非阻塞模式的套接字通道,用于 例如,不能写入比套接字中空闲更多的字节 输出缓冲区。

确实,套接字通道处于非阻塞模式。我对此进行了分析,每 200 次左右的读取中就有一个不同步。看起来我的频道正在写入更多字节,而我的读者实际上是从缓冲区读取的。

Another SO thread offers more information.

最终对我有用的是在每次读取时复制字节数组,而不是使用流。这可能不是性能最优的,但至少不会导致错误的数据:

if (readBuffer.hasRemaining()){
    byte[] b = new byte[readBuffer.remaining()]
    readBuffer.get(b)
    blobWriter.write(b)
}

【讨论】:

  • 不需要将其复制到字节数组中。一个简单的while (readBuffer.remaining() &gt; 0) blobWriter.write(readBuffer); 应该没问题。但是,如果我理解正确的话,你真的经历过这样一个案例,你链接到的我的问题的答案是 “不,它不会总是写入整个缓冲区” - 这是正确的吗?跨度>
  • 谢谢马可,我相信是的。
  • 我试过这个 Marco,但仍然误读。我打开了一个单独的线程,因为我遇到了同样的问题并且不再使用频道:stackoverflow.com/questions/40725665/…
猜你喜欢
  • 2012-09-22
  • 1970-01-01
  • 2016-09-01
  • 1970-01-01
  • 2011-11-08
  • 2015-07-02
  • 2021-10-22
  • 1970-01-01
相关资源
最近更新 更多