Проблема: правильная обработка спецификации UTF-8 при загрузке файла в строку Scala. Строка будет использоваться в качестве входных данных в XML.
Примечание. При вызове scala.xml.XML.loadString () происходит сбрасывание стека, если я не удаляю спецификацию из строки.
Ищу совет, как правильно загрузить файл в строку. Мне известно о scala.xml.XML.loadFile (), который правильно загружает файл со спецификацией в XML, но сначала мне нужно выполнить предварительную обработку строки.
Версия Scala: 2.11.8
Код:
import scala.xml.XML
import scala.compat.Platform.EOL
object Test {
val filename = "Tags_small.xml" // BOM present
// val filename = "Tags_test.xml" // BOM removed
def main(args: Array[String]) {
// The Tags.xml has BOM at the start of the file
// The replace() removes the UTF-8 BOM.
// FIX: Not elegant, but works for now
val lines = readFile(filename)
val xml = scala.xml.XML.loadString(
lines.replace("\u00EF\u00BB\u00BF", ""))
println(xml + EOL)
}
def readFile(filename: String): String = {
val bufferedSource = io.Source.fromFile(filename)
val lines = bufferedSource.mkString
bufferedSource.close
return lines
}
}
Шестнадцатеричное отображение входных данных (всего три строки). Обратите внимание, что первые три байта - это спецификация UTF-8:
0000: EF BB BF 3C 3F 78 6D 6C - 20 76 65 72 73 69 6F 6E ...<?xml - version
0010: 3D 22 31 2E 30 22 20 65 - 6E 63 6F 64 69 6E 67 3D = "1.0" e - ncoding=
0020: 22 75 74 66 2D 38 22 3F - 3E 0D 0A 3C 74 61 67 73 "utf-8"? - >..<tags
[РЕДАКТИРОВАТЬ 20.08.2018 с последней попыткой]
Я изменил readFile, чтобы использовать apache.commons BOMInputStream, и это работает. Однако у меня нет опыта работы с этой библиотекой и ее влияния на мой код (Apache Spark).
import java.io.FileInputStream
import java.io._
import org.apache.commons.io.input.BOMInputStream
def readFile(filename: String): String = {
val inStream = new FileInputStream(filename)
val content = io.Source.fromInputStream(
new BOMInputStream(inStream)).mkString
inStream.close()
content
}
Спасибо. Теперь добавим тесты для проверки нового кода.
Для тех из вас, кто следит за этим потоком, в следующие несколько дней я собираюсь довольно глубоко изучить, как Unicode и текстовые файлы загружаются в память в виде байтовых массивов и строк. Я опубликую свои результаты, как только завершу это. Я считаю, что bufferedSource.mkString должен был обработать этот случай. Теперь узнаем, что он поддерживает, а что не поддерживает. То же самое и для BOMInputStream. Возможно, проблема заключается в scala.xml.XML.loadString и его обработке Unicode.
Тестовые файлы, которые я использую, взяты из дампов данных StackOverflow. archive.org/download/stackexchange





Я бы пошел с вашим использованием BOMInputStream, он разработан для вашего варианта использования - apache.commons.io на самом деле является зависимостью для Spark-core, а также многих других библиотек - mvnrepository.com/artifact/commons-io/commons-io/usages