在 JavaFX 音乐播放器应用程序中使用 VLCJ 检索元数据时,我遇到了编码外来字符的问题。
这是我在准备和解析媒体后用于获取媒体元数据(例如标题和专辑)的代码:
@Override
public void mediaPlayerReady(MediaPlayer mediaPlayer) {
long length = mediaPlayer.status().length();
String formattedTotalDuration = StringFormatter.formatDuration(Duration.millis(length));
MetaApi meta = mediaPlayer.media().meta();
Platform.runLater(() -> {
playbackController.setLblDuration(formattedTotalDuration);
playbackController.setLblSongName(meta.get(Meta.TITLE));
playbackController.setLblSongArtist(meta.get(Meta.ARTIST));
playbackController.setLblSongAlbum(meta.get(Meta.ALBUM));
playbackController.setCoverArt(new Image(meta.get(Meta.ARTWORK_URL)));
});
}
当尝试显示包含日语等语言字符的标题、艺术家和专辑时,问题就会出现。例如,对于标题为“01.私と浪漫ていすと”的歌曲,
meta.get(Meta.TITLE)
会在控制台上返回�?�?�浪漫�?��?��?��?�,并显示为
。相反,不包含外来字符的文本会被正确处理,如图 。
我想知道是否有任何方法可以确保MetaAPI返回的文本编码正确。我尝试过设置以下系统属性
System.setProperty("file.encoding", "UTF-8");
以及手动将 UTF-8 编码应用于 meta.get(Meta.TITLE)
,但都没有成功。也许问题不在于编码?
我感谢任何指导或建议。
我的Java版本:21 VLCJ版本:4.8.2 Windows 11
更新:
我研究了如何按照 @Mike'Pomax'Kamermans 的建议检测文本编码。我将
meta.get(Meta.TITLE)
写入 txt 并使用 juniversalchardet 及其 UniversalDetector 获取其编码:
import org.mozilla.universalchardet.UniversalDetector;
import java.io.*;
import java.nio.charset.Charset;
public class StringEncodingConverter {
public static void main(String[] args) {
try {
// Detect text encoding
String filePath = "C:\\Users\\myUser\\Documents\\juniversalcharset\\data.txt";
Charset detectedCharset = detectCharset(filePath);
if (detectedCharset != null) {
System.out.println(detectedCharset.toString()); // <- Got 'UTF-8'
// Convert to Unicode
String unicodeText = convertToUnicode(filePath, detectedCharset);
System.out.println("Converted text:\n" + unicodeText);
} else {
System.out.println("Failed to detect text encoding.");
}
} catch (IOException e) {
}
}
private static Charset detectCharset(String filePath) throws IOException {
try (FileInputStream fis = new FileInputStream(filePath); BufferedInputStream bis = new BufferedInputStream(fis)) {
UniversalDetector detector = new UniversalDetector(null);
byte[] buf = new byte[4096];
int bytesRead;
while ((bytesRead = bis.read(buf)) > 0 && !detector.isDone()) {
detector.handleData(buf, 0, bytesRead);
}
detector.dataEnd();
String charsetName = detector.getDetectedCharset();
if (charsetName != null) {
return Charset.forName(charsetName);
}
}
return null;
}
private static String convertToUnicode(String filePath, Charset charset) throws IOException {
try (FileInputStream fis = new FileInputStream(filePath); InputStreamReader isr = new InputStreamReader(fis, charset); BufferedReader reader = new BufferedReader(isr)) {
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line).append("\n");
}
return result.toString();
}
}
}
原来MediaAPI返回的文本已经是UTF-8了。正如预期的那样,将其转换为 UTF-8 没有任何区别。不幸的是,从
meta.get()
取出一个字符串并将其直接传递给 UniversalDetector 给出了相同的结果。我根本不是专家,但这让我相信元数据本身及其处理方式可能有问题。
更新2
我忘记说了,我之前曾经使用jaudiotagger-3.0.1从歌曲中获取元数据,并且效果符合预期。我转而使用 VLCJ 的 MetaAPI,试图使我的项目更具凝聚力并减少依赖项数量,此外还通过避免为每首歌曲创建 File 实例来提高性能。在最坏的情况下,我可能会重新使用它。
我要向所有评论并指导我找到解决方案的人表示感谢。 @Slaw 指出了 vlcj 存储库上的一个 GitHub 问题,其中另一个用户在字幕描述方面遇到了类似的问题。他们发现乱码的来源是native-streams的版本,这似乎是jna的依赖。
在查看了 caprica 的 vlcj 播放器之后,我尝试通过播放与之前相同的歌曲并在状态面板中显示其标题来复制当前问题。如您所见,私と浪漫ていすと已正确渲染。鉴于这些库是我的项目中看似损坏的文本的潜在来源,我抓住了:
jna-5.5.0.jar
jna-platform-5.12.1.jar
native-streams-2.0.0.jar
vlcj-4.8.0.jar
vlcj-natives-4.8.0.jar
来自 vlcj-player 并替换了我以前使用的那些(我想补充一点,我是从这个页面下载的)。事后看来,这不是一个谨慎的决定。
编译并运行我的项目后,之前无法理解的文本成功呈现。
总之,我在这里学到的教训是从官方来源获取我使用的库。我想再次对大家的帮助表示感谢;我自己无法解决这个问题。