Java中将UTF-8日文全角字符ー转SHIFT_JIS时出现乱码问题
问题原因
你代码里的字符-是Unicode的U+2014(EM DASH,中文破折号),而非SHIFT_JIS编码817C对应的U+30FC(全角长音符号「ー」)。由于U+2014不在SHIFT_JIS的字符映射范围内,Java的OutputStreamWriter编码时会将无法映射的字符默认替换为?(十六进制3F)。
解决方法
有两种可行处理方式:
1. 替换目标字符(推荐)
将字符串中的中文破折号替换成全角长音符号,再执行编码:
public class ShiftJisTest { public static void main(String[] args) { String text = "東1-1"; // 替换中文破折号为日语全角长音符号 String convertedText = text.replace('-', 'ー'); try (BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream("output_data"), "SHIFT_JIS"))) { writer.write(convertedText); } catch (IOException e) { e.printStackTrace(); } } }
运行后输出的十六进制为93 8C 82 50 81 7C 82 50,完全符合预期。
2. 指定编码错误处理策略(仅用于校验场景)
若需严格校验编码合法性,可设置CharsetEncoder的错误处理规则,遇到无法编码的字符直接抛出异常(而非替换为?):
import java.io.*; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CodingErrorAction; public class ShiftJisTest { public static void main(String[] args) { String text = "東1-1"; Charset shiftJis = Charset.forName("SHIFT_JIS"); CharsetEncoder encoder = shiftJis.newEncoder() .onMalformedInput(CodingErrorAction.REPORT) .onUnmappableCharacter(CodingErrorAction.REPORT); try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("output_data"), encoder); BufferedWriter bw = new BufferedWriter(writer)) { bw.write(text); } catch (IOException e) { e.printStackTrace(); } } }
此方式会抛出CharacterCodingException,明确提示无法编码U+2014,适合需要严格控制字符编码的场景。
额外说明
- SHIFT_JIS字符集范围有限,仅覆盖日语常用字符及部分符号,中文破折号、英文长破折号等字符不在其映射表内。
- 从数据库读取文本时,需确认存储的字符为日语标准全角长音符号U+30FC,避免混入类似字符导致编码失败。
内容的提问来源于stack exchange,提问作者Prince
相关产品推荐
相关产品推荐

