java 处理换行符_Java 文件换行符识别与转换

java 处理换行符_Java 文件换行符识别与转换项目经验 如需转载 请注明作者 Yuloran t cn EGU6c76 背景项目开发需要手动合入几十种语言的翻译到 string xml 中 这是一件非常痛苦的事情 Copy Paste Copy Paste Copy Paste 人都快疯了 被逼无奈写了个自动替换翻译的工具 原理很简单 解析 Excel 中的翻译 替换到 Xml 中 Excel 解析用 jxl jar Xml 解析与修改

项目经验,如需转载,请注明作者:Yuloran (t.cn/EGU6c76)

背景

项目开发需要手动合入几十种语言的翻译到 string.xml 中,这是一件非常痛苦的事情:Copy、Paste,Copy、Paste,Copy、Paste… 人都快疯了!被逼无奈写了个自动替换翻译的工具,原理很简单:解析 Excel中的翻译,替换到 Xml 中。Excel 解析用 jxl.jar,Xml 解析与修改用 DOM,一顿操作,一天就写完了!正高兴呢,赶紧使用 git diff 查看修改对比,一看坏事了:“坑爹呢!这特么根本不能用好嘛!原文件的每一行都被识别成了新行(因为换行符变了),这代码还怎么审核?鬼知道你改了什么!” 所以,本文记录如何使用 Java 识别与转换文件换行符。

文件换行符分类

Intellij>File>Line Separators:

2dc63ae60dbdc8204c9d32176f0eb51e.png

查看 ASCII 码表:

\r(CR (carriage return)):十六进制为 0x0D

\n(LF (NL line feed, new line)):十六进制为 0x0A

Windows 换行符:\r\n,回车键+换行键;

Linux 换行符:\n,换行键;

Mac 换行符:\r,回车键。

没有换行符:文件的最后一行可以没有换行符

识别文件符

按行读取文件,然后再分别读出接下来的两个字节,判断其 int 值:

package com.yuloran.util;

import java.io.EOFException;

import java.io.File;

import java.io.IOException;

import java.io.RandomAccessFile;

public final class LineSeparatorHelper{

public enum LINE_SEPARATOR {

WINDOWS, LINUX, MAC, UNKNOWN

}

private LineSeparatorHelper(){

}

public static LINE_SEPARATOR getLineSeparator(File f) throws IllegalArgumentException{

if (f == null || !f.isFile() || !f.exists()) {

throw new IllegalArgumentException(“file must exists!”);

}

RandomAccessFile raf = null;

try {

raf = new RandomAccessFile(f, “r”);

String line = raf.readLine();

if (line == null) {

return LINE_SEPARATOR.UNKNOWN;

}

// 必须执行这一步,因为 RandomAccessFile 的 readLine() 会自动忽略并跳过换行符,所以需要先回退文件指针位置

// “ISO-8859-1” 为 RandomAccessFile 使用的字符集,此处必须指定,否则中文 length 获取不对

raf.seek(line.getBytes(“ISO-8859-1”).length);

byte nextByte = raf.readByte();

if (nextByte == 0x0A) {

return LINE_SEPARATOR.LINUX;

}

if (nextByte != 0x0D) {

return LINE_SEPARATOR.UNKNOWN;

}

try {

nextByte = raf.readByte();

if (nextByte == 0x0A) {

return LINE_SEPARATOR.WINDOWS;

}

return LINE_SEPARATOR.MAC;

} catch (EOFException e) {

return LINE_SEPARATOR.MAC;

}

} catch (IOException e) {

e.printStackTrace();

} finally {

if (raf != null) {

try {

raf.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

return LINE_SEPARATOR.UNKNOWN;

}

}

复制代码

使用 Intellij 创建一个 Java 工程,编写一个控制台应用,测试以上代码:

226a87bee10c284f5a8039f998770272.png

package com.yuloran;

import com.yuloran.util.LineSeparatorHelper;

import java.io.File;

public class Main{

public static void main(String[] args){

File f = new File(“test.txt”);

System.out.println(“line separator: ” + LineSeparatorHelper.getLineSeparator(f).name());

}

}

复制代码

test.txt 的换行符通过 File>Line Separators 进行切换,换行符符号可用 Notepad 查看,比如Windows 换行符为:

2bff0afa40c005bcf4666b74fe8a30a1.png

Notepad 显示所有符号方法:

e4913ba6bf0069b2e8fbaeadcc939cd8.png

测试结果:

68b2e9c67c9dead41a1c3245edbf1fe0.png

转换文件换行符

读出新文件换行符,若与原文件换行符不一致,则新建一临时文件,逐行写入原文件内容,并在行尾写入原文件换行符,然后删除原文件,重命名临时文件:

// 此处省略 LineSeparatorHelper 类其他代码…

@SuppressWarnings(“ResultOfMethodCallIgnored”)

public static boolean convert(LINE_SEPARATOR oldLs, File f, String charset){

if (oldLs == null || oldLs == LINE_SEPARATOR.UNKNOWN) {

return false;

}

if (f == null || !f.isFile() || !f.exists()) {

return false;

}

if (charset == null || charset.isEmpty()) {

charset = “UTF-8”;

}

LINE_SEPARATOR newLs = getLineSeparator(f);

if (newLs == oldLs) {

return false;

}

File temp = new File(f.getParent(), “temp.txt”);

if (temp.exists()) {

temp.delete();

}

BufferedReader br = null;

BufferedWriter bw = null;

try {

br = new BufferedReader(new InputStreamReader(new FileInputStream(f), charset));

bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(temp), charset));

String line;

int lineNumber = 0;

while ((line = br.readLine()) != null) {

if (lineNumber != 0) {

switch (oldLs) {

case WINDOWS:

bw.append(‘\r’).append(‘\n’);

break;

case LINUX:

bw.append(‘\n’);

break;

case MAC:

bw.append(‘\r’);

break;

default:

}

}

bw.write(line);

++lineNumber;

}

return true;

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

if (br != null) {

br.close();

}

if (bw != null) {

bw.close();

}

} catch (IOException e) {

e.printStackTrace();

}

f.delete();

temp.renameTo(f);

}

return false;

}

复制代码

测试代码:

package com.yuloran;

import com.yuloran.util.LineSeparatorHelper;

import java.io.File;

public class Main{

public static void main(String[] args){

File f = new File(“test.txt”);

System.out.println(“original line separator: ” + LineSeparatorHelper.getLineSeparator(f).name());

LineSeparatorHelper.convert(LineSeparatorHelper.LINE_SEPARATOR.WINDOWS, f, “UTF-8”);

System.out.println(“new line separator: ” + LineSeparatorHelper.getLineSeparator(f).name());

}

}

复制代码

测试结果:

f10a7b83ba841f9aebb34827f83142ac.png

85d39fb422ec457b5a01febf764760f3.png

13b74ed9430594e2c251c040268e5aa6.png

总结

RandomAccessFile 以 “ISO-8859-1” 编码方式读取一行,获取字节数时,须指定该编码方式

RandomAccessFile 读取一行后,文件指针指向下一行开头,跳过了换行符所占的字节位置,读取换行符时须回退文件指针位置

没有字节可读时,调用 readByte() 会抛出 EOFException:public final byte readByte() throws IOException{

int ch = this.read();

if (ch < 0)

throw new EOFException();

return (byte)(ch);

}

复制代码

重命名文件、删除文件须在 IO 流关闭后执行

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232865.html原文链接:https://javaforall.net

(0)
上一篇 2025年9月4日 下午6:01
下一篇 2025年9月4日 下午6:22


相关推荐

  • 永恒之蓝漏洞入侵_永恒之蓝漏洞探测

    永恒之蓝漏洞入侵_永恒之蓝漏洞探测一、基础知识介绍:1.何为永恒之蓝?永恒之蓝(EternalBlue)爆发于2017年4月14日晚,是一种利用Windows系统的SMB协议漏洞来获取系统的最高权限,以此来控制被入侵的计算机。甚至于2017年5月12日,不法分子通过改造“永恒之蓝”制作了wannacry勒索病毒,使全世界大范围内遭受了该勒索病毒,甚至波及到学校、大型企业、政府等机构,只能通过支付高额的赎…

    2022年10月17日
    6
  • CTK通用插件使用

    CTK通用插件使用1.把release版本和debug版本的CTK库文件拷贝到QT的bin目录下2.把release版本下的CTKWidgetsPlugins拷贝到qtplugins目录下Qtdesigner中就可以看到集成的CTK通用插件了3.建立一个qtgui程序,设置ctk的链接目录设置CTK的dll目录设置CTK的头文件目录设置CTK的lib路径4….

    2022年6月5日
    33
  • 龙虾、扣子、n8n、skills、RPA……都不重要

    龙虾、扣子、n8n、skills、RPA……都不重要

    2026年3月14日
    3
  • 【转载】关于C#静态构造函数的几点说明

    【转载】关于C#静态构造函数的几点说明

    2021年11月20日
    42
  • 求三角形面积——C语言

    求三角形面积——C语言C 语言 利用海伦公式求三角形面积代码如下 include stdio h include math h voidmain floata b c p doubleS printf 请输入三边长度 n scanf f f f amp a amp b amp c if a b gt c amp amp b c gt a amp amp a c gt b p a b c 2 S sq math h stdio h

    2026年3月19日
    2
  • python新手怎么兼职-利用python兼职[通俗易懂]

    python新手怎么兼职-利用python兼职[通俗易懂]广告关闭2017年12月,云+社区对外发布,从最开始的技术博客到现在拥有多个社区产品。未来,我们一起乘风破浪,创造无限可能。类似这种需求也在很多ppt兼职群(qq群搜索就可以查到)里能遇到,如果会python来自动批量操作ppt调整格式,那接单岂不是来者不拒?为了给大家增加一个赚钱的小机会,行哥这里给大家分享一下python操作ppt的用法用法大纲如下:?安装工具包首先用pip安装python…

    2022年6月11日
    60

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号