Java使用FileReader读取ASCII文件时特殊字符丢失问题求助
ASCII转EBCDIC时特殊二进制字符丢失的解决方案
问题根源
你用FileReader或指定UTF-8编码的InputStreamReader读取文件时,本质是按字符编码解析字节。文件中第486-498位的二进制内容(非可打印ASCII字符)无法被UTF-8或系统默认编码识别,会被自动替换为�这类占位符,导致原始字节信息丢失,后续转换自然出错。
解决思路
必须直接读取文件的原始字节流,完整保留所有内容;再区分ASCII文本区域和二进制区域,分别处理:ASCII部分按编码映射转换为EBCDIC,二进制部分直接保留原始字节,最后合并输出。
具体实现代码
import java.io.ByteArrayOutputStream; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; // 读取文件全部原始字节 byte[] rawBytes = Files.readAllBytes(Paths.get(sourceFile.getAbsolutePath())); // 拆分字节区域(注意:以下下标基于1-based位置转换为0-based数组索引,需根据实际情况调整) byte[] asciiSection1 = Arrays.copyOfRange(rawBytes, 0, 485); // 第1-485位(ASCII文本) byte[] binarySection = Arrays.copyOfRange(rawBytes, 485, 498); // 第486-498位(二进制内容) byte[] asciiSection2 = Arrays.copyOfRange(rawBytes, 498, rawBytes.length); // 第499位到末尾(ASCII文本) // 定义编码:ASCII和目标EBCDIC编码(IBM037是常用EBCDIC编码,可根据需求替换) Charset asciiCharset = Charset.forName("US-ASCII"); Charset ebcdicCharset = Charset.forName("IBM037"); // 转换ASCII区域到EBCDIC byte[] ebcdicSection1 = new String(asciiSection1, asciiCharset).getBytes(ebcdicCharset); byte[] ebcdicSection2 = new String(asciiSection2, asciiCharset).getBytes(ebcdicCharset); // 合并所有区域:转换后的ASCII + 原始二进制 + 转换后的ASCII ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); outputStream.write(ebcdicSection1); outputStream.write(binarySection); outputStream.write(ebcdicSection2); // 写入输出文件 Files.write(Paths.get(outputFile.getAbsolutePath()), outputStream.toByteArray());
关键说明
- 字节流读取:
Files.readAllBytes直接读取文件原始字节,不会对任何内容做编码解析,确保二进制信息完整保留。 - 编码转换边界:如果你的ASCII-EBCDIC转换工具(CharFormatConverter.java)有自定义映射逻辑,可替换上述代码中
new String(...).getBytes(...)的部分,用工具处理ASCII区域的转换。 - 位置校验:务必确认文件位置是1-based还是0-based,避免拆分区域时出现偏移错误。
内容的提问来源于stack exchange,提问作者Edisson Gabriel López
相关产品推荐
相关产品推荐

