Java写入质数文件用Notepad打开乱码,加空格后正常,求原因
为什么Notepad打开Java写入的含
\n的文本文件会出现乱码,加空格就正常? 这个问题本质是Windows记事本的自动编码检测逻辑在搞鬼,结合你写入的内容特征,才出现了这种看似奇怪的乱码现象。我给你拆解一下:
1. 你的代码写入的内容是什么?
你用bufferedWriter.write(i + "\n");把质数转成字符串后,加上单个换行符\n(ASCII码0x0A)写入文件。默认情况下,FileWriter会用系统默认的单字节编码(比如Windows上的GBK,或者UTF-8)写入,所以每个数字字符、每个\n都是1字节的ASCII数据。
比如质数5会被写成两个字节:0x35(字符'5') + 0x0A(换行符)。
2. Notepad为什么会把它解析成乱码?
Windows记事本打开无BOM(字节顺序标记)的文件时,会自动猜测编码:
- 当文件里只有数字和
\n这种单字节ASCII字符时,它的字节序列很容易被误判为UTF-16LE编码(Windows默认的双字节Unicode编码)。 - UTF-16LE是用两个字节表示一个字符的,刚才的
0x35 0x0A这两个字节,在UTF-16LE里会被解析成Unicode字符U+0A35——就是你看到的那个类中文的象形字符。大量这种双字节组合堆积起来,就形成了你看到的乱码。
3. 加空格为什么就正常了?
当你在换行前加个空格,写入的内容变成数字 + " " + "\n",比如质数5对应的字节是0x35('5') + 0x20(空格) + 0x0A(换行)。
空格的字节0x20是ASCII里最常见的字符之一,Notepad的编码检测逻辑会因为这个字节的存在,判断文件更符合单字节的ANSI/UTF-8编码特征,从而用正确的编码解析内容,自然就显示正常了。
额外补充:换行符的影响
你写入的是Linux风格的\n换行,而Windows记事本默认期望的是\r\n(CRLF,0x0D 0x0A)。虽然这不会直接导致乱码,但这种非标准换行也会让Notepad的编码检测逻辑更“困惑”,进一步增加误判的概率。
解决方法
给你几个靠谱的解决方案,比加空格更根本:
- 用Windows兼容的换行符:把
\n改成\r\n,既解决换行问题,也能减少编码误判:bufferedWriter.write(i + "\r\n"); - 明确指定编码并添加BOM:强制用UTF-8写入并添加BOM,让Notepad直接识别编码:
import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.io.IOException; public class Primes { public static void main(String args[]) { try { // 指定UTF-8编码,并写入BOM OutputStreamWriter writer = new OutputStreamWriter( new FileOutputStream("PrimeNumbers.txt", true), StandardCharsets.UTF_8 ); writer.write('\uFEFF'); // 写入UTF-8 BOM BufferedWriter bufferedWriter = new BufferedWriter(writer); for (int i = 5; i <= 10000000; i += 2) { boolean a = true; for (int o = 3; o < ((i / 3) + 1); o += 2) { if (i % o == 0) { a = false; o = i; } } if (a) { bufferedWriter.write(i + "\r\n"); } } bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } }
你的原始代码
import java.util.ArrayList; import java.util.Arrays; import java.io.FileWriter; import java.io.BufferedWriter; import java.io.IOException; public class Primes { public static void main(String args[]) { try { FileWriter writer = new FileWriter("PrimeNumbers.txt", true); BufferedWriter bufferedWriter = new BufferedWriter(writer); for (int i = 5; i <= 10000000; i += 2) { boolean a = true; for (int o = 3; o < ((i / 3) + 1); o += 2) { if (i % o == 0) { a = false; o = i; } } if (a == true) { bufferedWriter.write(i + "\n"); } } bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } }
乱码示例
ਵㄱㄊਲ਼㜱ㄊਹ㌲㈊ਹㄳ㌊ㄴ㐊ਲ਼㜴㔊ਲ਼㤵㘊㜶㜊㌷㜊ਹ㌸㠊ਹ㜹ㄊㄊ㌰ㄊ㜰ㄊ㤰ㄊ㌱ㄊ㜲ㄊㄳㄊ㜳ㄊ㤳ㄊ㤴ㄊㄵㄊ㜵ㄊ㌶ㄊ㜶ㄊ㌷ㄊ㤷ㄊㄸㄊㄹㄊ㌹ㄊ㜹ㄊ㤹㈊ㄱ㈊㌲㈊㜲㈊㤲㈊㌳㈊㤳㈊ㄴ㈊ㄵ㈊㜵㈊㌶㈊㤶㈊ㄷ㈊㜷㈊ㄸ㈊㌸㈊㌹㌊㜰㌊ㄱ㌊㌱㌊㜱㌊ㄳ㌊㜳㌊
内容的提问来源于stack exchange,提问作者bdusek
相关产品推荐
相关产品推荐

