今天一个同事向我反映,说她的一段JAVA代码,如果输出的文件后缀是.idx, 则写入的换行符会丢掉,从Editplus中看到所有内容都出现在一行。 我感到很奇怪,文件名和后缀会影响流的内容?这明显不可能 ,难道真的碰到灵异事件? 于是按照如下过程调试并解决问题: 1、写独立测试代码 首先要验证这个问题不是JAVA自身的问题,当即写了测试代码:

import

    
     java.io.BufferedWriter;


    
    import

    
     java.io.File;


    
    import

    
     java.io.FileWriter; 



    
    public

    
     

    
    class

    
     TestIdx {
    

    
    public

    
     

    
    static

    
     

    
    void

    
     main(String[] args) 

    
    throws

    
     Exception{
       File f

    
    =

    
    new

    
     File(

    
    "

    
    d://test.idx

    
    "

    
    );
       BufferedWriter w

    
    =

    
    new

    
     BufferedWriter(

    
    new

    
     FileWriter(f));
       w.write(

    
    "

    
    abc

    
    "

    
    );
       w.write(

    
    "

    
    /n

    
    "

    
    );
       w.write(

    
    "

    
    123

    
    "

    
    );
       w.flush();
       w.close();
    }
}

运行后,用UltraEdit打开结果文件,没问题。 同事说,她直接用的FileWriter,于是稍作修改,再测,没问题。 同事又说,她的文件用追加模式打开,再改,再测,还是没有问题。 2、重现问题 感到有些不可思议,于是到同事机器上查看。 发现确实有此现象。 3、代码走读 查看代码,没发现特别之处。 4、做局部替换,尝试定位问题 通过修改输出文件名、文件后缀,通过多次尝试,发现问题不是出在.idx后缀上, 因为任意新创建的文件均无此问题,但如果继续向她机器上已经存在的log.idx上追加就不行。 5、清理环境后尝试重现问题 既然问题与特定文件相关,则删除该奇怪文件(删前先做备份,待问题解决后追究根源), 重新运行程序生成新的同名文件,问题没有再重现。 那么,问题的根本原因肯定在此文件内。 6、追根溯源 我要求同事将log.idx文件发给我,我用UltraEdit打开,发现换行正确, 而同事机器上用Editplus打开同一个文件则换行不正确。 于是又找到一个用Editplus的同事,打开该文件,换行也不正确。 因此,可以说明,文件本身没有大问题,问题在于文本编辑器对文本中的换行的处理方式不一致。 进一步用Ultraedit的二进制模式研究该文本文件, 发现该文本文件存在两种换行格式:某些行之间是windows的“/r/n”,而某些行之间是unix的“/n”。 初步断定这是造成差异的原因,Editplus对存在两种回车制式的文件,可能只识别一种。 7、验证猜测 在Ultraedit中新建空白文本文件,输入:

123 
 456 
 789 
 在UE中切换到二进制模式,显示为: 
00000000h: 31 32 33 0D 0A 34 35 36 0D 0A 37 38 39          ; 123..456..789 
 用Editplus打开,正常显示为三行 

 在UE二进制模式下,删除第二个0D,变成: 
00000000h: 31 32 33 0D 0A 34 35 36 0A 37 38 39          ; 123..456.789 
 用Editplus打开,后面的回车不识别,显示为两行: 
123 
 456789  再删除第一个0D,变成: 
00000000h: 31 32 33 0A 34 35 36 0A 37 38 39          ; 123.456.789 
 用Editplus打开,正常显示为三行 
123 
 456 
 789 

 再恢复第二个0D,变成: 
00000000h: 31 32 33 0A 34 35 36 0D 0A 37 38 39          ; 123.456..789 
 用Editplus打开,前面的回车不识别,显示为两行: 
123456 
 789

8、结论 Editplus在判断文本文件换行方面, 当文本文件中仅存在一种换行格式的时候(无论/r/n还是/n),Editplus都能正确识别 当文本文件中存在两种换行格式的时候,以/r/n优先,单纯的/n被忽略。 9、造成此现象的过程 该同事第一版代码向文件中追加的换行符为“/r/n“,后来改成”/n“,但没有删除原来的文件, 而文件写入方式为追加,导致文件中出现两种换行格式。 可能有些人在第六步完成后就停住,而我喜欢的是后面三步。

 

补充结论:

bao110908 回帖详细解释Editplus对换行的处理机制:

EditPlus 有个文件格式,用于区分三种换行符之一。 一、/r/n 与 /n 混合(即 PC 与 Unix 换行混合) 1,如果文本中 /r/n 的数量大于 /n 的数量,那么就以 PC 的 /r/n 方式来显示,这时 /n 并不能显示成为一个新行,而是成为一个不可显字符; 2,如果文本中 /r/n 的数量小于 /n 的数量,那么就以 Unix 的 /n 方式来显示,这时 /r/n 中的 /r 成为一个不可显字符,而 /r 后面的 /n 进行换行; 3,如果文本中 /r/n 的数量与 /n 的数相相同,那么就优先采用 /r/n 方式来显示,这时单独的 /n 成为一个不可显字符。 二、/n 与 /r 混合(即 Unix 与 Mac 换行混合) 1,如果文本中 /n 的数量大于 /r 的数量,那么就以 Unix 的 /n 方式进行换行,这时 /r 成为一个不可显字符; 2,如果文本中 /n 的数量小于 /r 的数量,那么就以 Mac 的 /r 方式进行换行,这时 /n 成为一个不可显字符; 3,如果文本中 /n 与 /n 的数量一样多,就优先以 Unix 的 /n 方式进行换,同时 /r 成为一个不可显字符。 三、/r/n 与 /r 混合(即 PC 与 Mac 换行混合) 1,如果文本中 /r/n 的数量大于 /r 的数量,那么就以 PC 的 /r/n 方式进行换行,这时 /r 成为一个不可显字符; 2,如果文本中 /r/n 的数量小于 /r 的数量,那么就以 Mac 的 /r 方式进行换行,/r/n 其中的 /r 成为换行符,后面的 /n 成为一个不可显字符; 3,如果文本中 /r/n 与 /r 的数量一样多,就优先以 PC 的 /r/n 方式进行换,单独的 /r 成为一个不可显字符。 四、/r/n、/n 与 /r 混合(即 PC、Unix、Mac 换行混合) 1,这三种换行哪种换行多就采用哪种方式; 2,如果三种换行数量或两种换行数量相同时,以 /r/n、/n、/r 的优先顺序确定换行模行。 实验工具 文本显示:EditPlus 3.00(254)beta 二进制修改:PSPad 4.5.3(2298)