java 处理换行符_Java 文件换行符识别与转换
项目经验,如需转载,请注明作者: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:
查看 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 工程,编写一个控制台应用,测试以上代码:
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 换行符为:
Notepad 显示所有符号方法:
测试结果:
转换文件换行符
读出新文件换行符,若与原文件换行符不一致,则新建一临时文件,逐行写入原文件内容,并在行尾写入原文件换行符,然后删除原文件,重命名临时文件:
// 此处省略 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());
}
}
复制代码
测试结果:
总结
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 流关闭后执行
java 处理换行符_Java 文件换行符识别与转换相关推荐
- linux文件描述符泄漏,文件描述符(fd)泄漏排查一篇就够了
生产多次遇到文件描述符(fd)泄露相关的问题, 文件描述符泄漏一般引起 的现象是文件句柄数(封面图)/tcp alloc(上图)增长.文章分为两部分介绍文件描述符相关内容,第一部分介绍文件描述基础知识 ...
- java i o中文版_Java文件I/O的三种方法
摘要:之前在面试中被问到过两次Java中文件读入输出怎么写,当时只记得一个大概,没有办法很清晰的说出一个条理,今天特地看出总结了一下这方面的内容,想要写出来给大家分享.首先文件读入输出流常用有三种:F ...
- java输入输出换行程序_java文件输出换行问题。
我想把程序处理的数据输出到文件中,而且是一行一个数据,比如:张三男十岁但是我在输出流中用\n不行,用\r\n也不行(文本文档),但是用\n输入到word文档里就可以实现换行.但是我又想... 我想把程 ...
- java final修饰符_java final修饰符详解,final修饰方法
之前给大家讲过java final修饰符final修饰变量方面的知识,那么下面要继续给大家讲到的就是final修饰方法方面的知识,一起来了解一下吧. final修饰的方法不能被重写,假如因为一些原因, ...
- java的final修饰_java final 修饰符详解
final修饰符究竟有什么作用,我们该如何使用,对我们的应用开发又能够起到什么作用,有java基础的肯定是不难说出final的几个用法, 1.被final修饰的变量在首次被初始化之后是不能够再次被赋值 ...
- java访问修饰符_Java访问修饰符
java访问修饰符 Java access modifiers are used to provide access control in java. Java provides access con ...
- java 连接 sftp失败_java – 文件上传到SFTP失败(Apache VFS)
我有一个SFTP问题( Windows WinSSHD).我尝试用 Apache Commons VFS在一个文件夹中写一个文件.在本地SFTP上我没有上传的问题,但在第二个SFTP上我总是得到以下错 ...
- java复制和上传_java文件上传复制等功能
package com.sitech.message.controller.task; import java.io.File;//引入类 import java.io.FileInputStream ...
- java上传下载_Java文件上传与文件下载实现方法详解
本文实例讲述了Java文件上传与文件下载实现方法.分享给大家供大家参考,具体如下: Java文件上传 数据上传是客户端向服务器端上传数据,客户端向服务器发送的所有请求都属于数据上传.文件上传是数据上传 ...
最新文章
- 安装 Enthought Tool Suite 时遇到的问题
- 计算机网络第四章-网络层复习笔记
- FOI冬令营 Day 3
- form表单多文件上传
- IBATIS的优缺点
- jQuery验证框架教程
- 如何下载谷歌地图高程数据
- CImage不失真缩放显示图片
- 游戏测试-笔试/面试(一)
- Miracle2.1 列表页面显示附件链接
- ssm框架访问数据库一直在转圈(请求)
- JAVA菜鸟驿站快递分发系统计算机毕业设计Mybatis+系统+数据库+调试部署
- 日志服务与日志分析工具
- rpm 安装MySQL8
- python多光谱遥感数据处理、图像分类、定量评估及机器学习方法
- 电子信箱怎么样注册?邮箱格式怎么写?
- 文件传输助手——自同步、使用方法
- 索尼IMX219图像传感器
- 应届生毕业就失业?这该怎么办
- eas 税率修改_关于调整增值税税率的通知