无法处理大于 65535 个字符的字符串文字。编译器抛出 IllegalArgumentException

Unable to handle String literals size greater than 65535 characters. Compiler throws IllegalArgumentException

我正在尝试在 Scala 中解码 Base64 编码的图像。字符串文字的长度超过 65535 个字符。每当我尝试编译以下代码时,编译器都会给出 IllegalArgumentException。

Scala 代码:

val data = "/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAA ... "
val imageByte = Base64.getDecoder.decode(data)        
val byteArray = new ByteArrayInputStream(imageByte)       
val image = ImageIO.read(byteArray)                       
ImageIO.write(image, "jpeg", new File("image.jpeg"))

编译器异常:

Error:scalac: Error:         org.jetbrains.jps.incremental.scala.remote.ServerException
java.lang.IllegalArgumentException
at scala.tools.asm.ByteVector.putUTF8(ByteVector.java:213)
at scala.tools.asm.ClassWriter.newUTF8(ClassWriter.java:1092)
at scala.tools.asm.ClassWriter.newString(ClassWriter.java:1525)
at scala.tools.asm.ClassWriter.newConstItem(ClassWriter.java:1042)
at scala.tools.asm.MethodWriter.visitLdcInsn(MethodWriter.java:1134)
at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder.genConstant(GenASM.scala:1582)
at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder.scala$tools$nsc$backend$jvm$GenASM$JPlainBuilder$$genInstr(GenASM.scala:2296)
at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder$$anonfun$genBlock.apply(GenASM.scala:2227)
at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder$$anonfun$genBlock.apply(GenASM.scala:2213)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
at scala.tools.nsc.backend.icode.BasicBlocks$BasicBlock.foreach(BasicBlocks.scala:195)
at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder.genBlock(GenASM.scala:2213)
at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder.genBlocks(GenASM.scala:2151)
at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder.genCode(GenASM.scala:2746)
at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder.genMethod(GenASM.scala:1471)
at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder.genClass(GenASM.scala:1341)
at scala.tools.nsc.backend.jvm.GenASM$AsmPhase.emitFor(GenASM.scala:198)
at scala.tools.nsc.backend.jvm.GenASM$AsmPhase.run(GenASM.scala:204)
at scala.tools.nsc.Global$Run.compileUnitsInternal(Global.scala:1501)
at scala.tools.nsc.Global$Run.compileUnits(Global.scala:1486)
at scala.tools.nsc.Global$Run.compileSources(Global.scala:1481)
at scala.tools.nsc.Global$Run.compile(Global.scala:1582)
at xsbt.CachedCompiler0.run(CompilerInterface.scala:115)
at xsbt.CachedCompiler0.run(CompilerInterface.scala:94)
at xsbt.CompilerInterface.run(CompilerInterface.scala:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:101)
at sbt.compiler.AnalyzingCompiler.compile(AnalyzingCompiler.scala:47)
at sbt.compiler.AnalyzingCompiler.compile(AnalyzingCompiler.scala:41)
at org.jetbrains.jps.incremental.scala.local.IdeaIncrementalCompiler.compile(IdeaIncrementalCompiler.scala:29)
at org.jetbrains.jps.incremental.scala.local.LocalServer.compile(LocalServer.scala:26)
at org.jetbrains.jps.incremental.scala.remote.Main$.make(Main.scala:67)
at org.jetbrains.jps.incremental.scala.remote.Main$.nailMain(Main.scala:24)
at org.jetbrains.jps.incremental.scala.remote.Main.nailMain(Main.scala)
at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.martiansoftware.nailgun.NGSession.run(NGSession.java:319)

根据这个 bug,我了解到根据 JVM 规范,字节长度大于 2 字节的字段不适合。经过详尽的搜索后,我无法找到解决此问题的方法,该错误仍然存​​在。在 Java/Scala.

中处理长字符串文字可能是一个很好的解决方法

如果一次可以读取四个字节,则解码后将正好对应三个字节。将它们连接在一起,你会得到相同的结果。

当文字这么长时,由于可读性问题,它真的不应该再嵌入到代码中。我会从 file/resource.

加载它

Java

使用 Commons IO 这真的很容易做到:

String str = IOUtils.toString(this.getClass().getResource("myResource", StandardCharsets.UTF_8);

我认为可读性稍差,但如果你真的不想使用任何库,你也可以从 Java 7:

开始
String str = new String(Files.readAllBytes(Paths.get("myResource")), StandardCharsets.UTF_8);

斯卡拉

在 Scala 中你可以使用 build-in scala.io.Source class:

val testTxtSource = Source.fromFile("myResource")
val str = testTxtSource.mkString()
testTxtSource.close()