将 ByteString 写入文件导致 NullPointerException
Writing ByteString to File Causing NullPointerException
我有一个 Akka actor,它以大约 1500 字节的块读取文件的内容。当 actor 收到 NextBlock 消息时,它会回复包含在 ByteString 中的下一个数据块。一些非常简单的测试和手动观察数据表明演员工作正常。我正在使用 Scala 2.11.5、Akka 2.3.9、ScalaTest 2.2.1 和 SBT 0.13.5。
我在设置更大的测试时遇到问题。我想将大约 10kB 左右的测试模式数据写入文件,然后验证 Actor 的输出是否符合我的预期。我正在通过 ByteStringBuilder 创建测试模式。当我将测试数据写入文件时,出现 NullPointerExceptions。以下是显示该问题的精简版测试的代码:
import java.nio.ByteOrder
import java.nio.file.StandardOpenOption._
import java.nio.file.{Files, Paths}
import akka.actor.ActorSystem
import akka.testkit.TestKit
import akka.util.{ByteString, ByteStringBuilder}
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
class ByteBufferTest extends TestKit(ActorSystem("ByteBufferTest"))
with WordSpecLike with Matchers with BeforeAndAfterAll {
implicit val byteOrder = ByteOrder.BIG_ENDIAN
val file = Paths.get("test.data")
Files.deleteIfExists(file)
createTestFile()
"A ByteBufferTest" must { "work" in { assert(true) } }
def createTestFile(): Unit = {
val out = Files.newByteChannel(file, CREATE, WRITE)
out.write(contents.toByteBuffer) // Here is where the NPE occurs
out.close()
}
val contents: ByteString = {
val builder = new ByteStringBuilder
(0 to 255).foreach(builder.putInt)
builder.result()
}
override protected def afterAll(): Unit = {
Files.delete(file)
system.shutdown()
}
}
我试过很多不同的方法来解决这个问题
- 将 ByteString 转换为 ByteBuffer 并通过 ByteChannel 写入(如上所示)
- 将 ByteString 的各个字节写入 BufferedOutputStream
- 将 ByteString 转换为 Array[Byte] 并通过 BufferedOutputStream 写入
无论我尝试什么,我都会以
的方式结束
[debug] Running TaskDef(demo.ByteBufferTest, org.scalatest.tools.Framework$$anon@40fbf2c, false, [SuiteSelector])
java.lang.NullPointerException at demo.ByteBufferTest.createTestFile(ByteBufferTest.scala:32)
at demo.ByteBufferTest.<init>(ByteBufferTest.scala:21)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:374)
at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:641)
at sbt.TestRunner.runTest(TestFramework.scala:84)
at sbt.TestRunner.run(TestFramework.scala:94)
at sbt.TestFramework$$anon$$anonfun$$init$$$anonfun$apply.apply(TestFramework.scala:219)
at sbt.TestFramework$$anon$$anonfun$$init$$$anonfun$apply.apply(TestFramework.scala:219)
at sbt.TestFramework$.sbt$TestFramework$$withContextLoader(TestFramework.scala:207)
at sbt.TestFramework$$anon$$anonfun$$init$.apply(TestFramework.scala:219)
at sbt.TestFramework$$anon$$anonfun$$init$.apply(TestFramework.scala:219)
at sbt.TestFunction.apply(TestFramework.scala:224)
at sbt.Tests$$anonfun.apply(Tests.scala:196)
at sbt.Tests$$anonfun.apply(Tests.scala:196)
at sbt.std.Transform$$anon$$anonfun$apply.apply(System.scala:45)
at sbt.std.Transform$$anon$$anonfun$apply.apply(System.scala:45)
at sbt.std.Transform$$anon.work(System.scala:64)
at sbt.Execute$$anonfun$submit$$anonfun$apply.apply(Execute.scala:237)
at sbt.Execute$$anonfun$submit$$anonfun$apply.apply(Execute.scala:237)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
at sbt.Execute.work(Execute.scala:244)
at sbt.Execute$$anonfun$submit.apply(Execute.scala:237)
at sbt.Execute$$anonfun$submit.apply(Execute.scala:237)
at sbt.ConcurrentRestrictions$$anon$$anonfun.apply(ConcurrentRestrictions.scala:160)
at sbt.CompletionService$$anon.call(CompletionService.scala:30)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
有人知道我做错了什么吗?
我已经在 github
上放了一个示例项目
我没有找到确切的根本原因,但似乎与从 scala 测试 class 启动测试时的初始化有关。
我建议把createTestFile()
放在beforeAll()方法中。已测试,有效。
override def beforeAll {
createTestFile()
}
我有一个 Akka actor,它以大约 1500 字节的块读取文件的内容。当 actor 收到 NextBlock 消息时,它会回复包含在 ByteString 中的下一个数据块。一些非常简单的测试和手动观察数据表明演员工作正常。我正在使用 Scala 2.11.5、Akka 2.3.9、ScalaTest 2.2.1 和 SBT 0.13.5。
我在设置更大的测试时遇到问题。我想将大约 10kB 左右的测试模式数据写入文件,然后验证 Actor 的输出是否符合我的预期。我正在通过 ByteStringBuilder 创建测试模式。当我将测试数据写入文件时,出现 NullPointerExceptions。以下是显示该问题的精简版测试的代码:
import java.nio.ByteOrder
import java.nio.file.StandardOpenOption._
import java.nio.file.{Files, Paths}
import akka.actor.ActorSystem
import akka.testkit.TestKit
import akka.util.{ByteString, ByteStringBuilder}
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
class ByteBufferTest extends TestKit(ActorSystem("ByteBufferTest"))
with WordSpecLike with Matchers with BeforeAndAfterAll {
implicit val byteOrder = ByteOrder.BIG_ENDIAN
val file = Paths.get("test.data")
Files.deleteIfExists(file)
createTestFile()
"A ByteBufferTest" must { "work" in { assert(true) } }
def createTestFile(): Unit = {
val out = Files.newByteChannel(file, CREATE, WRITE)
out.write(contents.toByteBuffer) // Here is where the NPE occurs
out.close()
}
val contents: ByteString = {
val builder = new ByteStringBuilder
(0 to 255).foreach(builder.putInt)
builder.result()
}
override protected def afterAll(): Unit = {
Files.delete(file)
system.shutdown()
}
}
我试过很多不同的方法来解决这个问题
- 将 ByteString 转换为 ByteBuffer 并通过 ByteChannel 写入(如上所示)
- 将 ByteString 的各个字节写入 BufferedOutputStream
- 将 ByteString 转换为 Array[Byte] 并通过 BufferedOutputStream 写入
无论我尝试什么,我都会以
的方式结束[debug] Running TaskDef(demo.ByteBufferTest, org.scalatest.tools.Framework$$anon@40fbf2c, false, [SuiteSelector])
java.lang.NullPointerException at demo.ByteBufferTest.createTestFile(ByteBufferTest.scala:32)
at demo.ByteBufferTest.<init>(ByteBufferTest.scala:21)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:374)
at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:641)
at sbt.TestRunner.runTest(TestFramework.scala:84)
at sbt.TestRunner.run(TestFramework.scala:94)
at sbt.TestFramework$$anon$$anonfun$$init$$$anonfun$apply.apply(TestFramework.scala:219)
at sbt.TestFramework$$anon$$anonfun$$init$$$anonfun$apply.apply(TestFramework.scala:219)
at sbt.TestFramework$.sbt$TestFramework$$withContextLoader(TestFramework.scala:207)
at sbt.TestFramework$$anon$$anonfun$$init$.apply(TestFramework.scala:219)
at sbt.TestFramework$$anon$$anonfun$$init$.apply(TestFramework.scala:219)
at sbt.TestFunction.apply(TestFramework.scala:224)
at sbt.Tests$$anonfun.apply(Tests.scala:196)
at sbt.Tests$$anonfun.apply(Tests.scala:196)
at sbt.std.Transform$$anon$$anonfun$apply.apply(System.scala:45)
at sbt.std.Transform$$anon$$anonfun$apply.apply(System.scala:45)
at sbt.std.Transform$$anon.work(System.scala:64)
at sbt.Execute$$anonfun$submit$$anonfun$apply.apply(Execute.scala:237)
at sbt.Execute$$anonfun$submit$$anonfun$apply.apply(Execute.scala:237)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
at sbt.Execute.work(Execute.scala:244)
at sbt.Execute$$anonfun$submit.apply(Execute.scala:237)
at sbt.Execute$$anonfun$submit.apply(Execute.scala:237)
at sbt.ConcurrentRestrictions$$anon$$anonfun.apply(ConcurrentRestrictions.scala:160)
at sbt.CompletionService$$anon.call(CompletionService.scala:30)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
有人知道我做错了什么吗?
我已经在 github
上放了一个示例项目我没有找到确切的根本原因,但似乎与从 scala 测试 class 启动测试时的初始化有关。
我建议把createTestFile()
放在beforeAll()方法中。已测试,有效。
override def beforeAll {
createTestFile()
}