首页 > 其他分享 >更改文件导致MalformedInputException

更改文件导致MalformedInputException

时间:2024-07-18 10:12:25浏览次数:18  
标签:文件 MalformedInputException java 更改 snakeyaml boot springframework yaml org

1. 异常复现

工具及组件版本

IDE:IDEA 2023.3.2 (Ultimate Edition)

JDK:11

SpringBoot: 2.7.8

报错场景复现

编辑application.yml文件后,SpringBoot项目启动失败,报错java.nio.charset.MalformedInputException

错误信息如下:

org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 2
	at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:218)
	at org.yaml.snakeyaml.reader.StreamReader.ensureEnoughData(StreamReader.java:176)
	at org.yaml.snakeyaml.reader.StreamReader.ensureEnoughData(StreamReader.java:171)
	at org.yaml.snakeyaml.reader.StreamReader.peek(StreamReader.java:126)
	at org.yaml.snakeyaml.scanner.ScannerImpl.scanToNextToken(ScannerImpl.java:1218)
	at org.yaml.snakeyaml.scanner.ScannerImpl.fetchMoreTokens(ScannerImpl.java:329)
	at org.yaml.snakeyaml.scanner.ScannerImpl.checkToken(ScannerImpl.java:251)
	at org.yaml.snakeyaml.parser.ParserImpl$ParseImplicitDocumentStart.produce(ParserImpl.java:214)
	at org.yaml.snakeyaml.parser.ParserImpl.peekEvent(ParserImpl.java:166)
	at org.yaml.snakeyaml.parser.ParserImpl.checkEvent(ParserImpl.java:156)
	at org.yaml.snakeyaml.composer.Composer.checkNode(Composer.java:93)
	at org.yaml.snakeyaml.constructor.BaseConstructor.checkData(BaseConstructor.java:124)
	at org.yaml.snakeyaml.Yaml$1.hasNext(Yaml.java:509)
	at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:198)
	at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:166)
	at org.springframework.boot.env.OriginTrackedYamlLoader.load(OriginTrackedYamlLoader.java:88)
	at org.springframework.boot.env.YamlPropertySourceLoader.load(YamlPropertySourceLoader.java:50)
	at org.springframework.boot.context.config.StandardConfigDataLoader.load(StandardConfigDataLoader.java:54)
	at org.springframework.boot.context.config.StandardConfigDataLoader.load(StandardConfigDataLoader.java:36)
	at org.springframework.boot.context.config.ConfigDataLoaders.load(ConfigDataLoaders.java:108)
	at org.springframework.boot.context.config.ConfigDataImporter.load(ConfigDataImporter.java:128)
	at org.springframework.boot.context.config.ConfigDataImporter.resolveAndLoad(ConfigDataImporter.java:86)
	at org.springframework.boot.context.config.ConfigDataEnvironmentContributors.withProcessedImports(ConfigDataEnvironmentContributors.java:116)
	at org.springframework.boot.context.config.ConfigDataEnvironment.processWithProfiles(ConfigDataEnvironment.java:311)
	at org.springframework.boot.context.config.ConfigDataEnvironment.processAndApply(ConfigDataEnvironment.java:232)
	at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:102)
	at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:94)
	at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:102)
	at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEvent(EnvironmentPostProcessorApplicationListener.java:87)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
	at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:85)
	at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:66)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120)
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:114)
	at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:65)
	at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:343)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:301)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292)
	at com.test.monitor.MonitorApplication.main(Application.java:30)
Caused by: java.nio.charset.MalformedInputException: Input length = 2
	at java.base/java.nio.charset.CoderResult.throwException(CoderResult.java:274)
	at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:339)
	at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
	at java.base/java.io.InputStreamReader.read(InputStreamReader.java:185)
	at org.yaml.snakeyaml.reader.UnicodeReader.read(UnicodeReader.java:125)
	at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:183)
	... 43 common frames omitted

配置文件更改内容如下:

spring:
  cloud:
    nacos:
      discovery:
        # 测试服务器地址
        server-addr: 127.0.0.1:8848

2. 问题定位

由报错信息中的的MalformedInputException可知,这里是出现了编码问题,可能的选项有以下几种:

  1. 配置文件的格式有问题;
  2. 文件带了BOM,覆盖掉了默认的配置;
  3. 输入了编码错误的字符串,优先怀疑中文。

逐一排查,发现文件的格式没有问题,也没有BOM,推测是中文注释出了问题。

注释掉中文注释,不再报错。

解决临时问题,接下来需要找到根本原因。

我们继续从异常信息下手,可以看到org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:198)方法调用,这儿就是yaml文件解析为字符串的方法。该方法源码如下:

	private boolean process(MatchCallback callback, Yaml yaml, Resource resource) {
		int count = 0;
		try {
			if (logger.isDebugEnabled()) {
				logger.debug("Loading from YAML: " + resource);
			}
            // 这里完成了比特流到字符流的转换
			try (Reader reader = new UnicodeReader(resource.getInputStream())) {
				for (Object object : yaml.loadAll(reader)) {
					if (object != null && process(asMap(object), callback)) {
						count++;
						if (this.resolutionMethod == ResolutionMethod.FIRST_FOUND) {
							break;
						}
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Loaded " + count + " document" + (count > 1 ? "s" : "") +
							" from YAML resource: " + resource);
				}
			}
		}
		catch (IOException ex) {
			handleProcessError(resource, ex);
		}
		return (count > 0);
	}

可以看到代码中第8行完成了比特流到字符流的转换,debug模式下也正是这里出现了错误,通过截取resource.getInputStream()中的内容可知,注释中的中文果然出现了乱码。测试可知乱码的编码格式是gbk

那么为什么在编码格式不正确的时候,只要去掉英文字符就可以正常使用呢?

是因为配置中除了中文字符之外,配置之中的其他字符都属于ASCII码表中的字符,这部分字符在各种编码中都是固定不变的,所以即使是错误的编码也读取出了正确的信息。

注意:这里讲到是常见编码格式,例如UTF-16,UTF-16等因为长度原因是不兼容ASCII格式的。

那么进一步的,为什么IDE没有提示我文件编码信息错误呢?

进一步检查IDEA中的文件编码配置,路径”Settings-->File Encodings“。然后发现“Project Encoding”的编码里写着:<System Default: GBK>, 至此,真相大白。

IDE的项目编码为系统默认的GBK,覆盖了全局编码UTF-8格式,导致输入的字符都为GBK,但是IDE是可以正常识别该编码的。

编码相关知识参考博客 ASCII、Unicode、UTF-8、UTF-16、GBK、GB2312、ANSI等编码方式简析

3. 问题处理

  1. Project Encoding页面统一的编码改成UTF-8
  2. 给文件加上UTF-8格式的BOM也可以解决问题,增加之后再删除BOM可以避免自己更改编码错误的内容
  3. 将系统编码改为UTF-8,参考文档

4. 参考

[1] ASCII、Unicode、UTF-8、UTF-16、GBK、GB2312、ANSI等编码方式简析

标签:文件,MalformedInputException,java,更改,snakeyaml,boot,springframework,yaml,org
From: https://www.cnblogs.com/bloodcolding/p/18308824

相关文章

  • 2024-07-18 浅尝rollup-plugin-visualizer——文件打包分析体积大小
    前言:vite+vue项目rollup-plugin-visualizer:一个用于Rollup构建系统的插件,它能够生成可视化的报告,展示你的项目构建后的模块依赖关系和文件大小。仓库:https://github.com/btd/rollup-plugin-visualizer安装:yarnaddrollup-plugin-visualizer配置(vite.config.ts):import{......
  • 替代FTP的大文件、海量文件传输针对性解决方案
    许多企业有传输大文件、海量文件的需求,如影视制作与发行企业、软件与科技企业、医疗与健康机构、游戏开发企业、科研机构与教育机构、设计与建筑行业、跨国企业等等,可见大文件、海量文件的传输需求是比较广泛而普遍的。一般企业使用较多的方式是通过FTP传输,FTP因建设成本低、通......
  • 使用SecureCRT上传下载文件
    一、建立连接用SSH协议,22端口二、连接SFTP快捷键ALT+P​或者右键对话框,点击新建SFTP标签页三、设置目的地址3.1设置本地目录lcd本地目录 3.2远程目录cd远程目录 3.3上传方法put本地目录下的文件名/拖动文件至标签页3.4下载方法get远程目录下的文件名......
  • Linux介绍和文件管理
    Linux之父:LinuxTorvalds✔Linux目录:/bin:存放基础系统所需的命令/sbin:存放超级权限用户root的可执行命令/etc:存放系统程序或者一般工具的配置文件/dev:设备文件存储目录/proc:操作系统运行时,进程信息及内核信息/var:存放内容可能增长的文件(如日志)/tmp......
  • EtherCAT主站IGH-- 16 -- IGH之fsm_foe.h/c文件解析
    EtherCAT主站IGH--16--IGH之fsm_foe.h/c文件解析0预览一该文件功能`fsm_foe.c`文件功能函数预览二函数介绍1.`ec_fsm_foe_init`2.`ec_fsm_foe_clear`3.`ec_fsm_foe_exec`4.`ec_fsm_foe_success`5.`ec_fsm_foe_transfer`6.`ec_fsm_foe_err......
  • llama.cpp 转化 gguf 文件
    概览llama.cpp自带转化工具,把safetensor格式的模型文件转化为gguf格式,方便用cpu进行推理。需要注意的是,必须连带下载和safetensor格式相关的一些配置文件,故转化文件对准的是一个目录。但同时还要注意,有时模型作者为同一个模型保存了多种框架应用的模型文件,这些文件是......
  • Makefile-只修改了.h头文件,编译为什么不起作用
    Makefile-只修改了.h头文件,编译为什么不起作用?-腾讯云开发者社区-腾讯云(tencent.com) 不知道各位小伙伴是否碰到过这样的情况:一个.c文件include另一个.h头文件,使用Makefile来构建(编译)应用程序。第一次编译、执行,很正常!但是此时,如果修改了.h头文件,再次编译时,就出现......
  • gitee入门_如何上传文件
    前提条件:1,已经安装完git相关环境2,在gitee上已经创建完仓库1,初始化本地仓库在本地新建一个文件夹,点击鼠标右键,选择gitbash在打开后输入代码:gitinit2,同步文件打开gitee,选择自己的仓库,复制输入:gitremoteaddorigin此处粘贴然后再执行上述图片中的第二步第三步......
  • 【发现】_croc_轻松安全地在电脑之间拷贝文件
    https://schollz.com/tinker/croc6作者宣发了croc:一种快速、安全和简单的文件传输工具。传输文件的方式有很多种,而对这些方式来说最重要的是三点:快速安全简单(最重要)croc目的是做出满足这三点的传输工具。croc使用中继传输而不是上传再下载,提高传输速度。使用基于pake......
  • 使用Apache POI 处理Miscrosoft Office各种格式文件
    介绍ApachePOI是一个处理MiscrosoftOffice各种文件格式的开源项目。简单来说就是,我们可以使用POI在Java程序中对MiscrosoftOffice各种文件进行读写操作。一般情况下,POI都是用于操作Excel文件。ApachePOI的应用场景:●银行网银系统导出交易明细●各种业务系......