gpt4 book ai didi

java - 如何在 Scala 或 Java 中读取具有混合编码的文本文件?

转载 作者:IT老高 更新时间:2023-10-28 20:32:44 24 4
gpt4 key购买 nike

我正在尝试解析 CSV 文件,最好使用 weka.core.converters.CSVLoader。但是,我拥有的文件不是有效的 UTF-8 文件。它主要是一个 UTF-8 文件,但一些字段值采用不同的编码,所以没有整个文件有效的编码,但无论如何我都需要解析它。除了使用像 Weka 这样的 java 库之外,我主要在 Scala 中工作。我什至无法读取使用 scala.io.Source 的文件:例如

Source.
fromFile(filename)("UTF-8").
foreach(print);

抛出:

    java.nio.charset.MalformedInputException: Input length = 1
at java.nio.charset.CoderResult.throwException(CoderResult.java:277)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:337)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:176)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:153)
at java.io.BufferedReader.read(BufferedReader.java:174)
at scala.io.BufferedSource$$anonfun$iter$1$$anonfun$apply$mcI$sp$1.apply$mcI$sp(BufferedSource.scala:38)
at scala.io.Codec.wrap(Codec.scala:64)
at scala.io.BufferedSource$$anonfun$iter$1.apply(BufferedSource.scala:38)
at scala.io.BufferedSource$$anonfun$iter$1.apply(BufferedSource.scala:38)
at scala.collection.Iterator$$anon$14.next(Iterator.scala:150)
at scala.collection.Iterator$$anon$25.hasNext(Iterator.scala:562)
at scala.collection.Iterator$$anon$19.hasNext(Iterator.scala:400)
at scala.io.Source.hasNext(Source.scala:238)
at scala.collection.Iterator$class.foreach(Iterator.scala:772)
at scala.io.Source.foreach(Source.scala:181)

我很高兴将所有无效字符扔掉或用一些虚拟字符替换它们。我将有很多这样的文本以各种方式处理并且可能需要将数据传递给各种第三方库。一个理想的解决方案是某种全局设置,它将导致所有低级 java 库忽略文本中的无效字节,这样我就可以在不修改的情况下调用第三方库。

解决方案:

import java.nio.charset.CodingErrorAction
import scala.io.Codec

implicit val codec = Codec("UTF-8")
codec.onMalformedInput(CodingErrorAction.REPLACE)
codec.onUnmappableCharacter(CodingErrorAction.REPLACE)

val src = Source.
fromFile(filename).
foreach(print)

感谢 +Esailija 为我指明了正确的方向。这导致我到How to detect illegal UTF-8 byte sequences to replace them in java inputstream?它提供了核心的 java 解决方案。在 Scala 中,我可以通过使编解码器隐式来使其成为默认行为。我想我可以通过将其隐式编解码器定义放在包对象中,使其成为整个包的默认行为。

最佳答案

这就是我设法用 java 做到的:

    FileInputStream input;
String result = null;
try {
input = new FileInputStream(new File("invalid.txt"));
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
decoder.onMalformedInput(CodingErrorAction.IGNORE);
InputStreamReader reader = new InputStreamReader(input, decoder);
BufferedReader bufferedReader = new BufferedReader( reader );
StringBuilder sb = new StringBuilder();
String line = bufferedReader.readLine();
while( line != null ) {
sb.append( line );
line = bufferedReader.readLine();
}
bufferedReader.close();
result = sb.toString();

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch( IOException e ) {
e.printStackTrace();
}

System.out.println(result);

无效文件是用字节创建的:

0x68, 0x80, 0x65, 0x6C, 0x6C, 0xC3, 0xB6, 0xFE, 0x20, 0x77, 0xC3, 0xB6, 0x9C, 0x72, 0x6C, 0x64, 0x94

在 UTF-8 中是 hello wörld,其中混入了 4 个无效字节。

使用 .REPLACE 您会看到正在使用的标准 unicode 替换字符:

//"h�ellö� wö�rld�"

使用 .IGNORE,您会看到无效字节被忽略:

//"hellö wörld"

不指定.onMalformedInput,你会得到

java.nio.charset.MalformedInputException: Input length = 1
at java.nio.charset.CoderResult.throwException(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)

关于java - 如何在 Scala 或 Java 中读取具有混合编码的文本文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13625024/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com